Fix pthread key num calculation.
Bug: 18723085
Change-Id: Iba2c834b350e4cdba0b2d771b221560a3e5df952
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 8bb1be9..c99e69c 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -191,7 +191,7 @@
// At offsets >= 0, we have the TLS slots.
// At offsets < 0, we have the child stack.
thread->tls = reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(thread->attr.stack_base) +
- thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
+ thread->attr.stack_size - BIONIC_ALIGN(BIONIC_TLS_SLOTS * sizeof(void*), 16));
void* child_stack = thread->tls;
__init_tls(thread);
diff --git a/libc/dns/resolv/res_state.c b/libc/dns/resolv/res_state.c
index 57791d1..75bff97 100644
--- a/libc/dns/resolv/res_state.c
+++ b/libc/dns/resolv/res_state.c
@@ -50,7 +50,6 @@
#endif
static pthread_key_t _res_key;
-static pthread_once_t _res_once = PTHREAD_ONCE_INIT;
typedef struct {
int _h_errno;
@@ -105,6 +104,7 @@
free(rt);
}
+__attribute__((constructor))
static void
_res_init_key( void )
{
@@ -115,7 +115,6 @@
_res_thread_get(void)
{
_res_thread* rt;
- pthread_once( &_res_once, _res_init_key );
rt = pthread_getspecific( _res_key );
if (rt != NULL) {
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 0c6e062..4a35166 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -75,22 +75,40 @@
* enumerated above, and then there are those that are allocated during startup by calls to
* pthread_key_create; grep for GLOBAL_INIT_THREAD_LOCAL_BUFFER to find those. We need to manually
* maintain that second number, but pthread_test will fail if we forget.
+ * Following are current pthread keys used internally:
+ * basename libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * dirname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * uselocale libc
+ * getmntent_mntent libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * getmntent_strings libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * ptsname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * ttyname libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * strerror libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * strsignal libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * stubs libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ * _res_key libc
+ * je_thread_allocated_tsd jemalloc
+ * je_arenas_tsd jemalloc
+ * je_tcache_tsd jemalloc
+ * je_tcache_enabled_tsd jemalloc
+ * je_quarantine_tsd jemalloc
+ *
*/
-#define GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT 9
+
+#define LIBC_TLS_RESERVED_SLOTS 11
#if defined(USE_JEMALLOC)
/* jemalloc uses 5 keys for itself. */
-#define BIONIC_TLS_RESERVED_SLOTS (GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT + 5)
+#define BIONIC_TLS_RESERVED_SLOTS (LIBC_TLS_RESERVED_SLOTS + 5)
#else
-#define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
+#define BIONIC_TLS_RESERVED_SLOTS LIBC_TLS_RESERVED_SLOTS
#endif
/*
* Maximum number of elements in the TLS array.
* This includes space for pthread keys and our own internal slots.
- * We need to round up to maintain stack alignment.
*/
-#define BIONIC_TLS_SLOTS BIONIC_ALIGN(PTHREAD_KEYS_MAX + TLS_SLOT_FIRST_USER_SLOT + BIONIC_TLS_RESERVED_SLOTS, 4)
+#define BIONIC_TLS_SLOTS (PTHREAD_KEYS_MAX + TLS_SLOT_FIRST_USER_SLOT + BIONIC_TLS_RESERVED_SLOTS)
__END_DECLS
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index f63d1ee..4fc5bed 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -42,19 +42,19 @@
}
TEST(pthread, pthread_keys_max) {
- // POSIX says PTHREAD_KEYS_MAX should be at least 128.
- ASSERT_GE(PTHREAD_KEYS_MAX, 128);
+ // POSIX says PTHREAD_KEYS_MAX should be at least _POSIX_THREAD_KEYS_MAX.
+ ASSERT_GE(PTHREAD_KEYS_MAX, _POSIX_THREAD_KEYS_MAX);
}
-TEST(pthread, _SC_THREAD_KEYS_MAX_big_enough_for_POSIX) {
- // sysconf shouldn't return a smaller value.
+TEST(pthread, sysconf_SC_THREAD_KEYS_MAX_eq_PTHREAD_KEYS_MAX) {
int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX);
- ASSERT_GE(sysconf_max, PTHREAD_KEYS_MAX);
+ ASSERT_EQ(sysconf_max, PTHREAD_KEYS_MAX);
}
TEST(pthread, pthread_key_many_distinct) {
- // We should be able to allocate at least this many keys.
- int nkeys = sysconf(_SC_THREAD_KEYS_MAX) / 2;
+ // As gtest uses pthread keys, we can't allocate exactly PTHREAD_KEYS_MAX
+ // pthread keys, but We should be able to allocate at least this many keys.
+ int nkeys = PTHREAD_KEYS_MAX / 2;
std::vector<pthread_key_t> keys;
auto scope_guard = make_scope_guard([&keys]{
@@ -80,14 +80,13 @@
}
}
-TEST(pthread, pthread_key_EAGAIN) {
- int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX);
-
+TEST(pthread, pthread_key_not_exceed_PTHREAD_KEYS_MAX) {
std::vector<pthread_key_t> keys;
int rv = 0;
- // Two keys are used by gtest, so sysconf_max should be more than we are
- // allowed to allocate now.
- for (int i = 0; i < sysconf_max; i++) {
+
+ // Pthread keys are used by gtest, so PTHREAD_KEYS_MAX should
+ // be more than we are allowed to allocate now.
+ for (int i = 0; i < PTHREAD_KEYS_MAX; i++) {
pthread_key_t key;
rv = pthread_key_create(&key, NULL);
if (rv == EAGAIN) {
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 96d66e4..f5c0524 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -576,7 +576,7 @@
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime.
EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
- EXPECT_GT(_POSIX_THREAD_KEYS_MAX, 0);
+ EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_INHERIT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_PROTECT);