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 queuewqif a driver's bufferbufis 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 queuewqif the passedioctlcommand isMY_IOCTL_Xand if a driver's flagis_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 tobuff, and callwake_up_interruptible(&wq), so that to wake up the thread put to 'sleep' inread().(D) : On the driver's
ioctl()function, if theioctlcommand isMY_IOCTL_Y, I setis_free = 1, and callwake_up_interruptible(&wq), in order to wake up the thread put to 'sleep' byioctl(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 callingwake_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):
- “waiting queue : [pid_1, pid_2]” // before calling
wake_up_interruptible()onwrite() - “waiting queue : []” // after calling
wake_up_interruptible()onwrite()(I was expecting [pid_2]) - “waiting queue : [pid_2]” // before calling
wake_up_interruptible()onioctl(MY_IOCTL_Y) - “waiting queue : []” // after calling
wake_up_interruptible()onioctl(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.