mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-06 20:58:33 +01:00
htl: Add support for static TSD data
When using jemalloc, malloc() needs to use TSD, while libpthread initialization needs malloc(). Supporting a static TSD area allows jemalloc and libpthread to initialize together.
This commit is contained in:
parent
dcad5c8578
commit
644aa127b9
7 changed files with 98 additions and 19 deletions
|
@ -29,7 +29,16 @@ __pthread_destroy_specific (struct __pthread *thread)
|
||||||
|
|
||||||
/* Check if there is any thread specific data. */
|
/* Check if there is any thread specific data. */
|
||||||
if (thread->thread_specifics == NULL)
|
if (thread->thread_specifics == NULL)
|
||||||
return;
|
{
|
||||||
|
for (i = 0; i < PTHREAD_STATIC_KEYS; i++)
|
||||||
|
{
|
||||||
|
if (thread->static_thread_specifics[i] != NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == PTHREAD_STATIC_KEYS)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
__pthread_key_lock_ready ();
|
__pthread_key_lock_ready ();
|
||||||
|
|
||||||
|
@ -40,18 +49,32 @@ __pthread_destroy_specific (struct __pthread *thread)
|
||||||
|
|
||||||
__pthread_mutex_lock (&__pthread_key_lock);
|
__pthread_mutex_lock (&__pthread_key_lock);
|
||||||
|
|
||||||
for (i = 0; i < __pthread_key_count && i < thread->thread_specifics_size;
|
for (i = 0; i < __pthread_key_count; i++)
|
||||||
i++)
|
|
||||||
{
|
{
|
||||||
void *value;
|
void *value;
|
||||||
|
|
||||||
if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID)
|
if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
value = thread->thread_specifics[i];
|
if (thread->thread_specifics == NULL)
|
||||||
|
{
|
||||||
|
if (i >= PTHREAD_STATIC_KEYS)
|
||||||
|
break;
|
||||||
|
value = thread->static_thread_specifics[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (i >= thread->thread_specifics_size)
|
||||||
|
break;
|
||||||
|
value = thread->thread_specifics[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (value != NULL)
|
if (value != NULL)
|
||||||
{
|
{
|
||||||
thread->thread_specifics[i] = 0;
|
if (thread->thread_specifics == NULL)
|
||||||
|
thread->static_thread_specifics[i] = 0;
|
||||||
|
else
|
||||||
|
thread->thread_specifics[i] = 0;
|
||||||
|
|
||||||
if (__pthread_key_destructors[i])
|
if (__pthread_key_destructors[i])
|
||||||
{
|
{
|
||||||
|
@ -74,4 +97,6 @@ __pthread_destroy_specific (struct __pthread *thread)
|
||||||
free (thread->thread_specifics);
|
free (thread->thread_specifics);
|
||||||
thread->thread_specifics = 0;
|
thread->thread_specifics = 0;
|
||||||
thread->thread_specifics_size = 0;
|
thread->thread_specifics_size = 0;
|
||||||
|
memset (&thread->static_thread_specifics, 0,
|
||||||
|
sizeof (thread->static_thread_specifics));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,14 @@ __pthread_getspecific (pthread_key_t key)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
self = _pthread_self ();
|
self = _pthread_self ();
|
||||||
|
|
||||||
|
if (self->thread_specifics == NULL)
|
||||||
|
{
|
||||||
|
if (key >= PTHREAD_STATIC_KEYS)
|
||||||
|
return NULL;
|
||||||
|
return self->static_thread_specifics[key];
|
||||||
|
}
|
||||||
|
|
||||||
if (key >= self->thread_specifics_size)
|
if (key >= self->thread_specifics_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -26,5 +26,7 @@ __pthread_init_specific (struct __pthread *thread)
|
||||||
{
|
{
|
||||||
thread->thread_specifics = 0;
|
thread->thread_specifics = 0;
|
||||||
thread->thread_specifics_size = 0;
|
thread->thread_specifics_size = 0;
|
||||||
|
memset (&thread->static_thread_specifics, 0,
|
||||||
|
sizeof (thread->static_thread_specifics));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,11 @@
|
||||||
pthread_mutex_t __pthread_key_lock;
|
pthread_mutex_t __pthread_key_lock;
|
||||||
pthread_once_t __pthread_key_once = PTHREAD_ONCE_INIT;
|
pthread_once_t __pthread_key_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
void (**__pthread_key_destructors) (void *arg);
|
void (*__pthread_static_key_destructors [PTHREAD_STATIC_KEYS]) (void *arg);
|
||||||
int __pthread_key_size;
|
void (**__pthread_key_destructors) (void *arg) = __pthread_static_key_destructors;
|
||||||
|
int __pthread_key_size = PTHREAD_STATIC_KEYS;
|
||||||
int __pthread_key_count;
|
int __pthread_key_count;
|
||||||
int __pthread_key_invalid_count;
|
int __pthread_key_invalid_count = PTHREAD_STATIC_KEYS;
|
||||||
|
|
||||||
int
|
int
|
||||||
__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
|
__pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
|
||||||
|
@ -80,13 +81,21 @@ do_search:
|
||||||
void *t;
|
void *t;
|
||||||
int newsize;
|
int newsize;
|
||||||
|
|
||||||
if (__pthread_key_size == 0)
|
newsize = __pthread_key_size * 2;
|
||||||
newsize = 8;
|
|
||||||
else
|
if (__pthread_key_destructors == __pthread_static_key_destructors)
|
||||||
newsize = __pthread_key_size * 2;
|
{
|
||||||
|
/* We were still using the static array. Switch to dynamic. */
|
||||||
|
t = malloc (newsize * sizeof (*__pthread_key_destructors));
|
||||||
|
|
||||||
|
if (t != NULL)
|
||||||
|
memcpy (t, __pthread_key_destructors,
|
||||||
|
__pthread_key_size * sizeof (*__pthread_key_destructors));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t = realloc (__pthread_key_destructors,
|
||||||
|
newsize * sizeof (*__pthread_key_destructors));
|
||||||
|
|
||||||
t = realloc (__pthread_key_destructors,
|
|
||||||
newsize * sizeof (*__pthread_key_destructors));
|
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
{
|
{
|
||||||
__pthread_mutex_unlock (&__pthread_key_lock);
|
__pthread_mutex_unlock (&__pthread_key_lock);
|
||||||
|
|
|
@ -51,8 +51,16 @@ __pthread_key_delete (pthread_key_t key)
|
||||||
|
|
||||||
/* Just remove the key, no need to care whether it was
|
/* Just remove the key, no need to care whether it was
|
||||||
already there. */
|
already there. */
|
||||||
if (key < t->thread_specifics_size)
|
if (t->thread_specifics == NULL)
|
||||||
t->thread_specifics[key] = 0;
|
{
|
||||||
|
if (key < PTHREAD_STATIC_KEYS)
|
||||||
|
t->static_thread_specifics[key] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (key < t->thread_specifics_size)
|
||||||
|
t->thread_specifics[key] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
__libc_rwlock_unlock (GL (dl_pthread_threads_lock));
|
__libc_rwlock_unlock (GL (dl_pthread_threads_lock));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,14 @@
|
||||||
#include <libc-lockP.h>
|
#include <libc-lockP.h>
|
||||||
#include <pthreadP.h>
|
#include <pthreadP.h>
|
||||||
|
|
||||||
|
/* When using e.g. jemalloc, we need to be able to create and use keys before
|
||||||
|
being able to allocate. */
|
||||||
|
#define PTHREAD_STATIC_KEYS 4
|
||||||
|
|
||||||
#define PTHREAD_KEY_MEMBERS \
|
#define PTHREAD_KEY_MEMBERS \
|
||||||
void **thread_specifics; /* This is only resized by the thread, and always growing */ \
|
void **thread_specifics; /* This is only resized by the thread, and always growing */ \
|
||||||
unsigned thread_specifics_size; /* Number of entries in thread_specifics */
|
unsigned thread_specifics_size; /* Number of entries in thread_specifics */ \
|
||||||
|
void *static_thread_specifics[PTHREAD_STATIC_KEYS]; /* Static storage for a few entries */
|
||||||
|
|
||||||
#define PTHREAD_KEY_INVALID (void *) (-1)
|
#define PTHREAD_KEY_INVALID (void *) (-1)
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,34 @@ __pthread_setspecific (pthread_key_t key, const void *value)
|
||||||
if (key < 0 || key >= __pthread_key_count)
|
if (key < 0 || key >= __pthread_key_count)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
if (self->thread_specifics == NULL)
|
||||||
|
{
|
||||||
|
if (key < PTHREAD_STATIC_KEYS)
|
||||||
|
{
|
||||||
|
self->static_thread_specifics[key] = (void *) value;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (key >= self->thread_specifics_size)
|
if (key >= self->thread_specifics_size)
|
||||||
{
|
{
|
||||||
/* Amortize reallocation cost. */
|
/* Amortize reallocation cost. */
|
||||||
int newsize = 2 * key + 1;
|
int newsize = 2 * key + 1;
|
||||||
void **new = realloc (self->thread_specifics,
|
void **new;
|
||||||
newsize * sizeof (new[0]));
|
|
||||||
|
if (self->thread_specifics == NULL)
|
||||||
|
{
|
||||||
|
self->thread_specifics_size = PTHREAD_STATIC_KEYS;
|
||||||
|
new = malloc (newsize * sizeof (new[0]));
|
||||||
|
if (new != NULL)
|
||||||
|
memcpy (new, self->static_thread_specifics,
|
||||||
|
PTHREAD_STATIC_KEYS * sizeof (new[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new = realloc (self->thread_specifics,
|
||||||
|
newsize * sizeof (new[0]));
|
||||||
|
}
|
||||||
if (new == NULL)
|
if (new == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue