Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 14: Kernel Activities


qselects the desired wait queue andmodespecifies what state processes may have in order to be woken
up.nr_exclusiveindicates how many tasks with a setWQ_FLAG_EXCLUSIVEare to be woken up.

The kernel then iterates through the sleeping tasks and invokes their wake-up functionfunc:

kernel/sched.c
list_for_each_safe(curr, next, &q->task_list, task_list) {
unsigned flags = curr->flags;

if (curr->func(curr, mode, sync, key) &&
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}

The list is scanned repeatedly until there are eitherno further tasks or until the number of exclusive
tasks specified bynr_exclusivehas been woken up. This restriction is used to avoid a problem known
as thethundering herd. If several processes are waiting for exclusive access to a resource, it makes no
sense to wake all waiting processes because all but one will have to be put back to sleep.nr_exclusive
generalizes this restriction.

The most frequently usedwake_upfunction setsnr_exclusiveto 1 and thus makes sure that only one
exclusive task is woken up.

Recall from above thatWQ_FLAG_EXCLUSIVEtasks are added to the end of the wait queue. This implemen-
tation ensures that in mixed queues all normal tasksare woken up first, and only then is the restriction
for exclusive tasks taken into consideration.

It is useful to wake all processes in a wait queue if the processes are waiting for a data transfer to ter-
minate. This is because the data of several processes can be read at the same time without mutual
interference.

14.4.2 Completions


Completions resemble the semaphores discussed in Chapter 5 but are implemented on the basis of
wait queues. What interests us is the completions interface. Two actors are present on the stage: One
is waiting for something to be completed, and the other declares when this completion has happened.
Actually, this is a simplification: An arbitrary number of processes can wait for a completion. To rep-
resent the ‘‘something’’ that the processes wait for to be completed, the kernel uses the following data
structure:

<completion.h>
struct completion {
unsigned int done;
wait_queue_head_t wait;
};

doneallows for handling the situation in which an event is completedbeforesome other process waits for
its completion. This is discussed below.waitis a standard wait queue on which waiting processes are
put to sleep.
Free download pdf