diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-12-16 12:01:55 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-12-16 12:01:55 +0000 |
commit | b4acda17745b96b62c265783eacd9ab3b9e00463 (patch) | |
tree | 8edcea047626ca5cc3f6604c0f3906be050f004b | |
parent | 7e9a8bc9fe6b0f1dea7048dbd123685c564fe02a (diff) |
Avoid threading issues by performing dlsym in the _init function.
-rw-r--r-- | src/lwp.c | 197 |
1 files changed, 53 insertions, 144 deletions
@@ -50,12 +50,12 @@ #define RTLD_NEXT ((void *) -1) #endif -#define DLCALL(name, args...) ({ \ - static typeof (&name) name##_real; \ - if (name##_real == NULL) \ - name##_real = dlsym (RTLD_NEXT, #name); \ - (*name##_real) (args); \ -}) +#define DLSYM_DECLARE(name) \ + static typeof (&name) name##_real +#define DLSYM_DEFINE(name) \ + name##_real = dlsym (RTLD_NEXT, #name) +#define DLCALL(name, args...) \ + (*name##_real) (args) #define __libc_alias(N) typeof (N) __libc_##N __attribute__((alias(#N))) @@ -111,12 +111,20 @@ static LWP_SharedObject *so_ht[673]; static GSList *gslist_free_list; -static char _lwp_malloc_recurse_buffer[32768]; -static gushort _lwp_malloc_recurse_allocated; -static gushort _lwp_malloc_recurse_depth; - static int _lwp_initialized; -static int _lwp_events_initialized; +static int _lwp_dlcall_initialized; + +static void __attribute__ ((constructor)) +__lwp_init (void); + +DLSYM_DECLARE (malloc); +DLSYM_DECLARE (calloc); +DLSYM_DECLARE (realloc); +DLSYM_DECLARE (valloc); +DLSYM_DECLARE (pvalloc); +DLSYM_DECLARE (memalign); +DLSYM_DECLARE (posix_memalign); +DLSYM_DECLARE (free); static gpointer _lwp_perm_alloc (gsize size) @@ -713,58 +721,19 @@ unlock: pthread_mutex_unlock (&event_mutex); } -static gboolean -_lwp_malloc_recurse (void) -{ - if (! _lwp_events_initialized || _lwp_malloc_recurse_depth) - return TRUE; - - ++_lwp_malloc_recurse_depth; - - return FALSE; -} - -/* dlsym() calls calloc() to initialize its error buffer */ -static gboolean -_lwp_malloc_recursed_alloc (size_t size, gpointer *ret) -{ - if (! _lwp_malloc_recurse ()) - return FALSE; - - if (size == 0 || - size + _lwp_malloc_recurse_allocated + sizeof (guint) > G_N_ELEMENTS (_lwp_malloc_recurse_buffer)) { - *ret = NULL; - } else { - guint *len; - len = (guint *) (_lwp_malloc_recurse_buffer + _lwp_malloc_recurse_allocated); - *len = size; - _lwp_malloc_recurse_allocated += sizeof (guint); - - *ret = _lwp_malloc_recurse_buffer + _lwp_malloc_recurse_allocated; - _lwp_malloc_recurse_allocated += size; - } - - return TRUE; -} - -static void -_lwp_malloc_unrecurse (void) -{ - --_lwp_malloc_recurse_depth; -} - void * malloc (size_t size) { void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, &ret)) - return ret; + if (_lwp_initialized == 0) + __lwp_init (); - ret = DLCALL (malloc, size); + if (! _lwp_dlcall_initialized) + return NULL; - _lwp_malloc_unrecurse (); + ret = DLCALL (malloc, size); event.malloc.size = size; event.malloc.addr = ret; @@ -780,12 +749,13 @@ calloc (size_t n, size_t size) void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (n * size, &ret)) - return ret; + if (_lwp_initialized == 0) + __lwp_init (); - ret = DLCALL (calloc, n, size); + if (! _lwp_dlcall_initialized) + return NULL; - _lwp_malloc_unrecurse (); + ret = DLCALL (calloc, n, size); /* XXX differentiate? */ event.malloc.size = n * size; @@ -802,13 +772,11 @@ valloc (size_t size) void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, &ret)) - return ret; + if (! _lwp_dlcall_initialized) + return NULL; ret = DLCALL (valloc, size); - _lwp_malloc_unrecurse (); - /* XXX differentiate? */ event.memalign.align = sysconf (_SC_PAGESIZE); event.memalign.size = size; @@ -825,13 +793,11 @@ pvalloc (size_t size) void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, &ret)) - return ret; + if (! _lwp_dlcall_initialized) + return NULL; ret = DLCALL (pvalloc, size); - _lwp_malloc_unrecurse (); - /* XXX differentiate? */ event.memalign.align = sysconf (_SC_PAGESIZE); event.memalign.size = size; @@ -848,13 +814,11 @@ memalign (size_t boundary, size_t size) void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, &ret)) - return ret; + if (! _lwp_dlcall_initialized) + return NULL; ret = DLCALL (memalign, boundary, size); - _lwp_malloc_unrecurse (); - event.memalign.align = boundary; event.memalign.size = size; event.memalign.addr = ret; @@ -869,13 +833,11 @@ posix_memalign (void **ptr, size_t alignment, size_t size) int ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, ptr)) - return ptr != NULL; + if (! _lwp_dlcall_initialized) + return 0; ret = DLCALL (posix_memalign, ptr, alignment, size); - _lwp_malloc_unrecurse (); - event.memalign.align = alignment; event.memalign.size = size; event.memalign.addr = *ptr; @@ -890,56 +852,14 @@ realloc (void *ptr, size_t size) void *ret; LWP_Event event; - if (_lwp_malloc_recursed_alloc (size, &ret)) { - if (ptr != NULL) { - if (ret != NULL) { - guint *len = (guint *) ptr - 1; - if (*len < size) - size = *len; - memcpy (ret, ptr, size); - } - } - return ret; - } - - /* I'd rather just assert that this never happened, but it does! */ -#if 1 - if ((guint) ((char *) ptr - &_lwp_malloc_recurse_buffer[0]) < _lwp_malloc_recurse_allocated) - { - guint *len = (guint *) ptr - 1; - guint min_len; - - _lwp_malloc_unrecurse (); + if (_lwp_initialized == 0) + __lwp_init (); - /* use malloc() to create new tracked block */ - - ret = malloc (size); - if (ret != NULL) { - gchar *end = (gchar *) ptr + *len; - - min_len = *len; - if (min_len > size) - min_len = size; - memcpy (ret, ptr, min_len); - - /* optimistically reclaim the memory! */ - if (end == _lwp_malloc_recurse_buffer + - _lwp_malloc_recurse_allocated) - { - _lwp_malloc_recurse_allocated = (gchar *) len - _lwp_malloc_recurse_buffer; - } - } - - return ret; - } -#else - g_assert ((guint) ((char *) ptr - &_lwp_malloc_recurse_buffer[0]) > _lwp_malloc_recurse_allocated); -#endif + if (! _lwp_dlcall_initialized) + return NULL; ret = DLCALL (realloc, ptr, size); - _lwp_malloc_unrecurse (); - event.realloc.size = size; event.realloc.old_addr = ptr; event.realloc.new_addr = ret; @@ -954,33 +874,16 @@ free (void *ptr) { LWP_Event event; - if ((guint) ((char *) ptr - &_lwp_malloc_recurse_buffer[0]) < _lwp_malloc_recurse_allocated) - { - /* optimistically reclaim the memory! */ - guint *len = (guint *) ptr - 1; - gchar *end = (gchar *) ptr + *len; - if (end == _lwp_malloc_recurse_buffer + _lwp_malloc_recurse_allocated) { - _lwp_malloc_recurse_allocated = (gchar *) len - - _lwp_malloc_recurse_buffer; - } - - return; - } - - /* XXX dlsym may trigger a free not caught above.. */ - if (_lwp_malloc_recurse ()) + if (! _lwp_dlcall_initialized) return; DLCALL (free, ptr); - _lwp_malloc_unrecurse (); - event.free.addr = ptr; _lwp_record_event (LWP_FREE, &event); } /* XXX __builtin_new */ - static void __attribute__ ((constructor)) __lwp_init (void) { @@ -995,9 +898,18 @@ __lwp_init (void) env = getenv ("LWP_DISABLE_STACKTRACES"); _lwp_disable_stacktraces = env != NULL; - _lwp_record_event (LWP_INIT, &event); + DLSYM_DEFINE (malloc); + DLSYM_DEFINE (calloc); + DLSYM_DEFINE (realloc); + DLSYM_DEFINE (valloc); + DLSYM_DEFINE (pvalloc); + DLSYM_DEFINE (memalign); + DLSYM_DEFINE (posix_memalign); + DLSYM_DEFINE (free); + + _lwp_dlcall_initialized = TRUE; - _lwp_events_initialized = TRUE; + _lwp_record_event (LWP_INIT, &event); } static void __attribute__ ((destructor)) @@ -1005,8 +917,5 @@ __lwp_fini (void) { LWP_Event event; - if (--_lwp_initialized) - return; - _lwp_record_event (LWP_FINI, &event); } |