Cpumasksis a special way provided by the Linux kernel to store information about CPUs in the system. The relevant source code and header files which contains API for
boot_cpu_initfunction from the Kernel entry point part. This function makes first boot cpu online, active and etc...:
cpu_possibleis a set of cpu ID's which can be plugged in anytime during the life of that system boot or in other words mask of possible CPUs contains maximum number of CPUs which are possible in the system. It will be equal to value of the
NR_CPUSwhich is set statically via the
CONFIG_NR_CPUSkernel configuration option.
cpu_presentmask represents which CPUs are currently plugged in.
cpu_onlinerepresents a subset of the
cpu_presentand indicates CPUs which are available for scheduling or in other words a bit from this mask tells the kernel if a processor may be utilized by the Linux kernel.
cpu_active. Bits of this mask tells to Linux kernel is a task may be moved to a certain processor.
CONFIG_HOTPLUG_CPUconfiguration option and if this option is disabled
possible == presentand
active == online. The implementations of all of these functions are very similar. Every function checks the second parameter. If it is
true, it calls
cpumask_set_cpuotherwise it calls
cpumaskcreation. First is to use
cpumask_t. It is defined as:
cpumaskstructure which contains one bitmask
DECLARE_BITMAPmacro gets two parameters:
unsigned longwith the given name. Its implementation is pretty easy:
unsigned longis 8-bytes size and our array will contain only one element:
DECLARE_BITMAPmacro directly and the
to_cpumaskmacro which converts the given bitmap to
struct cpumask *:
__check_is_bitmapinline function is defined as:
1every time. We need it here for only one purpose: at compile time it checks that a given
bitmapis a bitmap, or in other words it checks that a given
bitmaphas type -
unsigned long *. So we just pass
to_cpumaskmacro for converting an array of
unsigned longto the
struct cpumask *.
set_cpu_online. This function takes two parameters:
stateparameter and calls
cpumask_clear_cpudepending on it. Here we can see casting to the
struct cpumask *of the second parameter in the
cpumask_set_cpu. In our case it is
cpu_online_bitswhich is a bitmap and defined as:
cpumask_set_cpufunction makes only one call to the
set_bitfunction takes two parameters too, and sets a given bit (first parameter) in the memory (second parameter or
cpu_online_bitsbitmap). We can see here that before
set_bitis called, its two parameters will be passed to the
cpumask_checkdoes nothing in our case and just returns given parameter. The second
cpumask_bitsjust returns the
bitsfield from the given
struct cpumask *structure:
nror number of the bit to the
IS_IMMEDIATEmacro which just calls the GCC internal
__builtin_constant_pchecks that given parameter is known constant at compile-time. As our
cpuis not compile-time constant, the
elseclause will be executed:
LOCK_PREFIXis a x86
lockinstruction. This instruction tells the cpu to occupy the system bus while the instruction(s) will be executed. This allows the CPU to synchronize memory access, preventing simultaneous access of multiple processors (or devices - the DMA controller for example) to one memory cell.
BITOP_ADDRcasts the given parameter to the
(*(volatile long *)and adds
+means that this operand is both read and written by the instruction.
mshows that this is a memory operand.
BITOP_ADDRis defined as:
memoryclobber. It tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands (for example, accessing the memory pointed to by one of the input parameters).
Ir- immediate register operand.
btsinstruction sets a given bit in a bit string and stores the value of a given bit in the
CFflag. So we passed the cpu number which is zero in our case and after
set_bitis executed, it sets the zero bit in the
cpu_online_bitscpumask. It means that the first cpu is online at this moment.
set_cpu_*API, cpumask of course provides another API for cpumasks manipulation. Let's consider it in short.
onlineCPUs. It calls the
cpumask_weightfunction with the
cpu_online_maskbitmap (read about it). The
cpumask_weightfunction makes one call of the
bitmap_weightfunction with two parameters:
nr_cpumask_bits- which is
NR_CPUSin our case.
num_online_cpus, cpumask provides macros for the all CPU states:
for_each_cpu- iterates over every cpu in a mask;
for_each_cpu_not- iterates over every cpu in a complemented mask;
cpumask_clear_cpu- clears a cpu in a cpumask;
cpumask_test_cpu- tests a cpu in a mask;
cpumask_setall- set all cpus in a mask;
cpumask_size- returns size to allocate for a 'struct cpumask' in bytes;