Linux Kernel Architecture

(Jacob Rumans) #1
Mauerer app03.tex V1 - 09/04/2008 6:11pm Page 1197

Appendix C: Notes on C


The input and output registers used are defined by means ofconstraints, which take the following form:


"constraint" (variable)

The previous example employs two constraints:


❑ "r"specifies that a register is to be used to represent the value of the given variable (aorb)inthe
assembler code. Which register is used is left to the compiler and is not known to the program-
mer when the assembler code is written, which is why%0,%1, and so on are used to work with
the registers.
❑ "=r"specifies that an output operand in the form of a register is involved.

In general, constraints are used to indicate whether a value is located in memory or in a register, which
kinds of registers may be used, and so on. GCC supports a wide range of constraints, some of which are
architecture-dependent and some are not. For a fulldescription, refer to the compiler documentation.
This section describes only the features relevant to the kernel.


The following architecture-independent constraints are used in the kernel:


❑ rindicates that a general-purpose register is used.
❑ mspecifies that an address in memory is used.
❑ IandJdefine a constant within the range 0–31 or 0–64 on IA-32 systems. This can be used for
shift operations.

These constraints can be refined by using the followingmodifiersprefixed to the actual constraint:


❑ =specifies that the operand may only be written. The previous value is discarded and replaced
with the output value of the operation.
❑ +specifies that an operand may be read and written.

The next two examples demonstrate how the facilities of the inline assembler are used in the kernel. First,
the atomic setting of a bit in aunsigned longvariable is performed by the following code:


include/asm-x86/bitops_32.h
static inline void set_bit(int nr, volatile unsigned long * addr)
{
__asm__ __volatile__( LOCK_PREFIX
"btsl %1,%0"
:"+m" (ADDR)
:"Ir" (nr));
}

btsstands for the assembler statement ‘‘bit test and set,’’ which queries the value of a given bit in a long
value, stores the value in the CF flag of the processor, and then sets the bit to one. Because long values
comprise 32 bits, the bit position can be specified by means of a constant in the range 0..31, which is
why the constraint typeIis used. The position must also be specified in a register as required by the
architecture — in this case, therconstraint is used.


Because the processed data resides in memory and is modified by a write access, the constraint+mmust
be used for the long value.

Free download pdf