问题
I was trying to understand how current
macro works, so started browsing the Linux Kernel source code version 4.19. Was trying to understand for x86 architecture
include/asm-generic/current.h:8
#define get_current() (current_thread_info()->task)
#define current get_current()
I then tried to find the definition of current_thread_info().
include/linux/thread_info.h
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the
* definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,
* including <asm/current.h> can cause a circular dependency on some platforms.
*/
#include <asm/current.h>
#define current_thread_info() ((struct thread_info *)current)
#endif
I then tried to find current definition
arch/x86/include/asm/current.h
DECLARE_PER_CPU(struct task_struct *, current_task);
static __always_inline struct task_struct *get_current(void)
{
return this_cpu_read_stable(current_task);
}
#define current get_current()
get_current() is again returning struct task_struct, why are we typecasting it to struct thread_info in current_thread_info().
Can you please explain how current gets executed. I read somewhere that it is placed at the top or bottom of the kernel stack
回答1:
For casting the pointer - the struct thread_info thread_info
is the first member of the struct task_struct:
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
The cast is legal - we're returning a pointer to the first member of a struct
. It could have similarly used ¤t->thread_info
but that cannot be used if the definition of struct task_struct
is opaque in some contexts (i.e. it is an incomplete type)!
As for how the DECLARE_PER_CPU
stuff works, that depends. What you have learnt in the past might not apply here any more. The variables declared with DECLARE_PER_CPU
are read and updated using special macros. Other
This is because on x86 the reads happen through a special segment register. Other CPU architectures must then use some completely different means of accessing per-cpu values.
Ordinarily the per-cpu variables should be read using this_cpu_read
which doesn't allow GCC to cache it in any way, but current thread info is an exception since the current thread always runs in the current thread no matter what CPU it is on. From arch/x86/include/asm/percpu.h:
/*
* this_cpu_read() makes gcc load the percpu variable every time it is
* accessed while this_cpu_read_stable() allows the value to be cached.
* this_cpu_read_stable() is more efficient and can be used if its value
* is guaranteed to be valid across cpus. The current users include
* get_current() and get_thread_info() both of which are actually
* per-thread variables implemented as per-cpu variables and thus
* stable for the duration of the respective task.
*/
来源:https://stackoverflow.com/questions/53940893/unable-to-understand-how-the-current-macro-works-for-x86-architecture