Sample Header Ad - 728x90

Problem printing the content of a waiting queue in Linux kernel

0 votes
1 answer
428 views
**Context:** Consider the following set of operations {A, B, C, D, E}: * (A) : On the read() function of my device driver, I add the calling thread to a wait queue wq if a driver's buffer buf is empty. More specifically, the calling thread is added to the queue via: wait_event_interruptible(wq, strlen(buf) > 0) * (B) : Similarly, on the ioctl() function of the driver, I add the calling thread to the same queue wq if the passed ioctl command is MY_IOCTL_X and if a driver's flag is_free == 0. Again, the calling thread is added to the waiting queue via: wait_event_interruptible(wq, is_free != 0) * (C) : On the driver's write() function, I pass the user-space content to buff, and call wake_up_interruptible(&wq), so that to wake up the thread put to 'sleep' in read(). * (D) : On the driver's ioctl() function, if the ioctl command is MY_IOCTL_Y, I set is_free = 1, and call wake_up_interruptible(&wq), in order to wake up the thread put to 'sleep' by ioctl(MY_IOCTL_X). * (E) : I've created a print_wait_queue() function to print the PIDs of the threads in the waiting queue. I call it before **and after** calling wake_up_interruptible() in operations C and D. The print function is implemented like this: void print_wait_queue(struct wait_queue_head* wq) { struct list_head *i, *tmp; pr_info("waiting queue: ["); list_for_each_safe(i, tmp, &(wq->head)) { struct wait_queue_entry* wq_item = list_entry(i, struct wait_queue_entry, entry); struct task_struct* task = (struct task_struct*) wq_item->private; pr_info("%d,", task->pid); } pr_info("]\n"); } **Problem:** The actual queueing and de-queueing seems to be working as intended, no issues here. However, the printing of the wait queue is not. Let's say I perform the operations described above, in this order: A -> B -> C -> D. This is what I get in the console (simplified output): 1. “waiting queue : [pid_1, pid_2]” // before calling wake_up_interruptible() on write() 2. “waiting queue : []” // after calling wake_up_interruptible() on write() (**I was expecting [pid_2]**) 3. “waiting queue : [pid_2]” // before calling wake_up_interruptible() on ioctl(MY_IOCTL_Y) 4. “waiting queue : []” // after calling wake_up_interruptible() on ioctl(MY_IOCTL_Y) As shown above, at print #2, the PID of the remaining thread - pid_2 - doesn’t show up in the PID list. Instead, I get an empty list. However, pid_2 shows up in the list before calling wake_up_interruptible() on ioctl(MY_IOCTL_Y) at print #3, as expected, indicating that pid_2 is actually kept in the waiting queue in-between prints #2 and #3. **Questions:** Why don’t I get [pid_2] at print #2 above, but then get it at #3? I’ve tried protecting the wait queue cycle in print_wait_queue() with a lock and it didn’t solve the printing issue. I've also confirmed that the address that the pointer I pass to print_wait_queue() always points to the same address.
Asked by fortune_pickle (101 rep)
Jan 30, 2022, 10:47 AM
Last activity: Feb 7, 2022, 12:45 AM