Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 5: Locking and Interprocess Communication


requests following the barrier before read or write requests issued before the barrier have been
completed.

The CPU can still reorder the time flow!
❑ smb_mb(),smp_rmb(),andsmp_wmb()act as the hardware memory barriers described above,
but only when they are used on SMP systems. They generate a software barrier on uniprocessor
systems instead.
❑ read_barrier_depends()is a special form of a read barrier that takes dependencies among
read operations into account. If a read requestafterthe barrier depends on data for which a read
request is performedbeforethe barrier, then both compiler and hardware must not reorder these
requests.

Notice that all commands presented above will have an impact on run-time performance. This is only
natural because if optimizations are disabled, things tend to run slower than with optimizations, which
is the whole purpose of optimizing code. Most of you will agree, though, the code that runs a little slower
but does the right thing is preferable to code that is fast — and wrong.

One particular application for optimization barriers is the kernel preemption mechanism. Note
that thepreempt_disableincrements the preemption counter and thus disables preemption, while
preempt_enablereenables preemption again by decreasing the preemption counter. Code inside a
region embraced by these commands is protected against preemption. Consider the following code:

preempt_disable();
function_which_must_not_be_preempted();
preempt_enable();

It would be quite inconvenient if the compiler would decide to rearrange the code as follows:

function_which_must_not_be_preempted();
preempt_disable();
preempt_enable();

Another possible reordering would be likewise suboptimal:

preempt_disable();
preempt_enable();
function_which_must_not_be_preempted();

In both cases, the non-preemptible partcouldbe preempted. Therefore,preempt_disableinserts a mem-
ory barrier after the preemption counter has been incremented:

<preempt.h>
#define preempt_disable() \
do { \
inc_preempt_count(); \
barrier(); \
} while (0)

This prevents the compiler from swappinginc_preempt_count()with any of the following statements.
Likewise,preempt_enablehas to insert an optimization barrier before preemption is enabled again:

<preempt.h>
#define preempt_enable() \
do { \
Free download pdf