Why thread_info should be the first element in task_struct?

tyChen

When reading Linux kernel source code, I find one thing makes me confused.

In task_struct, it says like this

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 complete code is here, can you tell me why this must be the first element in task_struct?

tyChen

After searching many books, websites and debugging the Linux kernel, I understand the design of thread_info and I get to know why it must be the first element in task_struct.

Firstly, we need to understand Linux kernel stack.

Then, we come to the core : we need to get to kernel stack by task_struct some time, and we need to get to task_struct by kernel stack some time. So we must have some way to do it.

1. task_struct to kernel stack

It is easy to use stack like below

static inline void *task_stack_page(const struct task_struct *task)
{
  return task->stack;
}

What's more, we can get to pt_regs by task_pt_regs(task)

2.kernel stack to task_struct

Here is the use of thread_info. Let me put two version here

struct thread_info {
  struct task_struct  *task;    /* main task structure */
  __u32      flags;    /* low level flags */
  __u32      status;    /* thread synchronous flags */
  __u32      cpu;    /* current CPU */
  mm_segment_t    addr_limit;
  unsigned int    sig_on_uaccess_error:1;
  unsigned int    uaccess_err:1;  /* uaccess failed */
};


struct thread_info {
  unsigned long flags;          /* low level flags */
  unsigned long status;    /* thread synchronous flags */    
};


The first one is the old version, it includes task_struct, from which we can go straightly to task_struct. But it costs too much to strore it, so the new version delete all.

In the old version, we have this function to get it.

static inline struct thread_info *current_thread_info(void)
{
  return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE);
}

But how can we get to task_struct by the new version?

It is because we use a new current_thread_info

#include <asm/current.h>
#define current_thread_info() ((struct thread_info *)current)
#endif

The current is defined below

struct task_struct;

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

That is to say, we have task_struct from per cpu.

Here is the last part of the source code we show

DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task;

......

__visible __notrace_funcgraph struct task_struct *
__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
......
this_cpu_write(current_task, next_p);
......
return prev_p;
}


...

#define this_cpu_read_stable(var)       percpu_stable_op("mov", var)

By this way, we can get task_struct easily.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

why sibling list is used to get the task_struct while fetching the children of a process

Linux Kernel: Threading vs Process - task_struct vs thread_info

Why task is done when first element in the future list is true?

Why are double quotes shown only for the first element?

why jQuery .find() only return first element?

Why is bash only appending first element to array

why boost::python iterator skips first element?

Why this code is giving error.......'a' is pointer to character pointer and should store address of 's', since s is pointer to first element to array

why extra space after first element

Why the icon in QListWidget is displayed only for the first element?

Getting a Pointer to the First Element of a Struct

Enforce element from a map used by a thread should not be used by another thread until first thread completes execution

Why is the array not printing the very first element?

Why is the distance between first and last element decreasing?

DropDownListFor - why selected element is always the first?

Why is this vector copying its first element?

Why ampersand should be escaped first in html escaping?

Why only the First Element is being added to the div

Why sizes of an array and a pointer to a first element are different?

Why is an element which should be 100% in width have an element to its right?

Why is the process state in task_struct stored as type 'long'?

why first li element dont move down?

Members of thread_info struct for linux on x86

Why is my for loop only grabbing first element?

Why the first element of response is null in serverless?

Why this list<int[]> not keep the first element?

Why does findIndex not return the first found element?

How 'task_struct' is accessed via 'thread_info' in linux latest kernel?

jq streaming eats first element, why?