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
Last activity: Feb 7, 2022, 12:45 AM