diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-09-13 17:29:24 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-09-15 02:25:13 -0400 |
commit | c65eacbe290b8141554c71b2c94489e73ade8c8d (patch) | |
tree | 001c2aa33a3dded758550c659ced4b70e341e03e | |
parent | d896fa20a70c9e596438728561e058a74ed3196b (diff) |
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>
-rw-r--r-- | include/linux/init_task.h | 9 | ||||
-rw-r--r-- | include/linux/sched.h | 36 | ||||
-rw-r--r-- | include/linux/thread_info.h | 15 | ||||
-rw-r--r-- | init/Kconfig | 7 | ||||
-rw-r--r-- | init/init_task.c | 7 | ||||
-rw-r--r-- | kernel/sched/sched.h | 4 |
6 files changed, 74 insertions, 4 deletions
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index f8834f820ec2..9c04d44eeb3c 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <net/net_namespace.h> | 15 | #include <net/net_namespace.h> |
16 | #include <linux/sched/rt.h> | 16 | #include <linux/sched/rt.h> |
17 | 17 | ||
18 | #include <asm/thread_info.h> | ||
19 | |||
18 | #ifdef CONFIG_SMP | 20 | #ifdef CONFIG_SMP |
19 | # define INIT_PUSHABLE_TASKS(tsk) \ | 21 | # define INIT_PUSHABLE_TASKS(tsk) \ |
20 | .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), | 22 | .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), |
@@ -183,12 +185,19 @@ extern struct task_group root_task_group; | |||
183 | # define INIT_KASAN(tsk) | 185 | # define INIT_KASAN(tsk) |
184 | #endif | 186 | #endif |
185 | 187 | ||
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 | |||
186 | /* | 194 | /* |
187 | * INIT_TASK is used to set up the first task table, touch at | 195 | * INIT_TASK is used to set up the first task table, touch at |
188 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 196 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
189 | */ | 197 | */ |
190 | #define INIT_TASK(tsk) \ | 198 | #define INIT_TASK(tsk) \ |
191 | { \ | 199 | { \ |
200 | INIT_TASK_TI(tsk) \ | ||
192 | .state = 0, \ | 201 | .state = 0, \ |
193 | .stack = init_stack, \ | 202 | .stack = init_stack, \ |
194 | .usage = ATOMIC_INIT(2), \ | 203 | .usage = ATOMIC_INIT(2), \ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 20f9f47bcfd0..a287e8b13549 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1458,6 +1458,13 @@ struct tlbflush_unmap_batch { | |||
1458 | }; | 1458 | }; |
1459 | 1459 | ||
1460 | struct task_struct { | 1460 | 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 | ||
1461 | volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ | 1468 | volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ |
1462 | void *stack; | 1469 | void *stack; |
1463 | atomic_t usage; | 1470 | atomic_t usage; |
@@ -1467,6 +1474,9 @@ struct task_struct { | |||
1467 | #ifdef CONFIG_SMP | 1474 | #ifdef CONFIG_SMP |
1468 | struct llist_node wake_entry; | 1475 | struct llist_node wake_entry; |
1469 | int on_cpu; | 1476 | int on_cpu; |
1477 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
1478 | unsigned int cpu; /* current CPU */ | ||
1479 | #endif | ||
1470 | unsigned int wakee_flips; | 1480 | unsigned int wakee_flips; |
1471 | unsigned long wakee_flip_decay_ts; | 1481 | unsigned long wakee_flip_decay_ts; |
1472 | struct task_struct *last_wakee; | 1482 | struct task_struct *last_wakee; |
@@ -2588,7 +2598,9 @@ extern void set_curr_task(int cpu, struct task_struct *p); | |||
2588 | void yield(void); | 2598 | void yield(void); |
2589 | 2599 | ||
2590 | union thread_union { | 2600 | union thread_union { |
2601 | #ifndef CONFIG_THREAD_INFO_IN_TASK | ||
2591 | struct thread_info thread_info; | 2602 | struct thread_info thread_info; |
2603 | #endif | ||
2592 | unsigned long stack[THREAD_SIZE/sizeof(long)]; | 2604 | unsigned long stack[THREAD_SIZE/sizeof(long)]; |
2593 | }; | 2605 | }; |
2594 | 2606 | ||
@@ -3076,10 +3088,26 @@ static inline void threadgroup_change_end(struct task_struct *tsk) | |||
3076 | cgroup_threadgroup_change_end(tsk); | 3088 | cgroup_threadgroup_change_end(tsk); |
3077 | } | 3089 | } |
3078 | 3090 | ||
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) | ||
3080 | 3108 | ||
3081 | #define task_thread_info(task) ((struct thread_info *)(task)->stack) | 3109 | #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) |
3083 | 3111 | ||
3084 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) | 3112 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) |
3085 | { | 3113 | { |
@@ -3379,7 +3407,11 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) | |||
3379 | 3407 | ||
3380 | static inline unsigned int task_cpu(const struct task_struct *p) | 3408 | static inline unsigned int task_cpu(const struct task_struct *p) |
3381 | { | 3409 | { |
3410 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
3411 | return p->cpu; | ||
3412 | #else | ||
3382 | return task_thread_info(p)->cpu; | 3413 | return task_thread_info(p)->cpu; |
3414 | #endif | ||
3383 | } | 3415 | } |
3384 | 3416 | ||
3385 | static inline int task_node(const struct task_struct *p) | 3417 | static inline int task_node(const struct task_struct *p) |
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 2b5b10eed74f..e2d0fd81b1ba 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h | |||
@@ -13,6 +13,21 @@ | |||
13 | struct timespec; | 13 | struct timespec; |
14 | struct compat_timespec; | 14 | struct compat_timespec; |
15 | 15 | ||
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 | |||
16 | /* | 31 | /* |
17 | * System call restart block. | 32 | * System call restart block. |
18 | */ | 33 | */ |
diff --git a/init/Kconfig b/init/Kconfig index cac3f096050d..ec8d43894b02 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -26,6 +26,13 @@ config IRQ_WORK | |||
26 | config BUILDTIME_EXTABLE_SORT | 26 | config BUILDTIME_EXTABLE_SORT |
27 | bool | 27 | bool |
28 | 28 | ||
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 | |||
29 | menu "General setup" | 36 | menu "General setup" |
30 | 37 | ||
31 | config BROKEN | 38 | config BROKEN |
diff --git a/init/init_task.c b/init/init_task.c index ba0a7f362d9e..11f83be1fa79 100644 --- a/init/init_task.c +++ b/init/init_task.c | |||
@@ -22,5 +22,8 @@ EXPORT_SYMBOL(init_task); | |||
22 | * Initial thread structure. Alignment of this is handled by a special | 22 | * Initial thread structure. Alignment of this is handled by a special |
23 | * linker map entry. | 23 | * linker map entry. |
24 | */ | 24 | */ |
25 | union thread_union init_thread_union __init_task_data = | 25 | union thread_union init_thread_union __init_task_data = { |
26 | { INIT_THREAD_INFO(init_task) }; | 26 | #ifndef CONFIG_THREAD_INFO_IN_TASK |
27 | INIT_THREAD_INFO(init_task) | ||
28 | #endif | ||
29 | }; | ||
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c64fc5114004..3655c9625e5b 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h | |||
@@ -1000,7 +1000,11 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) | |||
1000 | * per-task data have been completed by this moment. | 1000 | * per-task data have been completed by this moment. |
1001 | */ | 1001 | */ |
1002 | smp_wmb(); | 1002 | smp_wmb(); |
1003 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
1004 | p->cpu = cpu; | ||
1005 | #else | ||
1003 | task_thread_info(p)->cpu = cpu; | 1006 | task_thread_info(p)->cpu = cpu; |
1007 | #endif | ||
1004 | p->wake_cpu = cpu; | 1008 | p->wake_cpu = cpu; |
1005 | #endif | 1009 | #endif |
1006 | } | 1010 | } |