Skip to content

Commit c65eacb

Browse files
amlutoIngo Molnar
authored andcommitted
sched/core: Allow putting thread_info into task_struct
If an arch opts in by setting CONFIG_THREAD_INFO_IN_TASK_STRUCT, then thread_info is defined as a single 'u32 flags' and is the first entry of task_struct. thread_info::task is removed (it serves no purpose if thread_info is embedded in task_struct), and thread_info::cpu gets its own slot in task_struct. This is heavily based on a patch written by Linus. Originally-from: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jann Horn <jann@thejh.net> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/a0898196f0476195ca02713691a5037a14f2aac5.1473801993.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent d896fa2 commit c65eacb

File tree

6 files changed

+74
-4
lines changed

6 files changed

+74
-4
lines changed

include/linux/init_task.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <net/net_namespace.h>
1616
#include <linux/sched/rt.h>
1717

18+
#include <asm/thread_info.h>
19+
1820
#ifdef CONFIG_SMP
1921
# define INIT_PUSHABLE_TASKS(tsk) \
2022
.pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO),
@@ -183,12 +185,19 @@ extern struct task_group root_task_group;
183185
# define INIT_KASAN(tsk)
184186
#endif
185187

188+
#ifdef CONFIG_THREAD_INFO_IN_TASK
189+
# define INIT_TASK_TI(tsk) .thread_info = INIT_THREAD_INFO(tsk),
190+
#else
191+
# define INIT_TASK_TI(tsk)
192+
#endif
193+
186194
/*
187195
* INIT_TASK is used to set up the first task table, touch at
188196
* your own risk!. Base=0, limit=0x1fffff (=2MB)
189197
*/
190198
#define INIT_TASK(tsk) \
191199
{ \
200+
INIT_TASK_TI(tsk) \
192201
.state = 0, \
193202
.stack = init_stack, \
194203
.usage = ATOMIC_INIT(2), \

include/linux/sched.h

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,13 @@ struct tlbflush_unmap_batch {
14581458
};
14591459

14601460
struct task_struct {
1461+
#ifdef CONFIG_THREAD_INFO_IN_TASK
1462+
/*
1463+
* For reasons of header soup (see current_thread_info()), this
1464+
* must be the first element of task_struct.
1465+
*/
1466+
struct thread_info thread_info;
1467+
#endif
14611468
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
14621469
void *stack;
14631470
atomic_t usage;
@@ -1467,6 +1474,9 @@ struct task_struct {
14671474
#ifdef CONFIG_SMP
14681475
struct llist_node wake_entry;
14691476
int on_cpu;
1477+
#ifdef CONFIG_THREAD_INFO_IN_TASK
1478+
unsigned int cpu; /* current CPU */
1479+
#endif
14701480
unsigned int wakee_flips;
14711481
unsigned long wakee_flip_decay_ts;
14721482
struct task_struct *last_wakee;
@@ -2588,7 +2598,9 @@ extern void set_curr_task(int cpu, struct task_struct *p);
25882598
void yield(void);
25892599

25902600
union thread_union {
2601+
#ifndef CONFIG_THREAD_INFO_IN_TASK
25912602
struct thread_info thread_info;
2603+
#endif
25922604
unsigned long stack[THREAD_SIZE/sizeof(long)];
25932605
};
25942606

@@ -3076,10 +3088,26 @@ static inline void threadgroup_change_end(struct task_struct *tsk)
30763088
cgroup_threadgroup_change_end(tsk);
30773089
}
30783090

3079-
#ifndef __HAVE_THREAD_FUNCTIONS
3091+
#ifdef CONFIG_THREAD_INFO_IN_TASK
3092+
3093+
static inline struct thread_info *task_thread_info(struct task_struct *task)
3094+
{
3095+
return &task->thread_info;
3096+
}
3097+
static inline void *task_stack_page(const struct task_struct *task)
3098+
{
3099+
return task->stack;
3100+
}
3101+
#define setup_thread_stack(new,old) do { } while(0)
3102+
static inline unsigned long *end_of_stack(const struct task_struct *task)
3103+
{
3104+
return task->stack;
3105+
}
3106+
3107+
#elif !defined(__HAVE_THREAD_FUNCTIONS)
30803108

30813109
#define task_thread_info(task) ((struct thread_info *)(task)->stack)
3082-
#define task_stack_page(task) ((task)->stack)
3110+
#define task_stack_page(task) ((void *)(task)->stack)
30833111

30843112
static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
30853113
{
@@ -3379,7 +3407,11 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
33793407

33803408
static inline unsigned int task_cpu(const struct task_struct *p)
33813409
{
3410+
#ifdef CONFIG_THREAD_INFO_IN_TASK
3411+
return p->cpu;
3412+
#else
33823413
return task_thread_info(p)->cpu;
3414+
#endif
33833415
}
33843416

33853417
static inline int task_node(const struct task_struct *p)

include/linux/thread_info.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@
1313
struct timespec;
1414
struct compat_timespec;
1515

16+
#ifdef CONFIG_THREAD_INFO_IN_TASK
17+
struct thread_info {
18+
u32 flags; /* low level flags */
19+
};
20+
21+
#define INIT_THREAD_INFO(tsk) \
22+
{ \
23+
.flags = 0, \
24+
}
25+
#endif
26+
27+
#ifdef CONFIG_THREAD_INFO_IN_TASK
28+
#define current_thread_info() ((struct thread_info *)current)
29+
#endif
30+
1631
/*
1732
* System call restart block.
1833
*/

init/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ config IRQ_WORK
2626
config BUILDTIME_EXTABLE_SORT
2727
bool
2828

29+
config THREAD_INFO_IN_TASK
30+
bool
31+
help
32+
Select this to move thread_info off the stack into task_struct. To
33+
make this work, an arch will need to remove all thread_info fields
34+
except flags and fix any runtime bugs.
35+
2936
menu "General setup"
3037

3138
config BROKEN

init/init_task.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@ EXPORT_SYMBOL(init_task);
2222
* Initial thread structure. Alignment of this is handled by a special
2323
* linker map entry.
2424
*/
25-
union thread_union init_thread_union __init_task_data =
26-
{ INIT_THREAD_INFO(init_task) };
25+
union thread_union init_thread_union __init_task_data = {
26+
#ifndef CONFIG_THREAD_INFO_IN_TASK
27+
INIT_THREAD_INFO(init_task)
28+
#endif
29+
};

kernel/sched/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,11 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
10001000
* per-task data have been completed by this moment.
10011001
*/
10021002
smp_wmb();
1003+
#ifdef CONFIG_THREAD_INFO_IN_TASK
1004+
p->cpu = cpu;
1005+
#else
10031006
task_thread_info(p)->cpu = cpu;
1007+
#endif
10041008
p->wake_cpu = cpu;
10051009
#endif
10061010
}

0 commit comments

Comments
 (0)