Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities


init_completioninitializes acompletioninstance that was dynamically allocated, while
DECLARE_COMPLETIONis the macro of choice to set up a static instance of the data structure.

Processes can be added to the list usingwait_for_completion, where they wait (in exclusive sleep state)
until their request is processed by some part of the kernel. The function requires acompletioninstance
as a parameter:

<completion.h>
void wait_for_completion(struct completion *);
int wait_for_completion_interruptible(struct completion *x);
unsigned long wait_for_completion_timeout(struct completion *x,
unsigned long timeout);
unsigned long wait_for_completion_interruptible_timeout(
struct completion *x, unsigned long timeout);

Several refined variants are additionally available:

❑ Normally processes that wait for completion of an event are in an uninterruptible state, but
this can be changed ifwait_for_completion_interruptibleis used. The function returns
-ERESTARTSYSif the process was interrupted, and 0 otherwise.
❑ wait_for_completion_timeoutwaits for a completion event to occur, but provides an addi-
tional time-out in jiffies that cancels waiting after a defined time. This helps to prevent wait-
ing for an event indefinitely. If the completionis finished before the time-out occurs, then the
remaining time is returned as result, otherwise 0.
❑ wait_for_completion_interruptible_timeoutis a combination of both variants.

Once the request has been processed by another part of the kernel, eithercompleteorcomplete_all
must be invoked from there to wake the waiting processes. Because only one process can be removed
from the completions list at each invocation, the function must be invoked exactlyntimes fornwait-
ing processes.complete_all, on the other hand, wakes up all processing waiting for the completion.
complete_and_exitis a small wrapper that first appliescompleteand then callsdo_exitto finish the
kernel thread.

<completion.h>
void complete(struct completion *);
void complete_all(struct completion *);

kernel/exit.c
NORET_TYPE void complete_and_exit(struct completion *comp, long code);

complete,complete_all,andcomplete_and_exitrequire a pointer to an instance ofstruct completion
as a parameter that identifies the completion in question.

Now what is the meaning ofdoneinstruct completion?Eachtimecompleteis called, the counter
is incremented by 1, and thewait_forfunctions only puts the caller to sleep ifdoneis not equal to 0.
Effectively, this means that processes do notwait for events that are already completed.complete_all
works similarly, but sets the counter to the largest possible value (UINT_MAX/2— half of the maximal
value of an unsigned integer because the counter can also assume negative values) such that processes
that callwait_after the event has completed will never go to sleep.
Free download pdf