Fix pthread key num calculation.
authorYabin Cui <yabinc@google.com>
Fri, 12 Dec 2014 04:50:41 +0000 (20:50 -0800)
committerYabin Cui <yabinc@google.com>
Sat, 13 Dec 2014 01:00:08 +0000 (17:00 -0800)
Bug: 18723085
Change-Id: Iba2c834b350e4cdba0b2d771b221560a3e5df952

libc/bionic/pthread_create.cpp
libc/dns/resolv/res_state.c
libc/private/bionic_tls.h
tests/pthread_test.cpp
tests/unistd_test.cpp

index 8bb1be9d9e0289dac26c9ce483e7fda92812b0b8..c99e69c90fcc42ead98099c11542daf190040370 100644 (file)
@@ -191,7 +191,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
   // 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);
 
index 57791d1b9195bb527bc898e86467ee3075332e61..75bff97751b9a04184a1fd8b2be3d8a6759803f6 100644 (file)
@@ -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 @@ _res_thread_free( void*  _rt )
     free(rt);
 }
 
+__attribute__((constructor))
 static void
 _res_init_key( void )
 {
@@ -115,7 +115,6 @@ static _res_thread*
 _res_thread_get(void)
 {
     _res_thread*  rt;
-    pthread_once( &_res_once, _res_init_key );
     rt = pthread_getspecific( _res_key );
 
     if (rt != NULL) {
index 0c6e062393754cbca5e5ea9a95d2a35170c9cad5..4a3516683f116f91d439d57518d73481145e8bfe 100644 (file)
@@ -75,22 +75,40 @@ enum {
  * 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
 
index f63d1ee93e79a7eac2e1ed5bee48a190836be465..4fc5bed51fcaf1d7773d08ef8f95aaaa1f569814 100644 (file)
@@ -42,19 +42,19 @@ TEST(pthread, pthread_key_create) {
 }
 
 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_many_distinct) {
   }
 }
 
-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) {
index 96d66e48d6ff061b54413075f38cc38dc5574852..f5c0524c4d14d1ef82ac936ee102e180f67b0a70 100644 (file)
@@ -576,7 +576,7 @@ TEST(unistd, _POSIX_macros_smoke) {
   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);