From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757302AbbGQJbd (ORCPT ); Fri, 17 Jul 2015 05:31:33 -0400 Received: from mail-wi0-f180.google.com ([209.85.212.180]:36130 "EHLO mail-wi0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753728AbbGQJbb (ORCPT ); Fri, 17 Jul 2015 05:31:31 -0400 Date: Fri, 17 Jul 2015 11:31:25 +0200 From: Ingo Molnar To: Dave Hansen Cc: Andy Lutomirski , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , X86 ML , Peter Zijlstra , Borislav Petkov , Linus Torvalds , "linux-kernel@vger.kernel.org" Subject: [PATCH] x86/fpu, sched: Introduce CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and use it on x86 Message-ID: <20150717093125.GA4394@gmail.com> References: <20150716191437.A334FF2E@viggo.jf.intel.com> <55A8221E.8030108@sr71.net> <20150717084527.GC16130@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150717084527.GC16130@gmail.com> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org * Ingo Molnar wrote: > > * Dave Hansen wrote: > > > >> #endif /* _ASM_X86_FPU_H */ > > >> diff -puN arch/x86/kernel/process.c~dynamically-allocate-struct-fpu arch/x86/kernel/process.c > > >> --- a/arch/x86/kernel/process.c~dynamically-allocate-struct-fpu 2015-07-16 10:50:42.360571875 -0700 > > >> +++ b/arch/x86/kernel/process.c 2015-07-16 12:00:59.204808551 -0700 > > >> @@ -81,7 +81,7 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregist > > >> */ > > >> int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) > > >> { > > >> - *dst = *src; > > >> + memcpy(dst, src, arch_task_struct_size()); > > > > > > This is actually vaguely performance-critical, which makes me thing > > > that using some kind of inline or other real way (config macro, ifdef, > > > etc) to detect whether there's an arch override would be better than a > > > weak function. > > > > Fair enough. I'll send out another version in a bit if there are no more > > comments. > > Beyond making it a build time switch for other architectures, I'd also suggest > introducing a __read_mostly task_struct_size variable on x86, so that we can > write: > > memcpy(dst, src, task_struct_size); I.e. like the patch below, on top of your patch plus the bug.h patch I sent. Only build tested. Thanks, Ingo ======================> >>From ab5da866792e4297de2308b42121633419f6d06d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Fri, 17 Jul 2015 11:27:36 +0200 Subject: [PATCH] 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. Cc: Dave Hansen Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: bp@alien8.de Cc: luto@amacapital.net Signed-off-by: Ingo Molnar --- arch/Kconfig | 4 ++++ arch/x86/Kconfig | 1 + arch/x86/kernel/fpu/init.c | 9 ++++++--- arch/x86/kernel/process.c | 2 +- fs/proc/kcore.c | 4 ++-- include/linux/sched.h | 4 +++- kernel/fork.c | 21 ++++++++------------- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index bec6666a3cc4..dd6867885c73 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -221,6 +221,10 @@ config ARCH_TASK_STRUCT_ALLOCATOR config ARCH_THREAD_INFO_ALLOCATOR bool +# Select if arch wants to size task_struct dynamically +config ARCH_WANTS_DYNAMIC_TASK_STRUCT + bool + config HAVE_REGS_AND_STACK_ACCESS_API bool help diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6b03b716302..1e1d0e8ac9b6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -41,6 +41,7 @@ config X86 select ARCH_USE_CMPXCHG_LOCKREF if X86_64 select ARCH_USE_QUEUED_RWLOCKS select ARCH_USE_QUEUED_SPINLOCKS + select ARCH_WANTS_DYNAMIC_TASK_STRUCT select ARCH_WANT_FRAME_POINTERS select ARCH_WANT_IPC_PARSE_VERSION if X86_32 select ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c index 36de0ebdb957..5401243430ee 100644 --- a/arch/x86/kernel/fpu/init.c +++ b/arch/x86/kernel/fpu/init.c @@ -4,6 +4,8 @@ #include #include +#include + /* * Initialize the TS bit in CR0 according to the style of context-switches * we are using: @@ -137,9 +139,9 @@ unsigned int xstate_size; EXPORT_SYMBOL_GPL(xstate_size); /* - * We append the 'struct fpu' to the task_struct. + * We append the 'struct fpu' to the task_struct: */ -int arch_task_struct_size(void) +static void __init fpu__init_task_struct_size(void) { int task_size = sizeof(struct task_struct); @@ -159,7 +161,7 @@ int arch_task_struct_size(void) CHECK_MEMBER_AT_END_OF(struct fpu, state); CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); - return task_size; + task_struct_size = task_size; } /* @@ -313,6 +315,7 @@ void __init fpu__init_system(struct cpuinfo_x86 *c) fpu__init_system_generic(); fpu__init_system_xstate_size_legacy(); fpu__init_system_xstate(); + fpu__init_task_struct_size(); fpu__init_system_ctx_switch(); } diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 975420eac105..ae6a315cfa73 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -81,7 +81,7 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister); */ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { - memcpy(dst, src, arch_task_struct_size()); + memcpy(dst, src, task_struct_size); return fpu__copy(&dst->thread.fpu, &src->thread.fpu); } diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index a0fe99485687..1cfa1127c9dd 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) roundup(sizeof(CORE_STR), 4)) + roundup(sizeof(struct elf_prstatus), 4) + roundup(sizeof(struct elf_prpsinfo), 4) + - roundup(arch_task_struct_size(), 4); + roundup(task_struct_size, 4); *elf_buflen = PAGE_ALIGN(*elf_buflen); return size + *elf_buflen; } @@ -415,7 +415,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff) /* set up the task structure */ notes[2].name = CORE_STR; notes[2].type = NT_TASKSTRUCT; - notes[2].datasz = arch_task_struct_size(); + notes[2].datasz = task_struct_size; notes[2].data = current; nhdr->p_filesz += notesize(¬es[2]); diff --git a/include/linux/sched.h b/include/linux/sched.h index e43a41d892b6..d0504bb9f12a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1786,7 +1786,9 @@ struct task_struct { */ }; -extern int arch_task_struct_size(void); +#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT +extern int task_struct_size __read_mostly; +#endif /* Future-safe accessor for struct task_struct's cpus_allowed. */ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) diff --git a/kernel/fork.c b/kernel/fork.c index 9f84b1aa3dbf..cfbe24ddf3eb 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -287,14 +287,15 @@ static void set_max_threads(unsigned int max_threads_suggested) max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); } -#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ - BUILD_BUG_ON(sizeof(TYPE) != offsetofend(TYPE, MEMBER)) +#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT +/* Initialized by the architecture: */ +int task_struct_size __read_mostly; +#else +/* Static build time size: */ +static const int task_struct_size = sizeof(struct task_struct); +#endif -/* - * This function can be overridden by the architecture to support dynamic sizing - * of the task_struct: - */ -int __weak arch_task_struct_size(void) +void __init fork_init(void) { /* * Build-time checks for structure layout constraints: @@ -307,12 +308,6 @@ int __weak arch_task_struct_size(void) */ CHECK_MEMBER_AT_END_OF(struct task_struct, thread); - return sizeof(struct task_struct); -} - -void __init fork_init(void) -{ - int task_struct_size = arch_task_struct_size(); #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR #ifndef ARCH_MIN_TASKALIGN #define ARCH_MIN_TASKALIGN L1_CACHE_BYTES