mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 08:11:08 +00:00
malloc: Rewrite with explicit TLS access using __thread
This commit is contained in:
parent
db8ad8fac3
commit
6782806d8f
22
ChangeLog
22
ChangeLog
@ -1,3 +1,25 @@
|
|||||||
|
2015-10-17 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
|
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 <fweimer@redhat.com>
|
2015-10-17 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* stdio-common/vfprintf.c (printf_positional): Rewrite to use
|
* stdio-common/vfprintf.c (printf_positional): Rewrite to use
|
||||||
|
@ -64,9 +64,12 @@ extern int sanity_check_heap_info_alignment[(sizeof (heap_info)
|
|||||||
+ 2 * SIZE_SZ) % MALLOC_ALIGNMENT
|
+ 2 * SIZE_SZ) % MALLOC_ALIGNMENT
|
||||||
? -1 : 1];
|
? -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 mutex_t list_lock = MUTEX_INITIALIZER;
|
||||||
static size_t narenas = 1;
|
static size_t narenas = 1;
|
||||||
static mstate free_list;
|
static mstate free_list;
|
||||||
@ -89,15 +92,10 @@ int __malloc_initialized = -1;
|
|||||||
in the new arena. */
|
in the new arena. */
|
||||||
|
|
||||||
#define arena_get(ptr, size) do { \
|
#define arena_get(ptr, size) do { \
|
||||||
arena_lookup (ptr); \
|
ptr = thread_arena; \
|
||||||
arena_lock (ptr, size); \
|
arena_lock (ptr, size); \
|
||||||
} while (0)
|
} 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 { \
|
#define arena_lock(ptr, size) do { \
|
||||||
if (ptr && !arena_is_corrupt (ptr)) \
|
if (ptr && !arena_is_corrupt (ptr)) \
|
||||||
(void) mutex_lock (&ptr->mutex); \
|
(void) mutex_lock (&ptr->mutex); \
|
||||||
@ -138,11 +136,9 @@ ATFORK_MEM;
|
|||||||
static void *
|
static void *
|
||||||
malloc_atfork (size_t sz, const void *caller)
|
malloc_atfork (size_t sz, const void *caller)
|
||||||
{
|
{
|
||||||
void *vptr = NULL;
|
|
||||||
void *victim;
|
void *victim;
|
||||||
|
|
||||||
tsd_getspecific (arena_key, vptr);
|
if (thread_arena == ATFORK_ARENA_PTR)
|
||||||
if (vptr == ATFORK_ARENA_PTR)
|
|
||||||
{
|
{
|
||||||
/* We are the only thread that may allocate at all. */
|
/* We are the only thread that may allocate at all. */
|
||||||
if (save_malloc_hook != malloc_check)
|
if (save_malloc_hook != malloc_check)
|
||||||
@ -172,7 +168,6 @@ malloc_atfork (size_t sz, const void *caller)
|
|||||||
static void
|
static void
|
||||||
free_atfork (void *mem, const void *caller)
|
free_atfork (void *mem, const void *caller)
|
||||||
{
|
{
|
||||||
void *vptr = NULL;
|
|
||||||
mstate ar_ptr;
|
mstate ar_ptr;
|
||||||
mchunkptr p; /* chunk corresponding to mem */
|
mchunkptr p; /* chunk corresponding to mem */
|
||||||
|
|
||||||
@ -188,8 +183,7 @@ free_atfork (void *mem, const void *caller)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ar_ptr = arena_for_chunk (p);
|
ar_ptr = arena_for_chunk (p);
|
||||||
tsd_getspecific (arena_key, vptr);
|
_int_free (ar_ptr, p, thread_arena == ATFORK_ARENA_PTR);
|
||||||
_int_free (ar_ptr, p, vptr == ATFORK_ARENA_PTR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -212,9 +206,7 @@ ptmalloc_lock_all (void)
|
|||||||
|
|
||||||
if (mutex_trylock (&list_lock))
|
if (mutex_trylock (&list_lock))
|
||||||
{
|
{
|
||||||
void *my_arena;
|
if (thread_arena == ATFORK_ARENA_PTR)
|
||||||
tsd_getspecific (arena_key, my_arena);
|
|
||||||
if (my_arena == ATFORK_ARENA_PTR)
|
|
||||||
/* This is the same thread which already locks the global list.
|
/* This is the same thread which already locks the global list.
|
||||||
Just bump the counter. */
|
Just bump the counter. */
|
||||||
goto out;
|
goto out;
|
||||||
@ -234,8 +226,8 @@ ptmalloc_lock_all (void)
|
|||||||
__malloc_hook = malloc_atfork;
|
__malloc_hook = malloc_atfork;
|
||||||
__free_hook = free_atfork;
|
__free_hook = free_atfork;
|
||||||
/* Only the current thread may perform malloc/free calls now. */
|
/* Only the current thread may perform malloc/free calls now. */
|
||||||
tsd_getspecific (arena_key, save_arena);
|
save_arena = thread_arena;
|
||||||
tsd_setspecific (arena_key, ATFORK_ARENA_PTR);
|
thread_arena = ATFORK_ARENA_PTR;
|
||||||
out:
|
out:
|
||||||
++atfork_recursive_cntr;
|
++atfork_recursive_cntr;
|
||||||
}
|
}
|
||||||
@ -251,7 +243,7 @@ ptmalloc_unlock_all (void)
|
|||||||
if (--atfork_recursive_cntr != 0)
|
if (--atfork_recursive_cntr != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tsd_setspecific (arena_key, save_arena);
|
thread_arena = save_arena;
|
||||||
__malloc_hook = save_malloc_hook;
|
__malloc_hook = save_malloc_hook;
|
||||||
__free_hook = save_free_hook;
|
__free_hook = save_free_hook;
|
||||||
for (ar_ptr = &main_arena;; )
|
for (ar_ptr = &main_arena;; )
|
||||||
@ -279,7 +271,7 @@ ptmalloc_unlock_all2 (void)
|
|||||||
if (__malloc_initialized < 1)
|
if (__malloc_initialized < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tsd_setspecific (arena_key, save_arena);
|
thread_arena = save_arena;
|
||||||
__malloc_hook = save_malloc_hook;
|
__malloc_hook = save_malloc_hook;
|
||||||
__free_hook = save_free_hook;
|
__free_hook = save_free_hook;
|
||||||
free_list = NULL;
|
free_list = NULL;
|
||||||
@ -372,8 +364,7 @@ ptmalloc_init (void)
|
|||||||
__morecore = __failing_morecore;
|
__morecore = __failing_morecore;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tsd_key_create (&arena_key, NULL);
|
thread_arena = &main_arena;
|
||||||
tsd_setspecific (arena_key, (void *) &main_arena);
|
|
||||||
thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
|
thread_atfork (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2);
|
||||||
const char *s = NULL;
|
const char *s = NULL;
|
||||||
if (__glibc_likely (_environ != 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);
|
set_head (top (a), (((char *) h + h->size) - ptr) | PREV_INUSE);
|
||||||
|
|
||||||
LIBC_PROBE (memory_arena_new, 2, a, size);
|
LIBC_PROBE (memory_arena_new, 2, a, size);
|
||||||
tsd_setspecific (arena_key, (void *) a);
|
thread_arena = a;
|
||||||
mutex_init (&a->mutex);
|
mutex_init (&a->mutex);
|
||||||
(void) mutex_lock (&a->mutex);
|
(void) mutex_lock (&a->mutex);
|
||||||
|
|
||||||
@ -794,7 +785,7 @@ get_free_list (void)
|
|||||||
{
|
{
|
||||||
LIBC_PROBE (memory_arena_reuse_free_list, 1, result);
|
LIBC_PROBE (memory_arena_reuse_free_list, 1, result);
|
||||||
(void) mutex_lock (&result->mutex);
|
(void) mutex_lock (&result->mutex);
|
||||||
tsd_setspecific (arena_key, (void *) result);
|
thread_arena = result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,7 +838,7 @@ reused_arena (mstate avoid_arena)
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
LIBC_PROBE (memory_arena_reuse, 2, result, avoid_arena);
|
LIBC_PROBE (memory_arena_reuse, 2, result, avoid_arena);
|
||||||
tsd_setspecific (arena_key, (void *) result);
|
thread_arena = result;
|
||||||
next_to_use = result->next;
|
next_to_use = result->next;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -934,9 +925,8 @@ arena_get_retry (mstate ar_ptr, size_t bytes)
|
|||||||
static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||||||
arena_thread_freeres (void)
|
arena_thread_freeres (void)
|
||||||
{
|
{
|
||||||
void *vptr = NULL;
|
mstate a = thread_arena;
|
||||||
mstate a = tsd_getspecific (arena_key, vptr);
|
thread_arena = NULL;
|
||||||
tsd_setspecific (arena_key, NULL);
|
|
||||||
|
|
||||||
if (a != NULL)
|
if (a != NULL)
|
||||||
{
|
{
|
||||||
|
@ -332,8 +332,6 @@ this function is in @file{stdlib.h}.
|
|||||||
@c __libc_malloc @asulock @aculock @acsfd @acsmem
|
@c __libc_malloc @asulock @aculock @acsfd @acsmem
|
||||||
@c force_reg ok
|
@c force_reg ok
|
||||||
@c *malloc_hook unguarded
|
@c *malloc_hook unguarded
|
||||||
@c arena_lookup ok
|
|
||||||
@c tsd_getspecific ok, TLS
|
|
||||||
@c arena_lock @asulock @aculock @acsfd @acsmem
|
@c arena_lock @asulock @aculock @acsfd @acsmem
|
||||||
@c mutex_lock @asulock @aculock
|
@c mutex_lock @asulock @aculock
|
||||||
@c arena_get2 @asulock @aculock @acsfd @acsmem
|
@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_lock (list_lock) dup @asulock @aculock
|
||||||
@c mutex_unlock (list_lock) dup @aculock
|
@c mutex_unlock (list_lock) dup @aculock
|
||||||
@c mutex_lock (arena lock) dup @asulock @aculock [returns locked]
|
@c mutex_lock (arena lock) dup @asulock @aculock [returns locked]
|
||||||
@c tsd_setspecific ok, TLS
|
|
||||||
@c __get_nprocs ext ok @acsfd
|
@c __get_nprocs ext ok @acsfd
|
||||||
@c NARENAS_FROM_NCORES ok
|
@c NARENAS_FROM_NCORES ok
|
||||||
@c catomic_compare_and_exchange_bool_acq 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 *__malloc_hook dup unguarded
|
||||||
@c memset dup ok
|
@c memset dup ok
|
||||||
@c arena_get @asulock @aculock @acsfd @acsmem
|
@c arena_get @asulock @aculock @acsfd @acsmem
|
||||||
@c arena_lookup dup ok
|
|
||||||
@c arena_lock dup @asulock @aculock @acsfd @acsmem
|
@c arena_lock dup @asulock @aculock @acsfd @acsmem
|
||||||
@c top dup ok
|
@c top dup ok
|
||||||
@c chunksize dup ok
|
@c chunksize dup ok
|
||||||
|
@ -40,13 +40,6 @@ typedef int mutex_t;
|
|||||||
# define mutex_unlock(m) (*(m) = 0)
|
# define mutex_unlock(m) (*(m) = 0)
|
||||||
# define MUTEX_INITIALIZER (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 */
|
#endif /* !defined mutex_init */
|
||||||
|
|
||||||
#ifndef atomic_full_barrier
|
#ifndef atomic_full_barrier
|
||||||
|
@ -52,16 +52,6 @@
|
|||||||
/* No we're *not* using pthreads. */
|
/* No we're *not* using pthreads. */
|
||||||
#define __pthread_initialize ((void (*)(void))0)
|
#define __pthread_initialize ((void (*)(void))0)
|
||||||
|
|
||||||
/* thread specific data for glibc */
|
|
||||||
|
|
||||||
#include <libc-tsd.h>
|
|
||||||
|
|
||||||
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. */
|
/* madvise is a stub on Hurd, so don't bother calling it. */
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -58,16 +58,6 @@ extern void *__dso_handle __attribute__ ((__weak__));
|
|||||||
__linkin_atfork (&atfork_mem)
|
__linkin_atfork (&atfork_mem)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* thread specific data for glibc */
|
|
||||||
|
|
||||||
#include <libc-tsd.h>
|
|
||||||
|
|
||||||
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 <sysdeps/generic/malloc-machine.h>
|
#include <sysdeps/generic/malloc-machine.h>
|
||||||
|
|
||||||
#endif /* !defined(_MALLOC_MACHINE_H) */
|
#endif /* !defined(_MALLOC_MACHINE_H) */
|
||||||
|
Loading…
Reference in New Issue
Block a user