Wednesday, April 13, 2016

Wait Queues in Kernel

When one or more processes/threads want to sleep and wait for one or more events,  the kernel provides wait queues to handle such kind of scenarios. These are higher level mechanism implemented inside Linux kernel to put process/thread in sleep and wake them up.

Important Points :-

  • A Wait queue for an event is a list of nodes
  • Each node points to the thread/process waiting for that particular event. 
  • An individual node in the list is called a wait queue entry.
  • On the occurrence of the event, one or more processes on the list are woken.
  • After waking up, the processes remove themselves from the list.
Wait Queue is defined and used in the following way :-
  • wait_queue_head_t my_event;
  • init_waitqueue_head(&my_event);

The same could be also achieved by using this macro:
DECLARE_WAIT_QUEUE_HEAD(my_event);

Any thread/process that wants to wait for my_event could use either of the following options:
  • wait_event(&my_event, (event_present == 1) ); //Uninterruptible Sleep
  • wait_event_interruptible(&my_event, (event_present == 1) );   

Note that the second argument to the wait function is condition for waiting of the my_event here.


How to wake up thread/process which are sleeping on a wait queue:
  • wake_up(&my_event);: wakes up only one process from the wait queue.
  • wake_up_all(&my_event);: wakes up all the processes on the wait queue.
  • wake_up_interruptible(&my_event);: wakes up only one process from the wait queue that is in interruptible sleep.
Below is an example from Kernel driver(driver/mmc/core/core.c)

/*

 *  Start a new MMC custom command request for a host.
 * If there is on ongoing async request wait for completion
 * of that request and start the new one and return.
 * Does not wait for the new request to complete.
 */
static int mmc_wait_for_data_req_done(struct mmc_host *host,
     struct mmc_request *mrq,
     struct mmc_async_req *next_req)
{
while (1) {
wait_event_interruptible(context_info->wait,
(context_info->is_done_rcv ||
                        context_info->is_new_req));
                               .........
                               .........
                               .........
             }
}


/*

 * Wakes up mmc context, passed as a callback to host controller driver
 */
static void mmc_wait_data_done(struct mmc_request *mrq)
{
mrq->host->context_info.is_done_rcv = true;
wake_up_interruptible(&mrq->host->context_info.wait);
}




No comments:

Post a Comment