I learned thread_info is stored in the bottom of stack.
While looking in the source code of kernel, I'm trying to understand how to get current thread_info in linux kernel?
Source code below is 13bits masking of current_stack_pointer.
This is what I cannot get it. I don't understand that the position of thread_info changes. Why is it current stack pointer instead of start of stack?
Please help me to understand this code
/* * how to get the current stack pointer in C */ register unsigned long current_stack_pointer asm ("sp"); /* * how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) __attribute_const__; static inline struct thread_info *current_thread_info(void) { return (struct thread_info *) (current_stack_pointer & ~(THREAD_SIZE - 1)); }
You can always get current stack pointer from the platform specific stack pointer register, but you cannot find start of the stack so easily - it is just not there.
To do this you can restrict location of thread stack in memory: stack is always kept aligned in memory by its size and its size is always a power of two. This way if stack size is
2^n
, then zeroing out lowern
gives you start of the stack.In modern Linux stack is usually 8 KiB and is always 8 KiB aligned (lower 13 bits of its address are always 0). Zeroing out lower 13 bits of the current stack pointer gives you start of the stack.
This is exactly what expression
current_stack_pointer & ~(THREAD_SIZE - 1)
does: finds start of the current stack. It does not mean thatstruct thread_info
moves in memory - it doesn't. Even if stack pointer changes, zeroing out lower bits gives you the same value within a thread. This why it is also marked with__attribute_const__
which expands to__attribute__((const))
and tells GCC that this function always returns the same value so that multiple calls to this function can be omitted.PS: As stack grows downwards, by "start of the current stack" I mean the lowest address.