From: Stan Shebs Date: Mon, 12 Mar 2018 21:59:51 +0000 (-0700) Subject: Forward-port addition of __google_pthread_signal_safe_key_create X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=491d419cdde1d5ded66dda5d08016cd014f8d655;p=thirdparty%2Fglibc.git Forward-port addition of __google_pthread_signal_safe_key_create --- diff --git a/nptl/Versions b/nptl/Versions index 0ae5def464b..eeca21b6010 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -266,6 +266,7 @@ libpthread { } GLIBC_PRIVATE { + __google_pthread_signal_safe_key_create; __pthread_initialize_minimal; __pthread_clock_gettime; __pthread_clock_settime; __pthread_unwind; __pthread_get_minstack; diff --git a/nptl/pthread_key_create.c b/nptl/pthread_key_create.c index 0c0e53c44ad..4ff1e05c8d2 100644 --- a/nptl/pthread_key_create.c +++ b/nptl/pthread_key_create.c @@ -18,31 +18,52 @@ #include #include "pthreadP.h" +#include #include +static int +claim_key (pthread_key_t *key, void (*destr) (void *), size_t cnt) +{ + uintptr_t seq = __pthread_keys[cnt].seq; + if (KEY_UNUSED (seq) && KEY_USABLE (seq) + /* We found an unused slot. Try to allocate it. */ + && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq, + seq + 1, seq)) + { + /* Remember the destructor. */ + __pthread_keys[cnt].destr = destr; + + /* Return the key to the caller. */ + *key = cnt; + return 0; + } + return -1; +} int __pthread_key_create (pthread_key_t *key, void (*destr) (void *)) { /* Find a slot in __pthread_keys which is unused. */ - for (size_t cnt = 0; cnt < PTHREAD_KEYS_MAX; ++cnt) + for (size_t cnt = PTHREAD_SIGNAL_SAFE_KEYS_MAX; cnt < PTHREAD_KEYS_MAX; ++cnt) + { + if (claim_key (key, destr, cnt) == 0) + return 0; + } + + return EAGAIN; +} + +int __google_pthread_signal_safe_key_create ( + pthread_key_t *key, void (*destr) (void *)) +{ + /* Our implementation makes signal safe keys easy: they just have to + reside in the first (inline) block. */ + assert (PTHREAD_SIGNAL_SAFE_KEYS_MAX <= PTHREAD_KEY_1STLEVEL_SIZE); + /* Find a slot in __pthread_keys which is unused. */ + for (size_t cnt = 0; cnt < PTHREAD_SIGNAL_SAFE_KEYS_MAX; ++cnt) { - uintptr_t seq = __pthread_keys[cnt].seq; - - if (KEY_UNUSED (seq) && KEY_USABLE (seq) - /* We found an unused slot. Try to allocate it. */ - && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq, - seq + 1, seq)) - { - /* Remember the destructor. */ - __pthread_keys[cnt].destr = destr; - - /* Return the key to the caller. */ - *key = cnt; - - /* The call succeeded. */ - return 0; - } + if (claim_key (key, destr, cnt) == 0) + return 0; } return EAGAIN; diff --git a/nptl/tst-key1.c b/nptl/tst-key1.c index 8227f9e843d..3fc7487bcd4 100644 --- a/nptl/tst-key1.c +++ b/nptl/tst-key1.c @@ -33,7 +33,11 @@ do_test (void) { int max; #ifdef PTHREAD_KEYS_MAX +#ifdef PTHREAD_SIGNAL_SAFE_KEYS_MAX + max = PTHREAD_KEYS_MAX - PTHREAD_SIGNAL_SAFE_KEYS_MAX; +#else max = PTHREAD_KEYS_MAX; +#endif #else max = _POSIX_THREAD_KEYS_MAX; #endif diff --git a/nptl/tst-key4.c b/nptl/tst-key4.c index 810f25b3709..aa795f4a3c4 100644 --- a/nptl/tst-key4.c +++ b/nptl/tst-key4.c @@ -24,7 +24,11 @@ #ifdef PTHREAD_KEYS_MAX +#ifdef PTHREAD_SIGNAL_SAFE_KEYS_MAX +const int max = PTHREAD_KEYS_MAX - PTHREAD_SIGNAL_SAFE_KEYS_MAX; +#else const int max = PTHREAD_KEYS_MAX; +#endif #else const int max = _POSIX_THREAD_KEYS_MAX; #endif diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h index df049abf74d..fa125e0e609 100644 --- a/sysdeps/nptl/pthread.h +++ b/sysdeps/nptl/pthread.h @@ -1113,6 +1113,20 @@ extern int pthread_key_create (pthread_key_t *__key, void (*__destr_function) (void *)) __THROW __nonnull ((1)); +/* Exactly as pthread_key_create, but returns an async-signal-safe key: + getspecific, setspecific, and key_delete are async-signal-safe when + used with the returned key. The number of signal_safe keys is *extremely* + limited (PTHREAD_SIGNAL_SAFE_KEY_MAX); you are highly recommended to use + pthread_key_create unless it's absolutely necessary. This function + is async-signal-safe. */ +#if !defined(IS_IN_libpthread) +__attribute__((weak)) +#endif +extern int __google_pthread_signal_safe_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __THROW __nonnull ((1)); + + /* Destroy KEY. */ extern int pthread_key_delete (pthread_key_t __key) __THROW; diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/local_lim.h b/sysdeps/unix/sysv/linux/aarch64/bits/local_lim.h index 37aab9a24dd..43286195c34 100644 --- a/sysdeps/unix/sysv/linux/aarch64/bits/local_lim.h +++ b/sysdeps/unix/sysv/linux/aarch64/bits/local_lim.h @@ -63,6 +63,7 @@ #define _POSIX_THREAD_KEYS_MAX 128 /* This is the value this implementation supports. */ #define PTHREAD_KEYS_MAX 1024 +#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4 /* Controlling the iterations of destructors for thread-specific data. */ #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 diff --git a/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h index 7805fa510ea..904bb5c574a 100644 --- a/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h +++ b/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -62,6 +62,7 @@ #define _POSIX_THREAD_KEYS_MAX 128 /* This is the value this implementation supports. */ #define PTHREAD_KEYS_MAX 1024 +#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4 /* Controlling the iterations of destructors for thread-specific data. */ #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 diff --git a/sysdeps/unix/sysv/linux/bits/local_lim.h b/sysdeps/unix/sysv/linux/bits/local_lim.h index 2d82ada43cc..ae2d914b77b 100644 --- a/sysdeps/unix/sysv/linux/bits/local_lim.h +++ b/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -62,6 +62,7 @@ #define _POSIX_THREAD_KEYS_MAX 128 /* This is the value this implementation supports. */ #define PTHREAD_KEYS_MAX 1024 +#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4 /* Controlling the iterations of destructors for thread-specific data. */ #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h b/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h index 049094e4671..dfcf7288845 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h @@ -62,6 +62,7 @@ #define _POSIX_THREAD_KEYS_MAX 128 /* This is the value this implementation supports. */ #define PTHREAD_KEYS_MAX 1024 +#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4 /* Controlling the iterations of destructors for thread-specific data. */ #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 diff --git a/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h index a7ec88e1915..954650ed4a0 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -62,6 +62,7 @@ #define _POSIX_THREAD_KEYS_MAX 128 /* This is the value this implementation supports. */ #define PTHREAD_KEYS_MAX 1024 +#define PTHREAD_SIGNAL_SAFE_KEYS_MAX 4 /* Controlling the iterations of destructors for thread-specific data. */ #define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4