Fix pthread key num calculation.
Bug: 18723085 Change-Id: Iba2c834b350e4cdba0b2d771b221560a3e5df952
This commit is contained in:
parent
6d634f9baa
commit
6c238f2926
@ -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 TLS slots.
|
||||||
// At offsets < 0, we have the child stack.
|
// At offsets < 0, we have the child stack.
|
||||||
thread->tls = reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(thread->attr.stack_base) +
|
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;
|
void* child_stack = thread->tls;
|
||||||
__init_tls(thread);
|
__init_tls(thread);
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static pthread_key_t _res_key;
|
static pthread_key_t _res_key;
|
||||||
static pthread_once_t _res_once = PTHREAD_ONCE_INIT;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int _h_errno;
|
int _h_errno;
|
||||||
@ -105,6 +104,7 @@ _res_thread_free( void* _rt )
|
|||||||
free(rt);
|
free(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((constructor))
|
||||||
static void
|
static void
|
||||||
_res_init_key( void )
|
_res_init_key( void )
|
||||||
{
|
{
|
||||||
@ -115,7 +115,6 @@ static _res_thread*
|
|||||||
_res_thread_get(void)
|
_res_thread_get(void)
|
||||||
{
|
{
|
||||||
_res_thread* rt;
|
_res_thread* rt;
|
||||||
pthread_once( &_res_once, _res_init_key );
|
|
||||||
rt = pthread_getspecific( _res_key );
|
rt = pthread_getspecific( _res_key );
|
||||||
|
|
||||||
if (rt != NULL) {
|
if (rt != NULL) {
|
||||||
|
@ -75,22 +75,40 @@ enum {
|
|||||||
* enumerated above, and then there are those that are allocated during startup by calls to
|
* 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
|
* 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.
|
* 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)
|
#if defined(USE_JEMALLOC)
|
||||||
/* jemalloc uses 5 keys for itself. */
|
/* 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
|
#else
|
||||||
#define BIONIC_TLS_RESERVED_SLOTS GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT
|
#define BIONIC_TLS_RESERVED_SLOTS LIBC_TLS_RESERVED_SLOTS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of elements in the TLS array.
|
* Maximum number of elements in the TLS array.
|
||||||
* This includes space for pthread keys and our own internal slots.
|
* 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
|
__END_DECLS
|
||||||
|
|
||||||
|
@ -42,19 +42,19 @@ TEST(pthread, pthread_key_create) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(pthread, pthread_keys_max) {
|
TEST(pthread, pthread_keys_max) {
|
||||||
// POSIX says PTHREAD_KEYS_MAX should be at least 128.
|
// POSIX says PTHREAD_KEYS_MAX should be at least _POSIX_THREAD_KEYS_MAX.
|
||||||
ASSERT_GE(PTHREAD_KEYS_MAX, 128);
|
ASSERT_GE(PTHREAD_KEYS_MAX, _POSIX_THREAD_KEYS_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pthread, _SC_THREAD_KEYS_MAX_big_enough_for_POSIX) {
|
TEST(pthread, sysconf_SC_THREAD_KEYS_MAX_eq_PTHREAD_KEYS_MAX) {
|
||||||
// sysconf shouldn't return a smaller value.
|
|
||||||
int sysconf_max = sysconf(_SC_THREAD_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) {
|
TEST(pthread, pthread_key_many_distinct) {
|
||||||
// We should be able to allocate at least this many keys.
|
// As gtest uses pthread keys, we can't allocate exactly PTHREAD_KEYS_MAX
|
||||||
int nkeys = sysconf(_SC_THREAD_KEYS_MAX) / 2;
|
// 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;
|
std::vector<pthread_key_t> keys;
|
||||||
|
|
||||||
auto scope_guard = make_scope_guard([&keys]{
|
auto scope_guard = make_scope_guard([&keys]{
|
||||||
@ -80,14 +80,13 @@ TEST(pthread, pthread_key_many_distinct) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(pthread, pthread_key_EAGAIN) {
|
TEST(pthread, pthread_key_not_exceed_PTHREAD_KEYS_MAX) {
|
||||||
int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX);
|
|
||||||
|
|
||||||
std::vector<pthread_key_t> keys;
|
std::vector<pthread_key_t> keys;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
// Two keys are used by gtest, so sysconf_max should be more than we are
|
|
||||||
// allowed to allocate now.
|
// Pthread keys are used by gtest, so PTHREAD_KEYS_MAX should
|
||||||
for (int i = 0; i < sysconf_max; i++) {
|
// be more than we are allowed to allocate now.
|
||||||
|
for (int i = 0; i < PTHREAD_KEYS_MAX; i++) {
|
||||||
pthread_key_t key;
|
pthread_key_t key;
|
||||||
rv = pthread_key_create(&key, NULL);
|
rv = pthread_key_create(&key, NULL);
|
||||||
if (rv == EAGAIN) {
|
if (rv == EAGAIN) {
|
||||||
|
@ -576,7 +576,7 @@ TEST(unistd, _POSIX_macros_smoke) {
|
|||||||
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
|
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
|
||||||
EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime.
|
EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime.
|
||||||
EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
|
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_PRIORITY_SCHEDULING);
|
||||||
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_INHERIT);
|
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_INHERIT);
|
||||||
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_PROTECT);
|
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIO_PROTECT);
|
||||||
|
Loading…
Reference in New Issue
Block a user