Projects
Factory:RISC-V:Base
glibc
_service:tar_scm:0006-add-elsion-function-which...
Sign Up
Log In
Username
Password
Sorry, you are not authorized to perform this action.
×
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch of Package glibc
From 1cdbe579482c07e9f4bb3baa4864da2d3e7eb837 Mon Sep 17 00:00:00 2001 From: Andi Kleen <ak@linux.intel.com> Date: Sat, 10 Nov 2012 00:51:26 -0800i Subject: [PATCH 6/9] build extra lipthreadcond so add elsion functions which moved to libc in glibc-2.34. Some attributes are changed and cannot be directly referenced. --- nptl_2_17/lll_timedlock_wait_2_17.c | 59 +++++++++++++++++++++++++++++ nptl_2_17/elision-conf_2_17.c | 138 +++++++++++++++++++++++++++++++ nptl_2_17/elision-lock_2_17.c | 107 ++++++++++++++++++++++++ nptl_2_17/elision-timed_2_17.c | 27 ++++++ nptl_2_17/elision-trylock_2_17.c | 75 +++++++++++++++++ nptl_2_17/elision-unlock_2_17.c | 34 ++++++++ nptl_2_17/hle_2_17.h | 75 +++++++++++++++++ 6 files changed, 515 insertions(+) create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c create mode 100644 nptl_2_17/elision-conf_2_17.c create mode 100644 nptl_2_17/elision-lock_2_17.c create mode 100644 nptl_2_17/elision-timed_2_17.c create mode 100644 nptl_2_17/elision-trylock_2_17.c create mode 100644 nptl_2_17/elision-unlock_2_17.c create mode 100644 nptl_2_17/hle_2_17.h diff --git a/nptl_2_17/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c new file mode 100644 index 00000000..91bf9637 --- /dev/null +++ b/nptl_2_17/lll_timedlock_wait_2_17.c @@ -0,0 +1,59 @@ +/* Timed low level locking for pthread library. Generic futex-using version. + Copyright (C) 2003-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <atomic.h> +#include <errno.h> +#include <lowlevellock.h> +#include <sys/time.h> + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Try locking. */ + while (atomic_exchange_acq (futex, 2) != 0) + { + struct timeval tv; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* If *futex == 2, wait until woken or timeout. */ + lll_futex_timed_wait (futex, 2, &rt, private); + } + + return 0; +} diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c new file mode 100644 index 00000000..22af2944 --- /dev/null +++ b/nptl_2_17/elision-conf_2_17.c @@ -0,0 +1,138 @@ +/* elision-conf.c: Lock elision tunable parameters. + Copyright (C) 2013-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include <pthreadP.h> +#include <init-arch.h> +#include <elision-conf.h> +#include <unistd.h> + +#if HAVE_TUNABLES +# define TUNABLE_NAMESPACE elision +#endif +#include <elf/dl-tunables.h> + +/* Reasonable initial tuning values, may be revised in the future. + This is a conservative initial value. */ + +struct elision_config __elision_aconf = + { + /* How often to not attempt to use elision if a transaction aborted + because the lock is already acquired. Expressed in number of lock + acquisition attempts. */ + .skip_lock_busy = 3, + /* How often to not attempt to use elision if a transaction aborted due + to reasons other than other threads' memory accesses. Expressed in + number of lock acquisition attempts. */ + .skip_lock_internal_abort = 3, + /* How often we retry using elision if there is chance for the transaction + to finish execution (e.g., it wasn't aborted due to the lock being + already acquired. */ + .retry_try_xbegin = 3, + /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */ + .skip_trylock_internal_abort = 3, + }; + +/* Force elision for all new locks. This is used to decide whether existing + DEFAULT locks should be automatically upgraded to elision in + pthread_mutex_lock(). Disabled for suid programs. Only used when elision + is available. */ + +int __pthread_force_elision attribute_hidden = 0; + +#if HAVE_TUNABLES +static inline void +__always_inline +do_set_elision_enable (int32_t elision_enable) +{ + /* Enable elision if it's avaliable in hardware. It's not necessary to check + if __libc_enable_secure isn't enabled since elision_enable will be set + according to the default, which is disabled. */ + if (elision_enable == 1) + __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0; +} + +/* The pthread->elision_enable tunable is 0 or 1 indicating that elision + should be disabled or enabled respectively. The feature will only be used + if it's supported by the hardware. */ + +void +TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp) +{ + int32_t elision_enable = (int32_t) valp->numval; + do_set_elision_enable (elision_enable); +} + +#define TUNABLE_CALLBACK_FNDECL(__name, __type) \ +static inline void \ +__always_inline \ +do_set_elision_ ## __name (__type value) \ +{ \ + __elision_aconf.__name = value; \ +} \ +void \ +TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \ +{ \ + __type value = (__type) (valp)->numval; \ + do_set_elision_ ## __name (value); \ +} + +TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t); +TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t); +TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t); +TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t); +#endif + +/* Initialize elision. */ + +static void +elision_init (int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused)), + char **environ) +{ +#if HAVE_TUNABLES + /* Elision depends on tunables and must be explicitly turned on by setting + the appropriate tunable on a supported platform. */ + + TUNABLE_GET (enable, int32_t, + TUNABLE_CALLBACK (set_elision_enable)); + TUNABLE_GET (skip_lock_busy, int32_t, + TUNABLE_CALLBACK (set_elision_skip_lock_busy)); + TUNABLE_GET (skip_lock_internal_abort, int32_t, + TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort)); + TUNABLE_GET (tries, int32_t, + TUNABLE_CALLBACK (set_elision_retry_try_xbegin)); + TUNABLE_GET (skip_trylock_internal_abort, int32_t, + TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); +#endif + + if (!__pthread_force_elision) + __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */ +} + +#ifdef SHARED +# define INIT_SECTION ".init_array" +#else +# define INIT_SECTION ".preinit_array" +#endif + +void (*const __pthread_init_array []) (int, char **, char **) + __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) = +{ + &elision_init +}; diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c new file mode 100644 index 00000000..e6dbbc21 --- /dev/null +++ b/nptl_2_17/elision-lock_2_17.c @@ -0,0 +1,107 @@ +/* elision-lock.c: Elided pthread mutex lock. + Copyright (C) 2011-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <pthread_2_17.h> +#include "pthreadP_2_17.h" +#include "lowlevellock.h" +#include "hle_2_17.h" +#include <elision-conf.h> + +#if !defined(LLL_LOCK) && !defined(EXTRAARG) +/* Make sure the configuration code is always linked in for static + libraries. */ +#include "elision-conf_2_17.c" +#endif + +#ifndef EXTRAARG +#define EXTRAARG +#endif +#ifndef LLL_LOCK +#define LLL_LOCK(a,b) lll_lock(a,b), 0 +#endif + +#define aconf __elision_aconf + +/* Adaptive lock using transactions. + By default the lock region is run as a transaction, and when it + aborts or the lock is busy the lock adapts itself. */ + +int +__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private) +{ + /* adapt_count can be accessed concurrently; these accesses can be both + inside of transactions (if critical sections are nested and the outer + critical section uses lock elision) and outside of transactions. Thus, + we need to use atomic accesses to avoid data races. However, the + value of adapt_count is just a hint, so relaxed MO accesses are + sufficient. */ + if (atomic_load_relaxed (adapt_count) <= 0) + { + unsigned status; + int try_xbegin; + + for (try_xbegin = aconf.retry_try_xbegin; + try_xbegin > 0; + try_xbegin--) + { + if ((status = _xbegin()) == _XBEGIN_STARTED) + { + if (*futex == 0) + return 0; + + /* Lock was busy. Fall back to normal locking. + Could also _xend here but xabort with 0xff code + is more visible in the profiler. */ + _xabort (_ABORT_LOCK_BUSY); + } + + if (!(status & _XABORT_RETRY)) + { + if ((status & _XABORT_EXPLICIT) + && _XABORT_CODE (status) == _ABORT_LOCK_BUSY) + { + /* Right now we skip here. Better would be to wait a bit + and retry. This likely needs some spinning. See + above for why relaxed MO is sufficient. */ + if (atomic_load_relaxed (adapt_count) + != aconf.skip_lock_busy) + atomic_store_relaxed (adapt_count, aconf.skip_lock_busy); + } + /* Internal abort. There is no chance for retry. + Use the normal locking and next time use lock. + Be careful to avoid writing to the lock. See above for why + relaxed MO is sufficient. */ + else if (atomic_load_relaxed (adapt_count) + != aconf.skip_lock_internal_abort) + atomic_store_relaxed (adapt_count, + aconf.skip_lock_internal_abort); + break; + } + } + } + else + { + /* Use a normal lock until the threshold counter runs out. + Lost updates possible. */ + atomic_store_relaxed (adapt_count, + atomic_load_relaxed (adapt_count) - 1); + } + + /* Use a normal lock here. */ + return LLL_LOCK ((*futex), private); +} diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c new file mode 100644 index 00000000..5050f2d1 --- /dev/null +++ b/nptl_2_17/elision-timed_2_17.c @@ -0,0 +1,27 @@ +/* elision-timed.c: Lock elision timed lock. + Copyright (C) 2013-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <time.h> +#include <elision-conf.h> +#include "lowlevellock.h" +#include <old_macros_2_17.h> +#define __lll_lock_elision __lll_timedlock_elision +#define EXTRAARG const struct timespec *t, +#undef LLL_LOCK +#define LLL_LOCK(a, b) lll_timedlock(a, t, b) +#include "elision-lock_2_17.c" diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c new file mode 100644 index 00000000..70d8f8b9 --- /dev/null +++ b/nptl_2_17/elision-trylock_2_17.c @@ -0,0 +1,75 @@ +/* elision-trylock.c: Lock eliding trylock for pthreads. + Copyright (C) 2013-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <pthread_2_17.h> + +#include <lowlevellock.h> +#include "hle_2_17.h" +#include <elision-conf.h> + +#define aconf __elision_aconf + +/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is + the adaptation counter in the mutex. */ + +int +__lll_trylock_elision (int *futex, short *adapt_count) +{ + /* Implement POSIX semantics by forbiding nesting + trylock. Sorry. After the abort the code is re-executed + non transactional and if the lock was already locked + return an error. */ + _xabort (_ABORT_NESTED_TRYLOCK); + + /* Only try a transaction if it's worth it. See __lll_lock_elision for + why we need atomic accesses. Relaxed MO is sufficient because this is + just a hint. */ + if (atomic_load_relaxed (adapt_count) <= 0) + { + unsigned status; + + if ((status = _xbegin()) == _XBEGIN_STARTED) + { + if (*futex == 0) + return 0; + + /* Lock was busy. Fall back to normal locking. + Could also _xend here but xabort with 0xff code + is more visible in the profiler. */ + _xabort (_ABORT_LOCK_BUSY); + } + + if (!(status & _XABORT_RETRY)) + { + /* Internal abort. No chance for retry. For future + locks don't try speculation for some time. See above for MO. */ + if (atomic_load_relaxed (adapt_count) + != aconf.skip_lock_internal_abort) + atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort); + } + /* Could do some retries here. */ + } + else + { + /* Lost updates are possible but harmless (see above). */ + atomic_store_relaxed (adapt_count, + atomic_load_relaxed (adapt_count) - 1); + } + + return lll_trylock (*futex); +} diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c new file mode 100644 index 00000000..b5d38c5f --- /dev/null +++ b/nptl_2_17/elision-unlock_2_17.c @@ -0,0 +1,34 @@ +/* elision-unlock.c: Commit an elided pthread lock. + Copyright (C) 2013-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include "pthreadP_2_17.h" +#include "lowlevellock.h" +#include "hle_2_17.h" +#include <old_macros_2_17.h> + +int +__lll_unlock_elision(int *lock, int private) +{ + /* When the lock was free we're in a transaction. + When you crash here you unlocked a free lock. */ + if (*lock == 0) + _xend(); + else + lll_unlock ((*lock), private); + return 0; +} diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h new file mode 100644 index 00000000..4a7b9e3b --- /dev/null +++ b/nptl_2_17/hle_2_17.h @@ -0,0 +1,75 @@ +/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers + that do not support the intrinsics and instructions yet. */ +#ifndef _HLE_H +#define _HLE_H 1 + +#ifdef __ASSEMBLER__ + +.macro XBEGIN target + .byte 0xc7,0xf8 + .long \target-1f +1: +.endm + +.macro XEND + .byte 0x0f,0x01,0xd5 +.endm + +.macro XABORT code + .byte 0xc6,0xf8,\code +.endm + +.macro XTEST + .byte 0x0f,0x01,0xd6 +.endm + +#endif + +/* Official RTM intrinsics interface matching gcc/icc, but works + on older gcc compatible compilers and binutils. + We should somehow detect if the compiler supports it, because + it may be able to generate slightly better code. */ + +#define _XBEGIN_STARTED (~0u) +#define _XABORT_EXPLICIT (1 << 0) +#define _XABORT_RETRY (1 << 1) +#define _XABORT_CONFLICT (1 << 2) +#define _XABORT_CAPACITY (1 << 3) +#define _XABORT_DEBUG (1 << 4) +#define _XABORT_NESTED (1 << 5) +#define _XABORT_CODE(x) (((x) >> 24) & 0xff) + +#define _ABORT_LOCK_BUSY 0xff +#define _ABORT_LOCK_IS_LOCKED 0xfe +#define _ABORT_NESTED_TRYLOCK 0xfd + +#ifndef __ASSEMBLER__ + +#define __force_inline __attribute__((__always_inline__)) inline + +static __force_inline int _xbegin(void) +{ + int ret = _XBEGIN_STARTED; + asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory"); + return ret; +} + +static __force_inline void _xend(void) +{ + asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory"); +} + +static __force_inline void _xabort(const unsigned int status) +{ + asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); +} + +static __force_inline int _xtest(void) +{ + unsigned char out; + asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory"); + return out; +} + +#endif +#endif -- 2.30.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2