In the Linux Kernel the variable task_struct* current
is a reference to the current task_struct
. This is the process which is currently running on the CPU or which was running until interrupted by the kernel. This is true in every architecture. [kernel reference]
Architectures implement current
differently based upon their facilities and requirements.
In IA64 we find the most concise definition of current
: a system register. [kernel reference]
/*
* In kernel mode, thread pointer (r13) is used to point to the current task
* structure.
*/
#define current ((struct task_struct *) ia64_getreg(_IA64_REG_TP))
In general, the Linux Kernel implements task_struct* current
as:
#define get_current() (current_thread_info()->task)
#define current get_current()
The task_struct* current
is an offset into a structure struct thread_info
. In general, the struct thread_info current_thread
is stored at a mask of the kernel stack pointer.
In ARM we can wee this implemented as:
#define THREAD_SIZE_ORDER 1
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#define THREAD_START_SP (THREAD_SIZE - 8)
register unsigned long current_stack_pointer asm ("sp");
static inline struct thread_info *current_thread_info(void)
{
return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1));
}
In our ARM example this means that we can find the current_thread_info
and therefore current
at:
// $SP is kernel stack pointer
// mask bottom 13 bits are 0 for 4k page sizes.
task_struct* current = $SP & 0xffffe000;
In x86/x64 current
and many other variables are handled as per cpu variables to better support symmetric multiprocessing. In general, per cpu variables are variables which when declared a copy is made for each cpu in the system. In this way each can have their own task_struct* current
.
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()
current
is related to current_task
as above, but it is not current_task. It's a per_cpu_variable
and therefore an offset from a fixed value. That value might be 20 or something like that not a real pointer. The relation between current and current_task is
task_struct* current = __per_cpu_offset[CPU #] + current_task;