Allocate thread local buffers in __init_tls.
Thread local buffers were using pthread_setspecific for storage with
lazy initialization. pthread_setspecific shares TLS slots between the
linker and libc.so, so thread local buffers being initialized in a
different order between libc.so and the linker meant that bad things
would happen (manifesting as snprintf not working because the
locale was mangled)
Bug: http://b/20464031
Test: /data/nativetest64/bionic-unit-tests/bionic-unit-tests
everything passes
Test: /data/nativetest/bionic-unit-tests/bionic-unit-tests
thread_local tests are failing both before and after (KUSER_HELPERS?)
Test: /data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static
no additional failures
Change-Id: I9f445a77c6e86979f3fa49c4a5feecf6ec2b0c3f
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index c61e2ff..852b9ae 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -29,10 +29,15 @@
#ifndef __BIONIC_PRIVATE_BIONIC_TLS_H_
#define __BIONIC_PRIVATE_BIONIC_TLS_H_
+#include <locale.h>
+#include <mntent.h>
+#include <stdio.h>
#include <sys/cdefs.h>
+#include <sys/param.h>
#include "bionic_macros.h"
#include "__get_tls.h"
+#include "grp_pwd.h"
__BEGIN_DECLS
@@ -77,6 +82,28 @@
BIONIC_TLS_SLOTS // Must come last!
};
+// ~3 pages.
+struct bionic_tls {
+ locale_t locale;
+
+ char basename_buf[MAXPATHLEN];
+ char dirname_buf[MAXPATHLEN];
+
+ mntent mntent_buf;
+ char mntent_strings[BUFSIZ];
+
+ char ptsname_buf[32];
+ char ttyname_buf[64];
+
+ char strerror_buf[NL_TEXTMAX];
+ char strsignal_buf[NL_TEXTMAX];
+
+ group_state_t group;
+ passwd_state_t passwd;
+};
+
+#define BIONIC_TLS_SIZE (BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE))
+
/*
* Bionic uses some pthread keys internally. All pthread keys used internally
* should be created in constructors, except for keys that may be used in or
@@ -86,22 +113,10 @@
* pthread_test should fail if we forget.
*
* These are the pthread keys currently used internally by libc:
- *
- * basename libc (ThreadLocalBuffer)
- * dirname libc (ThreadLocalBuffer)
- * uselocale libc (can be used in constructors)
- * getmntent_mntent libc (ThreadLocalBuffer)
- * getmntent_strings libc (ThreadLocalBuffer)
- * ptsname libc (ThreadLocalBuffer)
- * ttyname libc (ThreadLocalBuffer)
- * strerror libc (ThreadLocalBuffer)
- * strsignal libc (ThreadLocalBuffer)
- * passwd libc (ThreadLocalBuffer)
- * group libc (ThreadLocalBuffer)
* _res_key libc (constructor in BSD code)
*/
-#define LIBC_PTHREAD_KEY_RESERVED_COUNT 12
+#define LIBC_PTHREAD_KEY_RESERVED_COUNT 1
/* Internally, jemalloc uses a single key for per thread data. */
#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1