Memo
Memo

Reputation: 469

Linux kernel - wait queues

I'm reading "Linux kernel development 3rd edition by Robert Love" to get a general idea about how the Linux kernel works..(2.6.2.3)

I'm confused about how wait queues work for example this code:

    /* ‘q’ is the wait queue we wish to sleep on */ 
DEFINE_WAIT(wait);
add_wait_queue(q, &wait); 

while (!condition) { /* condition is the event that we are waiting for */
    prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE); 
    if (signal_pending(current))
        /* handle signal */ 
      schedule();
    }

finish_wait(&q, &wait);

I just want to know in what context is this loop running?

Sorry if this is a stupid Question. I'm just having trouble seeing the big pic

Upvotes: 3

Views: 10201

Answers (2)

Jaydeep
Jaydeep

Reputation: 5

As per your example... I added comments....

NOTE: while creating waiting queue by default it will be in sleep stat.

DEFINE_WAIT(wait); /* first wait ---> it the kernel global wait queue it is pointing */

add_wait_queue(q, &wait); /* first wait ---> it the kernel global wait queue it is pointing using add_wait_queue(q, &wait); ---> you are adding your own waiting queue (like appending linked list) */

while (!condition) { /* condition is the event that we are waiting for */ /*condition --> Let's say you are getting data from user space in write method (using __get_user()) */

prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE); 

/* This will wait when any wake_up_process() call will be generated having interrupt */ if (signal_pending(current))

/* This is continuously monitoring if any signal is pending on current CPU on which wait queue is running while not pending any signal generally used return -ERESTARTSYS; or "break" the loop if interrupts came exa., SIGINT or SIGKILL and finishes wait queue statement to check again / / handle signal */

  schedule();  // Scheduling of wait queue
               // Remove from global data structure 
}

finish_wait(&q, &wait); //Finishing wait queue

Upvotes: -2

Andreas Bombe
Andreas Bombe

Reputation: 2470

Which process is running the code? The process that called it. I don't mean to make fun of the question but the gist is that kernel code can run in different contexts: Either because a system call led to this place, because it is in a interrupt handler, or because it is a callback function called from another context (such as workqueues or timer functions).

Since this example is sleeping, it must be in a context where sleeping is allowed, meaning it is executed in response to a system call or at least in a kernel thread. So the answer is the process time is taken from the process (or kernel thread) that called into this kernel code that needs to sleep. That is the only place where sleeping is allowed in the first place.

A certain special case are workqueues, these are explicitly for functions that need to sleep. Typical use would be to queue a function that needs to sleep from a context where sleeping is forbidden. In that case, the process context is that of one of the kernel worker threads designated to process workqueue items.

You will return to this loop when the wait_queue is woken up, which either sets one task waiting on the queue to runnable or all of them, depending on the wake_up function called.

The most important thing is, forget about this unless you are interested in the implementation details. Since many people got this wrong and it's basically the same thing everywhere it's needed, there have long been macros encapsulating the whole procedure. Look up wait_event(), that's how your example should really look like:

wait_event(q, condition);

Upvotes: 8

Related Questions