Unable to understand how the “current” macro works for x86 architecture

白昼怎懂夜的黑 提交于 2020-06-28 05:30:57

问题


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 &current->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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!