Right now I'm reading the book "Linux Kernel Development 3d Edition" by Robert Love. There he write about the thread_info struct which contains the pointer to task_struct struct and, as I understood, located at the bottom or at the top of kernel stack of process (depends on architecture). I wasn't familiar with Linux kernel API until recently and I wasn't known of current() method existence. There is an excerpt from the book related to how current() method actually works:
On x86, current is calculated by masking out the 13 least-significant bits of the stack pointer to obtain the thread_info structure.This is done by the current_thread_info() function.The assembly is shown here: movl $-8192, %eax andl %esp, %eax This assumes that the stack size is 8KB.When 4KB stacks are enabled, 4096 is used in lieu of 8192.
My questions are:
- As far as I know if we have a decimal value represented as a set of bits, then there is only one least-significant bit in the set, isn't it?
- What is the magical number 13?
For thous who will read this topic, the questions I have voiced can lead to conclusion that the author don't understand properly the process of memory allocation and administration. Ok, that's may be right due to the fact that in my mind I can represent the memory allocated for the stack as the ribbon full of bits (or bytes). All of this bytes accessible by a specific memory address represented as some decimal value. The origin of the stack is the lowest memory address and the fin of the stack is the highest value of memory address. But HOW, HOW can we get the the pointer to the thread_info struct located at the, say, end of the stack only by masking out 13 least-significant bits of ARBITRARY located stack pointer (If I understood correctly, we masking out bits of the stack pointer ADDRESS represented as decimal value).
My 2 bits: note that the implementation of 'current' is arch-dependant. The answers so far focus on the x86; various means of getting at the thread_info and thus the task_struct are employed by other arch's on the Linux OS.
For eg., apparently the PPC uses a register (it's RISC, remember, with plenty of GPRs) to store the value of current- in effect rendering it part of hardware context! This is going to be really fast.
The modern x86 port (i looked up the 4.1.0 kernel sources) uses per-cpu data to implement current in a fast and lockless fashion. And so on...
Note that both the bottom and limit(top) address (assuming a bottom-up stack with higher address located in the bottom) MUST BE a multiple of stack size. For example, if a stack size is 8192 (=2^13), the 13 least significant bits must all be 0 for both the bottom and limit address. The least-significant 13 bit is NOT ARBITRARY in a sense that it gives the offset between the bottom address and limit address, which both ends with 13 0's. Thus masking out the least-significant 13 bits give you the address of the limit address, which is where the thread_info structure located.
Each process only gets 8192 bytes of kernel stack, aligned to a 8192-byte boundary, so whenever the stack pointer is altered by a push or a pop, the low 13 bits are the only part that changes. 2**13==8192.
The kernel stack contains a special struct at the top -- thread_info:
So, to get the
task_struct
you'll need to get athread_info
pointer with GET_THREAD_INFO from the ASM-code:... or with current_thread_info from the C-code:
Note that
THREAD_SIZE
defined as(PAGE_SIZE << THREAD_SIZE_ORDER)
andTHREAD_SIZE_ORDER
equals 1 for both x86_32 and x86_64 soTHREAD_SIZE
results to 8192 (2^13 or 1<<13).