diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-07-17 06:28:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-07-17 21:42:51 -0400 |
commit | 5aaeb5c01c5b6c0be7b7aadbf3ace9f3a4458c3d (patch) | |
tree | 8cf45cdd6647d1067d94aaad64598a7728f15d6b | |
parent | 0c8c0f03e3a292e031596484275c14cf39c0ab7a (diff) |
x86/fpu, sched: Introduce CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and use it on x86
Don't burden architectures without dynamic task_struct sizing
with the overhead of dynamic sizing.
Also optimize the x86 code a bit by caching task_struct_size.
Acked-and-Tested-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave@sr71.net>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1437128892-9831-3-git-send-email-mingo@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/Kconfig | 4 | ||||
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/kernel/fpu/init.c | 17 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 2 | ||||
-rw-r--r-- | fs/proc/kcore.c | 4 | ||||
-rw-r--r-- | include/linux/sched.h | 6 | ||||
-rw-r--r-- | kernel/fork.c | 11 |
7 files changed, 27 insertions, 18 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index bec6666a3cc4..8a8ea7110de8 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -221,6 +221,10 @@ config ARCH_TASK_STRUCT_ALLOCATOR | |||
221 | config ARCH_THREAD_INFO_ALLOCATOR | 221 | config ARCH_THREAD_INFO_ALLOCATOR |
222 | bool | 222 | bool |
223 | 223 | ||
224 | # Select if arch wants to size task_struct dynamically via arch_task_struct_size: | ||
225 | config ARCH_WANTS_DYNAMIC_TASK_STRUCT | ||
226 | bool | ||
227 | |||
224 | config HAVE_REGS_AND_STACK_ACCESS_API | 228 | config HAVE_REGS_AND_STACK_ACCESS_API |
225 | bool | 229 | bool |
226 | help | 230 | help |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3dbb7e7909ca..b3a1a5d77d92 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -41,6 +41,7 @@ config X86 | |||
41 | select ARCH_USE_CMPXCHG_LOCKREF if X86_64 | 41 | select ARCH_USE_CMPXCHG_LOCKREF if X86_64 |
42 | select ARCH_USE_QUEUED_RWLOCKS | 42 | select ARCH_USE_QUEUED_RWLOCKS |
43 | select ARCH_USE_QUEUED_SPINLOCKS | 43 | select ARCH_USE_QUEUED_SPINLOCKS |
44 | select ARCH_WANTS_DYNAMIC_TASK_STRUCT | ||
44 | select ARCH_WANT_FRAME_POINTERS | 45 | select ARCH_WANT_FRAME_POINTERS |
45 | select ARCH_WANT_IPC_PARSE_VERSION if X86_32 | 46 | select ARCH_WANT_IPC_PARSE_VERSION if X86_32 |
46 | select ARCH_WANT_OPTIONAL_GPIOLIB | 47 | select ARCH_WANT_OPTIONAL_GPIOLIB |
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index deacbfa6b33e..0b39173dd971 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <asm/fpu/internal.h> | 4 | #include <asm/fpu/internal.h> |
5 | #include <asm/tlbflush.h> | 5 | #include <asm/tlbflush.h> |
6 | 6 | ||
7 | #include <linux/sched.h> | ||
8 | |||
7 | /* | 9 | /* |
8 | * Initialize the TS bit in CR0 according to the style of context-switches | 10 | * Initialize the TS bit in CR0 according to the style of context-switches |
9 | * we are using: | 11 | * we are using: |
@@ -136,16 +138,14 @@ static void __init fpu__init_system_generic(void) | |||
136 | unsigned int xstate_size; | 138 | unsigned int xstate_size; |
137 | EXPORT_SYMBOL_GPL(xstate_size); | 139 | EXPORT_SYMBOL_GPL(xstate_size); |
138 | 140 | ||
139 | #define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ | 141 | /* Enforce that 'MEMBER' is the last field of 'TYPE': */ |
140 | BUILD_BUG_ON((sizeof(TYPE) - \ | 142 | #define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ |
141 | offsetof(TYPE, MEMBER) - \ | 143 | BUILD_BUG_ON(sizeof(TYPE) != offsetofend(TYPE, MEMBER)) |
142 | sizeof(((TYPE *)0)->MEMBER)) > \ | ||
143 | 0) \ | ||
144 | 144 | ||
145 | /* | 145 | /* |
146 | * We append the 'struct fpu' to the task_struct. | 146 | * We append the 'struct fpu' to the task_struct: |
147 | */ | 147 | */ |
148 | int __weak arch_task_struct_size(void) | 148 | static void __init fpu__init_task_struct_size(void) |
149 | { | 149 | { |
150 | int task_size = sizeof(struct task_struct); | 150 | int task_size = sizeof(struct task_struct); |
151 | 151 | ||
@@ -172,7 +172,7 @@ int __weak arch_task_struct_size(void) | |||
172 | CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); | 172 | CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); |
173 | CHECK_MEMBER_AT_END_OF(struct task_struct, thread); | 173 | CHECK_MEMBER_AT_END_OF(struct task_struct, thread); |
174 | 174 | ||
175 | return task_size; | 175 | arch_task_struct_size = task_size; |
176 | } | 176 | } |
177 | 177 | ||
178 | /* | 178 | /* |
@@ -326,6 +326,7 @@ void __init fpu__init_system(struct cpuinfo_x86 *c) | |||
326 | fpu__init_system_generic(); | 326 | fpu__init_system_generic(); |
327 | fpu__init_system_xstate_size_legacy(); | 327 | fpu__init_system_xstate_size_legacy(); |
328 | fpu__init_system_xstate(); | 328 | fpu__init_system_xstate(); |
329 | fpu__init_task_struct_size(); | ||
329 | 330 | ||
330 | fpu__init_system_ctx_switch(); | 331 | fpu__init_system_ctx_switch(); |
331 | } | 332 | } |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 975420eac105..397688beed4b 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -81,7 +81,7 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister); | |||
81 | */ | 81 | */ |
82 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 82 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
83 | { | 83 | { |
84 | memcpy(dst, src, arch_task_struct_size()); | 84 | memcpy(dst, src, arch_task_struct_size); |
85 | 85 | ||
86 | return fpu__copy(&dst->thread.fpu, &src->thread.fpu); | 86 | return fpu__copy(&dst->thread.fpu, &src->thread.fpu); |
87 | } | 87 | } |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index a0fe99485687..92e6726f6e37 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -92,7 +92,7 @@ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen) | |||
92 | roundup(sizeof(CORE_STR), 4)) + | 92 | roundup(sizeof(CORE_STR), 4)) + |
93 | roundup(sizeof(struct elf_prstatus), 4) + | 93 | roundup(sizeof(struct elf_prstatus), 4) + |
94 | roundup(sizeof(struct elf_prpsinfo), 4) + | 94 | roundup(sizeof(struct elf_prpsinfo), 4) + |
95 | roundup(arch_task_struct_size(), 4); | 95 | roundup(arch_task_struct_size, 4); |
96 | *elf_buflen = PAGE_ALIGN(*elf_buflen); | 96 | *elf_buflen = PAGE_ALIGN(*elf_buflen); |
97 | return size + *elf_buflen; | 97 | return size + *elf_buflen; |
98 | } | 98 | } |
@@ -415,7 +415,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff) | |||
415 | /* set up the task structure */ | 415 | /* set up the task structure */ |
416 | notes[2].name = CORE_STR; | 416 | notes[2].name = CORE_STR; |
417 | notes[2].type = NT_TASKSTRUCT; | 417 | notes[2].type = NT_TASKSTRUCT; |
418 | notes[2].datasz = arch_task_struct_size(); | 418 | notes[2].datasz = arch_task_struct_size; |
419 | notes[2].data = current; | 419 | notes[2].data = current; |
420 | 420 | ||
421 | nhdr->p_filesz += notesize(¬es[2]); | 421 | nhdr->p_filesz += notesize(¬es[2]); |
diff --git a/include/linux/sched.h b/include/linux/sched.h index e43a41d892b6..04b5ada460b4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1786,7 +1786,11 @@ struct task_struct { | |||
1786 | */ | 1786 | */ |
1787 | }; | 1787 | }; |
1788 | 1788 | ||
1789 | extern int arch_task_struct_size(void); | 1789 | #ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT |
1790 | extern int arch_task_struct_size __read_mostly; | ||
1791 | #else | ||
1792 | # define arch_task_struct_size (sizeof(struct task_struct)) | ||
1793 | #endif | ||
1790 | 1794 | ||
1791 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ | 1795 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ |
1792 | #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) | 1796 | #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) |
diff --git a/kernel/fork.c b/kernel/fork.c index 431b67a6098c..dbd9b8d7b7cc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -287,21 +287,20 @@ static void set_max_threads(unsigned int max_threads_suggested) | |||
287 | max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); | 287 | max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); |
288 | } | 288 | } |
289 | 289 | ||
290 | int __weak arch_task_struct_size(void) | 290 | #ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT |
291 | { | 291 | /* Initialized by the architecture: */ |
292 | return sizeof(struct task_struct); | 292 | int arch_task_struct_size __read_mostly; |
293 | } | 293 | #endif |
294 | 294 | ||
295 | void __init fork_init(void) | 295 | void __init fork_init(void) |
296 | { | 296 | { |
297 | int task_struct_size = arch_task_struct_size(); | ||
298 | #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR | 297 | #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR |
299 | #ifndef ARCH_MIN_TASKALIGN | 298 | #ifndef ARCH_MIN_TASKALIGN |
300 | #define ARCH_MIN_TASKALIGN L1_CACHE_BYTES | 299 | #define ARCH_MIN_TASKALIGN L1_CACHE_BYTES |
301 | #endif | 300 | #endif |
302 | /* create a slab on which task_structs can be allocated */ | 301 | /* create a slab on which task_structs can be allocated */ |
303 | task_struct_cachep = | 302 | task_struct_cachep = |
304 | kmem_cache_create("task_struct", task_struct_size, | 303 | kmem_cache_create("task_struct", arch_task_struct_size, |
305 | ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL); | 304 | ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL); |
306 | #endif | 305 | #endif |
307 | 306 | ||