Skip to content

Instantly share code, notes, and snippets.

@lacraig2
Last active May 2, 2020 04:13
Show Gist options
  • Save lacraig2/7a18f95d6d8ffcfec7fda4a1e9f23a33 to your computer and use it in GitHub Desktop.
Save lacraig2/7a18f95d6d8ffcfec7fda4a1e9f23a33 to your computer and use it in GitHub Desktop.

current in the Linux Kernel

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.

IA64

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))

Generic Kernel behavior

In general, the Linux Kernel implements task_struct* current as:

#define get_current() (current_thread_info()->task)
#define current get_current()

[kernel reference]

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));
}

[kernel reference]

task offset link for great picture

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; 

x86/x64

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()

[kernel reference]

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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment