From 6782806d8f6664d87d17bb30f8ce4e0c7c931e17 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Sat, 17 Oct 2015 12:06:48 +0200 Subject: [PATCH] malloc: Rewrite with explicit TLS access using __thread --- ChangeLog | 22 ++++++++++++++ malloc/arena.c | 48 ++++++++++++------------------ manual/memory.texi | 4 --- sysdeps/generic/malloc-machine.h | 7 ----- sysdeps/mach/hurd/malloc-machine.h | 10 ------- sysdeps/nptl/malloc-machine.h | 10 ------- 6 files changed, 41 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 123f34cf8d..eeee6d69ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2015-10-17 Florian Weimer + + malloc: Rewrite with explicit TLS access using __thread. + * sysdeps/generic/malloc-machine.h (tsd_key_t, tsd_key_create) + (tsd_setspecific, tsd_getspecific): Remove. + * sysdeps/mach/hurd/malloc-machine.h (tsd_key_t, tsd_key_create) + (tsd_setspecific, tsd_getspecific): Likewise. + * sysdeps/nptl/malloc-machine.h (tsd_key_t, tsd_key_create) + (tsd_setspecific, tsd_getspecific): Likewise. + * malloc/arena.c (thread_arena): New TLS variable. + (arena_key): Remove variable. + (arena_get): Use thread_arena. + (arena_lookup): Remove macro. + (malloc_atfork, free_atfork, ptmalloc_lock_all) + (ptmalloc_unlock_all, ptmalloc_unlock_all2, ptmalloc_init) + (_int_new_arena, get_free_list, reused_arena) + (arena_thread_freeres): Use thread_arena. + * manual/memory.texi (Basic Allocation): Remove arena_lookup, + tsd_getspecific, tsd_setspecific from safety annotations. + (Allocating Cleared Space): Remove arena_lookup from safety + annotations. + 2015-10-17 Florian Weimer * stdio-common/vfprintf.c (printf_positional): Rewrite to use diff --git a/malloc/arena.c b/malloc/arena.c index cb45a048cd..caf718de10 100644 --- a/malloc/arena.c +++ b/malloc/arena.c @@ -64,9 +64,12 @@ extern int sanity_check_heap_info_alignment[(sizeof (heap_info) + 2 * SIZE_SZ) % MALLOC_ALIGNMENT ? -1 : 1]; -/* Thread specific data */ +/* Thread specific data. */ + +static __thread mstate thread_arena attribute_tls_model_ie; + +/* Arena free list. */ -static tsd_key_t arena_key; static mutex_t list_lock = MUTEX_INITIALIZER; static size_t narenas = 1; static mstate free_list; @@ -89,15 +92,10 @@ int __malloc_initialized = -1; in the new arena. */ #define arena_get(ptr, size) do { \ - arena_lookup (ptr); \ + ptr = thread_arena; \ arena_lock (ptr, size); \ } while (0) -#define arena_lookup(ptr) do { \ - void *vptr = NULL; \ - ptr = (mstate) tsd_getspecific (arena_key, vptr); \ - } while (0) - #define arena_lock(ptr, size) do { \ if (ptr && !arena_is_corrupt (ptr)) \ (void) mutex_lock (&ptr->mutex); \ @@ -138,11 +136,9 @@ ATFORK_MEM; static void * malloc_atfork (size_t sz, const void *caller) { - void *vptr = NULL; void *victim; - tsd_getspecific (arena_key, vptr); - if (vptr == ATFORK_ARENA_PTR) + if (thread_arena == ATFORK_ARENA_PTR) { /* We are the only thread that may allocate at all. */ if (save_malloc_hook != malloc_check) @@ -172,7 +168,6 @@ malloc_atfork (size_t sz, const void *caller) static void free_atfork (void *mem, const void *caller) { - void *vptr = NULL; mstate ar_ptr; mchunkptr p; /* chunk corresponding to mem */ @@ -188,8 +183,7 @@ free_atfork (void *mem, const void *caller) } ar_ptr = arena_for_chunk (p); - tsd_getspecific (arena_key, vptr); - _int_free (ar_ptr, p, vptr == ATFORK_ARENA_PTR); + _int_free (ar_ptr, p, thread_arena == ATFORK_ARENA_PTR); } @@ -212,9 +206,7 @@ ptmalloc_lock_all (void) if (mutex_trylock (&list_lock)) { - void *my_arena; - tsd_getspecific (arena_key, my_arena); - if (my_arena == ATFORK_ARENA_PTR) + if (thread_arena == ATFORK_ARENA_PTR) /* This is the same thread which already locks the global list. Just bump the counter. */ goto out; @@ -234,8 +226,8 @@ ptmalloc_lock_all (void) __malloc_hook = malloc_atfork; __free_hook = free_atfork; /* Only the current thread may perform malloc/free calls now. */ - tsd_getspecific (arena_key, save_arena); - tsd_setspecific (arena_key, ATFORK_ARENA_PTR); + save_arena = thread_arena; + thread_arena = ATFORK_ARENA_PTR; out: ++atfork_recursive_cntr; } @@ -251,7 +243,7 @@ ptmalloc_unlock_all (void) if (--atfork_recursive_cntr != 0) return; - tsd_setspecific (arena_key, save_arena); + thread_arena = save_arena; __malloc_hook = save_malloc_hook; __free_hook = save_free_hook; for (ar_ptr = &main_arena;; ) @@ -279,7 +271,7 @@ ptmalloc_unlock_all2 (void) if (__malloc_initialized < 1) return; - tsd_setspecific (arena_key, save_arena); + thread_arena = save_arena; __malloc_hook = save_malloc_hook; __free_hook = save_free_hook; free_list = NULL; @@ -372,8 +364,7 @@ ptmalloc_init (void) __morecore = __failing_morecore; #endif - tsd_key_create (&arena_key, NULL); - tsd_setspecific (arena_key, (void *) &main_arena); + thread_arena = &main_arena; thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2); const char *s = NULL; if (__glibc_likely (_environ != NULL)) @@ -761,7 +752,7 @@ _int_new_arena (size_t size) set_head (top (a), (((char *) h + h->size) - ptr) | PREV_INUSE); LIBC_PROBE (memory_arena_new, 2, a, size); - tsd_setspecific (arena_key, (void *) a); + thread_arena = a; mutex_init (&a->mutex); (void) mutex_lock (&a->mutex); @@ -794,7 +785,7 @@ get_free_list (void) { LIBC_PROBE (memory_arena_reuse_free_list, 1, result); (void) mutex_lock (&result->mutex); - tsd_setspecific (arena_key, (void *) result); + thread_arena = result; } } @@ -847,7 +838,7 @@ reused_arena (mstate avoid_arena) out: LIBC_PROBE (memory_arena_reuse, 2, result, avoid_arena); - tsd_setspecific (arena_key, (void *) result); + thread_arena = result; next_to_use = result->next; return result; @@ -934,9 +925,8 @@ arena_get_retry (mstate ar_ptr, size_t bytes) static void __attribute__ ((section ("__libc_thread_freeres_fn"))) arena_thread_freeres (void) { - void *vptr = NULL; - mstate a = tsd_getspecific (arena_key, vptr); - tsd_setspecific (arena_key, NULL); + mstate a = thread_arena; + thread_arena = NULL; if (a != NULL) { diff --git a/manual/memory.texi b/manual/memory.texi index 0729e702db..cea2cd7ba7 100644 --- a/manual/memory.texi +++ b/manual/memory.texi @@ -332,8 +332,6 @@ this function is in @file{stdlib.h}. @c __libc_malloc @asulock @aculock @acsfd @acsmem @c force_reg ok @c *malloc_hook unguarded -@c arena_lookup ok -@c tsd_getspecific ok, TLS @c arena_lock @asulock @aculock @acsfd @acsmem @c mutex_lock @asulock @aculock @c arena_get2 @asulock @aculock @acsfd @acsmem @@ -341,7 +339,6 @@ this function is in @file{stdlib.h}. @c mutex_lock (list_lock) dup @asulock @aculock @c mutex_unlock (list_lock) dup @aculock @c mutex_lock (arena lock) dup @asulock @aculock [returns locked] -@c tsd_setspecific ok, TLS @c __get_nprocs ext ok @acsfd @c NARENAS_FROM_NCORES ok @c catomic_compare_and_exchange_bool_acq ok @@ -835,7 +832,6 @@ is declared in @file{stdlib.h}. @c *__malloc_hook dup unguarded @c memset dup ok @c arena_get @asulock @aculock @acsfd @acsmem -@c arena_lookup dup ok @c arena_lock dup @asulock @aculock @acsfd @acsmem @c top dup ok @c chunksize dup ok diff --git a/sysdeps/generic/malloc-machine.h b/sysdeps/generic/malloc-machine.h index 10f6e72eb2..802d1f5b43 100644 --- a/sysdeps/generic/malloc-machine.h +++ b/sysdeps/generic/malloc-machine.h @@ -40,13 +40,6 @@ typedef int mutex_t; # define mutex_unlock(m) (*(m) = 0) # define MUTEX_INITIALIZER (0) -typedef void *tsd_key_t; -# define tsd_key_create(key, destr) do {} while(0) -# define tsd_setspecific(key, data) ((key) = (data)) -# define tsd_getspecific(key, vptr) (vptr = (key)) - -# define thread_atfork(prepare, parent, child) do {} while(0) - #endif /* !defined mutex_init */ #ifndef atomic_full_barrier diff --git a/sysdeps/mach/hurd/malloc-machine.h b/sysdeps/mach/hurd/malloc-machine.h index 1fdbd3de93..9221d1b459 100644 --- a/sysdeps/mach/hurd/malloc-machine.h +++ b/sysdeps/mach/hurd/malloc-machine.h @@ -52,16 +52,6 @@ /* No we're *not* using pthreads. */ #define __pthread_initialize ((void (*)(void))0) -/* thread specific data for glibc */ - -#include - -typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ -__libc_tsd_define (static, void *, MALLOC) /* declaration/common definition */ -#define tsd_key_create(key, destr) ((void) (key)) -#define tsd_setspecific(key, data) __libc_tsd_set (void *, MALLOC, (data)) -#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (void *, MALLOC)) - /* madvise is a stub on Hurd, so don't bother calling it. */ #include diff --git a/sysdeps/nptl/malloc-machine.h b/sysdeps/nptl/malloc-machine.h index c0ec49ee56..8dea606f5e 100644 --- a/sysdeps/nptl/malloc-machine.h +++ b/sysdeps/nptl/malloc-machine.h @@ -58,16 +58,6 @@ extern void *__dso_handle __attribute__ ((__weak__)); __linkin_atfork (&atfork_mem) #endif -/* thread specific data for glibc */ - -#include - -typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ -__libc_tsd_define (static, void *, MALLOC) /* declaration/common definition */ -#define tsd_key_create(key, destr) ((void) (key)) -#define tsd_setspecific(key, data) __libc_tsd_set (void *, MALLOC, (data)) -#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (void *, MALLOC)) - #include #endif /* !defined(_MALLOC_MACHINE_H) */ -- 2.43.5