Commit b235beea authored by Linus Torvalds's avatar Linus Torvalds

Clarify naming of thread info/stack allocators

We've had the thread info allocated together with the thread stack for
most architectures for a long time (since the thread_info was split off
from the task struct), but that is about to change.

But the patches that move the thread info to be off-stack (and a part of
the task struct instead) made it clear how confused the allocator and
freeing functions are.

Because the common case was that we share an allocation with the thread
stack and the thread_info, the two pointers were identical.  That
identity then meant that we would have things like

	ti = alloc_thread_info_node(tsk, node);
	...
	tsk->stack = ti;

which certainly _worked_ (since stack and thread_info have the same
value), but is rather confusing: why are we assigning a thread_info to
the stack? And if we move the thread_info away, the "confusing" code
just gets to be entirely bogus.

So remove all this confusion, and make it clear that we are doing the
stack allocation by renaming and clarifying the function names to be
about the stack.  The fact that the thread_info then shares the
allocation is an implementation detail, and not really about the
allocation itself.

This is a pure renaming and type fix: we pass in the same pointer, it's
just that we clarify what the pointer means.

The ia64 code that actually only has one single allocation (for all of
task_struct, thread_info and kernel thread stack) now looks a bit odd,
but since "tsk->stack" is actually not even used there, that oddity
doesn't matter.  It would be a separate thing to clean that up, I
intentionally left the ia64 changes as a pure brute-force renaming and
type change.
Acked-by: default avatarAndy Lutomirski <luto@amacapital.net>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 63c04ee7
...@@ -226,8 +226,8 @@ config ARCH_INIT_TASK ...@@ -226,8 +226,8 @@ config ARCH_INIT_TASK
config ARCH_TASK_STRUCT_ALLOCATOR config ARCH_TASK_STRUCT_ALLOCATOR
bool bool
# Select if arch has its private alloc_thread_info() function # Select if arch has its private alloc_thread_stack() function
config ARCH_THREAD_INFO_ALLOCATOR config ARCH_THREAD_STACK_ALLOCATOR
bool bool
# Select if arch wants to size task_struct dynamically via arch_task_struct_size: # Select if arch wants to size task_struct dynamically via arch_task_struct_size:
......
...@@ -45,7 +45,7 @@ config IA64 ...@@ -45,7 +45,7 @@ config IA64
select GENERIC_SMP_IDLE_THREAD select GENERIC_SMP_IDLE_THREAD
select ARCH_INIT_TASK select ARCH_INIT_TASK
select ARCH_TASK_STRUCT_ALLOCATOR select ARCH_TASK_STRUCT_ALLOCATOR
select ARCH_THREAD_INFO_ALLOCATOR select ARCH_THREAD_STACK_ALLOCATOR
select ARCH_CLOCKSOURCE_DATA select ARCH_CLOCKSOURCE_DATA
select GENERIC_TIME_VSYSCALL_OLD select GENERIC_TIME_VSYSCALL_OLD
select SYSCTL_ARCH_UNALIGN_NO_WARN select SYSCTL_ARCH_UNALIGN_NO_WARN
......
...@@ -48,15 +48,15 @@ struct thread_info { ...@@ -48,15 +48,15 @@ struct thread_info {
#ifndef ASM_OFFSETS_C #ifndef ASM_OFFSETS_C
/* how to get the thread information struct from C */ /* how to get the thread information struct from C */
#define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
#define alloc_thread_info_node(tsk, node) \ #define alloc_thread_stack_node(tsk, node) \
((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) ((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
#define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) #define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
#else #else
#define current_thread_info() ((struct thread_info *) 0) #define current_thread_info() ((struct thread_info *) 0)
#define alloc_thread_info_node(tsk, node) ((struct thread_info *) 0) #define alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
#define task_thread_info(tsk) ((struct thread_info *) 0) #define task_thread_info(tsk) ((struct thread_info *) 0)
#endif #endif
#define free_thread_info(ti) /* nothing */ #define free_thread_stack(ti) /* nothing */
#define task_stack_page(tsk) ((void *)(tsk)) #define task_stack_page(tsk) ((void *)(tsk))
#define __HAVE_THREAD_FUNCTIONS #define __HAVE_THREAD_FUNCTIONS
......
...@@ -115,7 +115,7 @@ static inline unsigned long current_stack_pointer(void) ...@@ -115,7 +115,7 @@ static inline unsigned long current_stack_pointer(void)
} }
#ifndef CONFIG_KGDB #ifndef CONFIG_KGDB
void arch_release_thread_info(struct thread_info *ti); void arch_release_thread_stack(unsigned long *stack);
#endif #endif
#define get_thread_info(ti) get_task_struct((ti)->task) #define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task)
......
...@@ -397,8 +397,9 @@ static bool kgdb_arch_undo_singlestep(struct pt_regs *regs) ...@@ -397,8 +397,9 @@ static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
* single-step state is cleared. At this point the breakpoints should have * single-step state is cleared. At this point the breakpoints should have
* been removed by __switch_to(). * been removed by __switch_to().
*/ */
void arch_release_thread_info(struct thread_info *ti) void arch_release_thread_stack(unsigned long *stack)
{ {
struct thread_info *ti = (void *)stack;
if (kgdb_sstep_thread == ti) { if (kgdb_sstep_thread == ti) {
kgdb_sstep_thread = NULL; kgdb_sstep_thread = NULL;
......
...@@ -78,7 +78,7 @@ struct thread_info { ...@@ -78,7 +78,7 @@ struct thread_info {
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
void arch_release_thread_info(struct thread_info *info); void arch_release_thread_stack(unsigned long *stack);
/* How to get the thread information struct from C. */ /* How to get the thread information struct from C. */
register unsigned long stack_pointer __asm__("sp"); register unsigned long stack_pointer __asm__("sp");
......
...@@ -73,8 +73,9 @@ void arch_cpu_idle(void) ...@@ -73,8 +73,9 @@ void arch_cpu_idle(void)
/* /*
* Release a thread_info structure * Release a thread_info structure
*/ */
void arch_release_thread_info(struct thread_info *info) void arch_release_thread_stack(unsigned long *stack)
{ {
struct thread_info *info = (void *)stack;
struct single_step_state *step_state = info->step_state; struct single_step_state *step_state = info->step_state;
if (step_state) { if (step_state) {
......
...@@ -3007,7 +3007,7 @@ static inline int object_is_on_stack(void *obj) ...@@ -3007,7 +3007,7 @@ static inline int object_is_on_stack(void *obj)
return (obj >= stack) && (obj < (stack + THREAD_SIZE)); return (obj >= stack) && (obj < (stack + THREAD_SIZE));
} }
extern void thread_info_cache_init(void); extern void thread_stack_cache_init(void);
#ifdef CONFIG_DEBUG_STACK_USAGE #ifdef CONFIG_DEBUG_STACK_USAGE
static inline unsigned long stack_not_used(struct task_struct *p) static inline unsigned long stack_not_used(struct task_struct *p)
......
...@@ -453,7 +453,7 @@ void __init __weak smp_setup_processor_id(void) ...@@ -453,7 +453,7 @@ void __init __weak smp_setup_processor_id(void)
} }
# if THREAD_SIZE >= PAGE_SIZE # if THREAD_SIZE >= PAGE_SIZE
void __init __weak thread_info_cache_init(void) void __init __weak thread_stack_cache_init(void)
{ {
} }
#endif #endif
...@@ -627,7 +627,7 @@ asmlinkage __visible void __init start_kernel(void) ...@@ -627,7 +627,7 @@ asmlinkage __visible void __init start_kernel(void)
/* Should be run before the first non-init thread is created */ /* Should be run before the first non-init thread is created */
init_espfix_bsp(); init_espfix_bsp();
#endif #endif
thread_info_cache_init(); thread_stack_cache_init();
cred_init(); cred_init();
fork_init(); fork_init();
proc_caches_init(); proc_caches_init();
......
...@@ -148,18 +148,18 @@ static inline void free_task_struct(struct task_struct *tsk) ...@@ -148,18 +148,18 @@ static inline void free_task_struct(struct task_struct *tsk)
} }
#endif #endif
void __weak arch_release_thread_info(struct thread_info *ti) void __weak arch_release_thread_stack(unsigned long *stack)
{ {
} }
#ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR #ifndef CONFIG_ARCH_THREAD_STACK_ALLOCATOR
/* /*
* Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a
* kmemcache based allocator. * kmemcache based allocator.
*/ */
# if THREAD_SIZE >= PAGE_SIZE # if THREAD_SIZE >= PAGE_SIZE
static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
int node) int node)
{ {
struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP, struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP,
...@@ -172,33 +172,33 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, ...@@ -172,33 +172,33 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
return page ? page_address(page) : NULL; return page ? page_address(page) : NULL;
} }
static inline void free_thread_info(struct thread_info *ti) static inline void free_thread_stack(unsigned long *stack)
{ {
struct page *page = virt_to_page(ti); struct page *page = virt_to_page(stack);
memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK, memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK,
-(1 << THREAD_SIZE_ORDER)); -(1 << THREAD_SIZE_ORDER));
__free_kmem_pages(page, THREAD_SIZE_ORDER); __free_kmem_pages(page, THREAD_SIZE_ORDER);
} }
# else # else
static struct kmem_cache *thread_info_cache; static struct kmem_cache *thread_stack_cache;
static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, static struct thread_info *alloc_thread_stack_node(struct task_struct *tsk,
int node) int node)
{ {
return kmem_cache_alloc_node(thread_info_cache, THREADINFO_GFP, node); return kmem_cache_alloc_node(thread_stack_cache, THREADINFO_GFP, node);
} }
static void free_thread_info(struct thread_info *ti) static void free_stack(unsigned long *stack)
{ {
kmem_cache_free(thread_info_cache, ti); kmem_cache_free(thread_stack_cache, stack);
} }
void thread_info_cache_init(void) void thread_stack_cache_init(void)
{ {
thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, thread_stack_cache = kmem_cache_create("thread_stack", THREAD_SIZE,
THREAD_SIZE, 0, NULL); THREAD_SIZE, 0, NULL);
BUG_ON(thread_info_cache == NULL); BUG_ON(thread_stack_cache == NULL);
} }
# endif # endif
#endif #endif
...@@ -221,9 +221,9 @@ struct kmem_cache *vm_area_cachep; ...@@ -221,9 +221,9 @@ struct kmem_cache *vm_area_cachep;
/* SLAB cache for mm_struct structures (tsk->mm) */ /* SLAB cache for mm_struct structures (tsk->mm) */
static struct kmem_cache *mm_cachep; static struct kmem_cache *mm_cachep;
static void account_kernel_stack(struct thread_info *ti, int account) static void account_kernel_stack(unsigned long *stack, int account)
{ {
struct zone *zone = page_zone(virt_to_page(ti)); struct zone *zone = page_zone(virt_to_page(stack));
mod_zone_page_state(zone, NR_KERNEL_STACK, account); mod_zone_page_state(zone, NR_KERNEL_STACK, account);
} }
...@@ -231,8 +231,8 @@ static void account_kernel_stack(struct thread_info *ti, int account) ...@@ -231,8 +231,8 @@ static void account_kernel_stack(struct thread_info *ti, int account)
void free_task(struct task_struct *tsk) void free_task(struct task_struct *tsk)
{ {
account_kernel_stack(tsk->stack, -1); account_kernel_stack(tsk->stack, -1);
arch_release_thread_info(tsk->stack); arch_release_thread_stack(tsk->stack);
free_thread_info(tsk->stack); free_thread_stack(tsk->stack);
rt_mutex_debug_task_free(tsk); rt_mutex_debug_task_free(tsk);
ftrace_graph_exit_task(tsk); ftrace_graph_exit_task(tsk);
put_seccomp_filter(tsk); put_seccomp_filter(tsk);
...@@ -343,7 +343,7 @@ void set_task_stack_end_magic(struct task_struct *tsk) ...@@ -343,7 +343,7 @@ void set_task_stack_end_magic(struct task_struct *tsk)
static struct task_struct *dup_task_struct(struct task_struct *orig, int node) static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
{ {
struct task_struct *tsk; struct task_struct *tsk;
struct thread_info *ti; unsigned long *stack;
int err; int err;
if (node == NUMA_NO_NODE) if (node == NUMA_NO_NODE)
...@@ -352,15 +352,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) ...@@ -352,15 +352,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
if (!tsk) if (!tsk)
return NULL; return NULL;
ti = alloc_thread_info_node(tsk, node); stack = alloc_thread_stack_node(tsk, node);
if (!ti) if (!stack)
goto free_tsk; goto free_tsk;
err = arch_dup_task_struct(tsk, orig); err = arch_dup_task_struct(tsk, orig);
if (err) if (err)
goto free_ti; goto free_stack;
tsk->stack = ti; tsk->stack = stack;
#ifdef CONFIG_SECCOMP #ifdef CONFIG_SECCOMP
/* /*
* We must handle setting up seccomp filters once we're under * We must handle setting up seccomp filters once we're under
...@@ -392,14 +392,14 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) ...@@ -392,14 +392,14 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
tsk->task_frag.page = NULL; tsk->task_frag.page = NULL;
tsk->wake_q.next = NULL; tsk->wake_q.next = NULL;
account_kernel_stack(ti, 1); account_kernel_stack(stack, 1);
kcov_task_init(tsk); kcov_task_init(tsk);
return tsk; return tsk;
free_ti: free_stack:
free_thread_info(ti); free_thread_stack(stack);
free_tsk: free_tsk:
free_task_struct(tsk); free_task_struct(tsk);
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment