Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities



  1. DEFINE_WAITallows for creating a static instance ofwait_queue_tthat is automatically ini-
    tialized:
    #define DEFINE_WAIT(name) \
    wait_queue_t name = { \
    .private = current, \
    .func = autoremove_wake_function, \
    .task_list = LIST_HEAD_INIT((name).task_list), \
    }


autoremove_wake_functionis now used to wake the process. The function not only calls
default_wake_function, but also removes the wait queue element from the wait queue.

add_wait_queueis normally not used directly. It is more common to usewait_event.Thisisamacro
that requires two parameters:



  1. A wait queue to wait on.

  2. A condition in the form of a C expression of the event to wait for.


All the macro needs to do is to ensure that the condition is not yet already fulfilled; in this case, pro-
cessing can be immediately stopped because there is nothing to wait for. The hard work is delegated to
__wait_event:


<wait.h>
#define __wait_event(wq, condition) \
do { \
DEFINE_WAIT(__wait); \
\
for (;;) { \
prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
finish_wait(&wq, &__wait); \
} while (0)

After setting up the wait queue element withDEFINE_WAIT, the macro produces an endless loop. The
process is put to sleep on the wait queue usingprepare_to_wait. Every time it is woken up, the kernel
checks if the specified condition is fulfilled, and exits the endless loop if this is so. Otherwise, control is
given to the scheduler, and the task is put to sleep again.


It is essential that bothwait_eventand__wait_eventare implemented as macros — this allows for
specifying conditions given by standard C expressions! Since C does not support any nifty features like
higher-order functions, this behavior would be impossible (or at least very clumsy) to achieve using
regular procedures.

Free download pdf