From patchwork Mon Aug 7 21:11:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 21961 Received: (qmail 69941 invoked by alias); 7 Aug 2017 21:12:11 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 69713 invoked by uid 89); 7 Aug 2017 21:12:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-27.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-qt0-f181.google.com X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=hwcpiN9k08tG+LP72w7Rj0dlj2WMKWx8nb2CqZNfhho=; b=iOWYaSFPGd8hQQ76E16nlyHeJobgiKH1ZUMmxCMGaSO4wKvS+uX1pEoQjfkhiQ6z8n gKTLAhInZZXZcQVzWqJol/bkgp9My+1t7XzEr7a26ijWiNwtruUHM23EjQyfTbvOt2QI GJ1ntMHYdWrx4NgPCPMU0rVuKqsYJgDMCIL4vHwMqyKUSYHAIE98OXlypyXUivMfOA/8 BeKZE5P2mxXnMnOaf4mUUBSXtbgs0kKXV9Ie66A+yr2ta0hu2zDQCDmsgvwxrn5YlwBu kICR+OQLOz+E1G3yxACzqifwiEguVPm6Rw2kolabI3TAXlCEg6wgpDJfqfeB51223oLA W42Q== X-Gm-Message-State: AHYfb5jTiDBl5AFZp9OHqPkpGZNRd9NINb0uHEIKC+XSAiBU208+3rAs io+/AMP/ipuv3w9BUeH2pQ== X-Received: by 10.200.36.232 with SMTP id t37mr2887580qtt.273.1502140322408; Mon, 07 Aug 2017 14:12:02 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Subject: [PATCH 3/3] Single thread optimization refactor Date: Mon, 7 Aug 2017 18:11:54 -0300 Message-Id: <1502140314-16598-3-git-send-email-adhemerval.zanella@linaro.org> In-Reply-To: <1502140314-16598-1-git-send-email-adhemerval.zanella@linaro.org> References: <1502140314-16598-1-git-send-email-adhemerval.zanella@linaro.org> Current GLIBC uses the define TLS_MULTIPLE_THREADS_IN_TCB to whether declare or not the global variables used for the single thread optimization for cancellable syscalls (STOCS). ALthough it does work correctly, this is not the correct define since there are architectures that do not define TLS_MULTIPLE_THREADS_IN_TCB but does not use the global variables (by prefering accessing the TCB/pthread_t fields instead). With single thread optimization for cancellable syscalls refactored by using SINGLE_THREAD_BY_GLOBAL define, we can use it instead to define where the __{libc,pthread}_multiple_threads is defined. This is based on my "Remove sysdep-cancel assembly macro" patchset [1]. Checked on x86_64-linux-gnu and on a build with major touched ABis (aarch64-linux-gnu, alpha-linux-gnu, arm-linux-gnueabihf, hppa-linux-gnu, i686-linux-gnu, m68k-linux-gnu, microblaze-linux-gnu, mips-linux-gnu, mips64-linux-gnu, powerpc-linux-gnu, powerpc64le-linux-gnu, s390-linux-gnu, s390x-linux-gnu, sh4-linux-gnu, sparcv9-linux-gnu, sparc64-linux-gnu, tilegx-linux-gnu). * nptl/allocatestack.c (allocate_state): Use SET_SINGLE_THREAD_PTHREAD macro. * nptl/pthread_cancel.c (__pthread_cancel): Likewise. * nptl/libc_multiple_threads.c (__libc_multiple_threads): Define for libc and SINGLE_THREAD_BY_GLOBAL. * nptl/libc_pthread_init.c (__libc_pthread_init): Use same signature whether SINGLE_THREAD_BY_GLOBAL is set or not. * nptl/pthreadP.h (__libc_pthread_init): Likewise. * nptl/nptl-init.c (__libc_multiple_threads_ptr): Use MULTIPLE_THREADS_PTR_DEF. (__pthread_initialize_minimal_internal): Use MULTIPLE_THREADS_PTR_SET macro. * nptl/vars.c (__pthread_multiple_threads): Define for libpthread and SINGLE_THREAD_BY_GLOBAL. * sysdeps/unix/sysv/linux/sysdep-cancel.h (MULTIPLE_THREADS_PTR_DEF): Define. (MULTIPLE_THREADS_PTR_SET): Likewise. (SET_SINGLE_THREAD_PTHREAD): Likewise. [1] https://sourceware.org/ml/libc-alpha/2017-08/msg00095.html --- ChangeLog | 19 +++++++++++++++++++ nptl/allocatestack.c | 9 +++------ nptl/libc_multiple_threads.c | 4 +--- nptl/libc_pthread_init.c | 12 ++++-------- nptl/nptl-init.c | 14 +++++--------- nptl/pthreadP.h | 14 -------------- nptl/pthread_cancel.c | 7 +++---- nptl/vars.c | 12 ++++++------ sysdeps/unix/sysv/linux/sysdep-cancel.h | 27 +++++++++++++++++++++++++-- 9 files changed, 66 insertions(+), 52 deletions(-) diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index ce2e24a..89cb0de 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -32,6 +32,7 @@ #include #include #include +#include #ifndef NEED_SEPARATE_REGISTER_STACK @@ -456,9 +457,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, /* This is at least the second thread. */ pd->header.multiple_threads = 1; -#ifndef TLS_MULTIPLE_THREADS_IN_TCB - __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; -#endif + SET_SINGLE_THREAD_PTHREAD (1); #ifndef __ASSUME_PRIVATE_FUTEX /* The thread must know when private futexes are supported. */ @@ -576,9 +575,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, /* This is at least the second thread. */ pd->header.multiple_threads = 1; -#ifndef TLS_MULTIPLE_THREADS_IN_TCB - __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; -#endif + SET_SINGLE_THREAD_PTHREAD (1); #ifndef __ASSUME_PRIVATE_FUTEX /* The thread must know when private futexes are supported. */ diff --git a/nptl/libc_multiple_threads.c b/nptl/libc_multiple_threads.c index ef6a4be..1ae23e2 100644 --- a/nptl/libc_multiple_threads.c +++ b/nptl/libc_multiple_threads.c @@ -18,11 +18,9 @@ #include -#if IS_IN (libc) -# ifndef TLS_MULTIPLE_THREADS_IN_TCB +#if IS_IN (libc) && defined (SINGLE_THREAD_BY_GLOBAL) /* Variable set to a nonzero value either if more than one thread runs or ran, or if a single-threaded process is trying to cancel itself. See nptl/descr.h for more context on the single-threaded process case. */ int __libc_multiple_threads attribute_hidden; -# endif #endif diff --git a/nptl/libc_pthread_init.c b/nptl/libc_pthread_init.c index 0db7a10..aedd92f 100644 --- a/nptl/libc_pthread_init.c +++ b/nptl/libc_pthread_init.c @@ -26,18 +26,12 @@ #include #include #include - +#include unsigned long int *__fork_generation_pointer; -#ifdef TLS_MULTIPLE_THREADS_IN_TCB -void -#else -extern int __libc_multiple_threads attribute_hidden; - int * -#endif internal_function __libc_pthread_init (unsigned long int *ptr, void (*reclaim) (void), const struct pthread_functions *functions) @@ -74,8 +68,10 @@ __libc_pthread_init (unsigned long int *ptr, void (*reclaim) (void), __libc_pthread_functions_init = 1; #endif -#ifndef TLS_MULTIPLE_THREADS_IN_TCB +#ifdef SINGLE_THREAD_BY_GLOBAL return &__libc_multiple_threads; +# else + return NULL; #endif } diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c index 2921607..a1320f3 100644 --- a/nptl/nptl-init.c +++ b/nptl/nptl-init.c @@ -38,11 +38,9 @@ #include #include #include +#include -#ifndef TLS_MULTIPLE_THREADS_IN_TCB -/* Pointer to the corresponding variable in libc. */ -int *__libc_multiple_threads_ptr attribute_hidden; -#endif +MULTIPLE_THREADS_PTR_DEF; /* Size and alignment of static TLS block. */ size_t __static_tls_size; @@ -457,11 +455,9 @@ __pthread_initialize_minimal_internal (void) GL(dl_wait_lookup_done) = &__wait_lookup_done; /* Register the fork generation counter with the libc. */ -#ifndef TLS_MULTIPLE_THREADS_IN_TCB - __libc_multiple_threads_ptr = -#endif - __libc_pthread_init (&__fork_generation, __reclaim_stacks, - ptr_pthread_functions); + MULTIPLE_THREADS_PTR_SET (__libc_pthread_init (&__fork_generation, + __reclaim_stacks, + ptr_pthread_functions)); /* Determine whether the machine is SMP or not. */ __is_smp = is_smp_system (); diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 6e7d6ff..a79f0b2 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -384,25 +384,11 @@ hidden_proto (__nptl_create_event) hidden_proto (__nptl_death_event) /* Register the generation counter in the libpthread with the libc. */ -#ifdef TLS_MULTIPLE_THREADS_IN_TCB -extern void __libc_pthread_init (unsigned long int *ptr, - void (*reclaim) (void), - const struct pthread_functions *functions) - internal_function; -#else extern int *__libc_pthread_init (unsigned long int *ptr, void (*reclaim) (void), const struct pthread_functions *functions) internal_function; -/* Variable set to a nonzero value either if more than one thread runs or ran, - or if a single-threaded process is trying to cancel itself. See - nptl/descr.h for more context on the single-threaded process case. */ -extern int __pthread_multiple_threads attribute_hidden; -/* Pointer to the corresponding variable in libc. */ -extern int *__libc_multiple_threads_ptr attribute_hidden; -#endif - /* Find a thread given its TID. */ extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden #ifdef SHARED diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c index 742dfe6..f52ea08 100644 --- a/nptl/pthread_cancel.c +++ b/nptl/pthread_cancel.c @@ -19,10 +19,11 @@ #include #include #include -#include "pthreadP.h" #include #include #include +#include +#include int __pthread_cancel (pthread_t th) @@ -88,9 +89,7 @@ __pthread_cancel (pthread_t th) cannot. So we set multiple_threads to true so that cancellation points get executed. */ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); -#ifndef TLS_MULTIPLE_THREADS_IN_TCB - __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; -#endif + SET_SINGLE_THREAD_PTHREAD (1); } /* Mark the thread as canceled. This has to be done atomically since other bits could be modified as well. */ diff --git a/nptl/vars.c b/nptl/vars.c index 198f463..20ebcd5 100644 --- a/nptl/vars.c +++ b/nptl/vars.c @@ -30,14 +30,14 @@ int __default_pthread_attr_lock = LLL_LOCK_INITIALIZER; /* Flag whether the machine is SMP or not. */ int __is_smp attribute_hidden; -#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Table of the key information. */ +struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX] + __attribute__ ((nocommon)); +hidden_data_def (__pthread_keys) + +#if IS_IN (libpthread) && defined (SINGLE_THREAD_BY_GLOBAL) /* Variable set to a nonzero value either if more than one thread runs or ran, or if a single-threaded process is trying to cancel itself. See nptl/descr.h for more context on the single-threaded process case. */ int __pthread_multiple_threads attribute_hidden; #endif - -/* Table of the key information. */ -struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX] - __attribute__ ((nocommon)); -hidden_data_def (__pthread_keys) diff --git a/sysdeps/unix/sysv/linux/sysdep-cancel.h b/sysdeps/unix/sysv/linux/sysdep-cancel.h index 821114b..86044de 100644 --- a/sysdeps/unix/sysv/linux/sysdep-cancel.h +++ b/sysdeps/unix/sysv/linux/sysdep-cancel.h @@ -30,12 +30,24 @@ thread check to use global variables instead of the pthread_t field. */ #ifdef SINGLE_THREAD_BY_GLOBAL + +extern int __pthread_multiple_threads attribute_hidden; + +/* Variable set to a nonzero value either if more than one thread runs or ran, + or if a single-threaded process is trying to cancel itself. See + nptl/descr.h for more context on the single-threaded process case. */ +# define MULTIPLE_THREADS_PTR_DEF \ + int *__libc_multiple_threads_ptr attribute_hidden + +# define MULTIPLE_THREADS_PTR_SET(__ptr) \ + __libc_multiple_threads_ptr = (__ptr) + # if IS_IN (libc) -extern int __libc_multiple_threads; +extern int __libc_multiple_threads attribute_hidden; # define SINGLE_THREAD_P \ __glibc_likely (__libc_multiple_threads == 0) # elif IS_IN (libpthread) -extern int __pthread_multiple_threads; +extern int *__libc_multiple_threads_ptr attribute_hidden; # define SINGLE_THREAD_P \ __glibc_likely (__pthread_multiple_threads == 0) # elif IS_IN (librt) @@ -46,7 +58,16 @@ extern int __pthread_multiple_threads; /* For rtld, et cetera. */ # define SINGLE_THREAD_P (1) # endif + +# define SET_SINGLE_THREAD_PTHREAD(__value) \ + *__libc_multiple_threads_ptr = __pthread_multiple_threads = (__value) + #else + +# define MULTIPLE_THREADS_PTR_DEF + +# define MULTIPLE_THREADS_PTR_SET(__ptr) __ptr + # if IS_IN (libc) || IS_IN (libpthread) || IS_IN (librt) # define SINGLE_THREAD_P \ __glibc_likely (THREAD_GETMEM (THREAD_SELF, \ @@ -55,6 +76,8 @@ extern int __pthread_multiple_threads; /* For rtld, et cetera. */ # define SINGLE_THREAD_P (1) # endif + +# define SET_SINGLE_THREAD_PTHREAD(__value) #endif #define RTLD_SINGLE_THREAD_P \