summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-12-16 12:01:55 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2007-12-16 12:01:55 +0000
commitb4acda17745b96b62c265783eacd9ab3b9e00463 (patch)
tree8edcea047626ca5cc3f6604c0f3906be050f004b
parent7e9a8bc9fe6b0f1dea7048dbd123685c564fe02a (diff)
Avoid threading issues by performing dlsym in the _init function.
-rw-r--r--src/lwp.c197
1 files changed, 53 insertions, 144 deletions
diff --git a/src/lwp.c b/src/lwp.c
index 5200a88..d03045e 100644
--- a/src/lwp.c
+++ b/src/lwp.c
@@ -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);
}