aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/bionic/pthread_create.cpp2
-rw-r--r--libc/dns/resolv/res_state.c3
-rw-r--r--libc/private/bionic_tls.h28
-rw-r--r--tests/pthread_test.cpp25
-rw-r--r--tests/unistd_test.cpp2
5 files changed, 38 insertions, 22 deletions
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 8bb1be9d..c99e69c9 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -191,7 +191,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
191 // At offsets >= 0, we have the TLS slots. 191 // At offsets >= 0, we have the TLS slots.
192 // At offsets < 0, we have the child stack. 192 // At offsets < 0, we have the child stack.
193 thread->tls = reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(thread->attr.stack_base) + 193 thread->tls = reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(thread->attr.stack_base) +
194 thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*)); 194 thread->attr.stack_size - BIONIC_ALIGN(BIONIC_TLS_SLOTS * sizeof(void*), 16));
195 void* child_stack = thread->tls; 195 void* child_stack = thread->tls;
196 __init_tls(thread); 196 __init_tls(thread);
197 197
diff --git a/libc/dns/resolv/res_state.c b/libc/dns/resolv/res_state.c
index 57791d1b..75bff977 100644
--- a/libc/dns/resolv/res_state.c
+++ b/libc/dns/resolv/res_state.c
@@ -50,7 +50,6 @@
50#endif 50#endif
51 51
52static pthread_key_t _res_key; 52static pthread_key_t _res_key;
53static pthread_once_t _res_once = PTHREAD_ONCE_INIT;
54 53
55typedef struct { 54typedef struct {
56 int _h_errno; 55 int _h_errno;
@@ -105,6 +104,7 @@ _res_thread_free( void* _rt )
105 free(rt); 104 free(rt);
106} 105}
107 106
107__attribute__((constructor))
108static void 108static void
109_res_init_key( void ) 109_res_init_key( void )
110{ 110{
@@ -115,7 +115,6 @@ static _res_thread*
115_res_thread_get(void) 115_res_thread_get(void)
116{ 116{
117 _res_thread* rt; 117 _res_thread* rt;
118 pthread_once( &_res_once, _res_init_key );
119 rt = pthread_getspecific( _res_key ); 118 rt = pthread_getspecific( _res_key );
120 119
121 if (rt != NULL) { 120 if (rt != NULL) {
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 0c6e0623..4a351668 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -75,22 +75,40 @@ enum {
75 * enumerated above, and then there are those that are allocated during startup by calls to 75 * enumerated above, and then there are those that are allocated during startup by calls to
76 * pthread_key_create; grep for GLOBAL_INIT_THREAD_LOCAL_BUFFER to find those. We need to manually 76 * pthread_key_create; grep for GLOBAL_INIT_THREAD_LOCAL_BUFFER to find those. We need to manually
77 * maintain that second number, but pthread_test will fail if we forget. 77 * maintain that second number, but pthread_test will fail if we forget.
78 * Following are current pthread keys used internally:
79 * basename libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
80 * dirname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
81 * uselocale libc
82 * getmntent_mntent libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
83 * getmntent_strings libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
84 * ptsname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
85 * ttyname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
86 * strerror libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
87 * strsignal libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
88 * stubs libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
89 * _res_key libc
90 * je_thread_allocated_tsd jemalloc
91 * je_arenas_tsd jemalloc
92 * je_tcache_tsd jemalloc
93 * je_tcache_enabled_tsd jemalloc
94 * je_quarantine_tsd jemalloc
95 *
78 */ 96 */
79#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 9 97
98#define LIBC_TLS_RESERVED_SLOTS 11
80 99
81#if defined(USE_JEMALLOC) 100#if defined(USE_JEMALLOC)
82/* jemalloc uses 5 keys for itself. */ 101/* jemalloc uses 5 keys for itself. */
83#define BIONIC_TLS_RESERVED_SLOTS (GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT + 5) 102#define BIONIC_TLS_RESERVED_SLOTS (LIBC_TLS_RESERVED_SLOTS + 5)
84#else 103#else
85#define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 104#define BIONIC_TLS_RESERVED_SLOTS LIBC_TLS_RESERVED_SLOTS
86#endif 105#endif
87 106
88/* 107/*
89 * Maximum number of elements in the TLS array. 108 * Maximum number of elements in the TLS array.
90 * This includes space for pthread keys and our own internal slots. 109 * This includes space for pthread keys and our own internal slots.
91 * We need to round up to maintain stack alignment.
92 */ 110 */
93#define BIONIC_TLS_SLOTS BIONIC_ALIGN(PTHREAD_KEYS_MAX + TLS_SLOT_FIRST_USER_SLOT + BIONIC_TLS_RESERVED_SLOTS, 4) 111#define BIONIC_TLS_SLOTS (PTHREAD_KEYS_MAX + TLS_SLOT_FIRST_USER_SLOT + BIONIC_TLS_RESERVED_SLOTS)
94 112
95__END_DECLS 113__END_DECLS
96 114
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index f63d1ee9..4fc5bed5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -42,19 +42,19 @@ TEST(pthread, pthread_key_create) {
42} 42}
43 43
44TEST(pthread, pthread_keys_max) { 44TEST(pthread, pthread_keys_max) {
45 // POSIX says PTHREAD_KEYS_MAX should be at least 128. 45 // POSIX says PTHREAD_KEYS_MAX should be at least _POSIX_THREAD_KEYS_MAX.
46 ASSERT_GE(PTHREAD_KEYS_MAX, 128); 46 ASSERT_GE(PTHREAD_KEYS_MAX, _POSIX_THREAD_KEYS_MAX);
47} 47}
48 48
49TEST(pthread, _SC_THREAD_KEYS_MAX_big_enough_for_POSIX) { 49TEST(pthread, sysconf_SC_THREAD_KEYS_MAX_eq_PTHREAD_KEYS_MAX) {
50 // sysconf shouldn't return a smaller value.
51 int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX); 50 int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX);
52 ASSERT_GE(sysconf_max, PTHREAD_KEYS_MAX); 51 ASSERT_EQ(sysconf_max, PTHREAD_KEYS_MAX);
53} 52}
54 53
55TEST(pthread, pthread_key_many_distinct) { 54TEST(pthread, pthread_key_many_distinct) {
56 // We should be able to allocate at least this many keys. 55 // As gtest uses pthread keys, we can't allocate exactly PTHREAD_KEYS_MAX
57 int nkeys = sysconf(_SC_THREAD_KEYS_MAX) / 2; 56 // pthread keys, but We should be able to allocate at least this many keys.
57 int nkeys = PTHREAD_KEYS_MAX / 2;
58 std::vector<pthread_key_t> keys; 58 std::vector<pthread_key_t> keys;
59 59
60 auto scope_guard = make_scope_guard([&keys]{ 60 auto scope_guard = make_scope_guard([&keys]{
@@ -80,14 +80,13 @@ TEST(pthread, pthread_key_many_distinct) {
80 } 80 }
81} 81}
82 82
83TEST(pthread, pthread_key_EAGAIN) { 83TEST(pthread, pthread_key_not_exceed_PTHREAD_KEYS_MAX) {
84 int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX);
85
86 std::vector<pthread_key_t> keys; 84 std::vector<pthread_key_t> keys;
87 int rv = 0; 85 int rv = 0;
88 // Two keys are used by gtest, so sysconf_max should be more than we are 86
89 // allowed to allocate now. 87 // Pthread keys are used by gtest, so PTHREAD_KEYS_MAX should
90 for (int i = 0; i < sysconf_max; i++) { 88 // be more than we are allowed to allocate now.
89 for (int i = 0; i < PTHREAD_KEYS_MAX; i++) {
91 pthread_key_t key; 90 pthread_key_t key;
92 rv = pthread_key_create(&key, NULL); 91 rv = pthread_key_create(&key, NULL);
93 if (rv == EAGAIN) { 92 if (rv == EAGAIN) {
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 96d66e48..f5c0524c 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -576,7 +576,7 @@ TEST(unistd, _POSIX_macros_smoke) {
576 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE); 576 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
577 EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime. 577 EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime.
578 EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0); 578 EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
579 EXPECT_GT(_POSIX_THREAD_KEYS_MAX, 0); 579 EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
580 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING); 580 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
581 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_INHERIT); 581 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_INHERIT);
582 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_PROTECT); 582 EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_PROTECT);