#include <dlfcn.h>
#include <sys/types.h>
#include <stdio.h>
-#include <pthread.h>
+#include <urcu/system.h>
+#include <urcu/uatomic.h>
#define TRACEPOINT_DEFINE
#define TRACEPOINT_CREATE_PROBES
#define STATIC_CALLOC_LEN 4096
static char static_calloc_buf[STATIC_CALLOC_LEN];
-static size_t static_calloc_buf_offset;
-static pthread_mutex_t static_calloc_mutex = PTHREAD_MUTEX_INITIALIZER;
+static unsigned long static_calloc_buf_offset;
static void *static_calloc(size_t nmemb, size_t size)
{
- size_t prev_offset;
+ unsigned long prev_offset, new_offset, res_offset;
- pthread_mutex_lock(&static_calloc_mutex);
- if (nmemb * size > sizeof(static_calloc_buf) - static_calloc_buf_offset) {
- pthread_mutex_unlock(&static_calloc_mutex);
- return NULL;
- }
- prev_offset = static_calloc_buf_offset;
- static_calloc_buf_offset += nmemb * size;
- pthread_mutex_unlock(&static_calloc_mutex);
+ /*
+ * Protect static_calloc_buf_offset from concurrent updates
+ * using a cmpxchg loop rather than a mutex to remove a
+ * dependency on pthread. This will minimize the risk of bad
+ * interaction between mutex and malloc instrumentation.
+ */
+ res_offset = CMM_LOAD_SHARED(static_calloc_buf_offset);
+ do {
+ prev_offset = res_offset;
+ if (nmemb * size > sizeof(static_calloc_buf) - prev_offset) {
+ return NULL;
+ }
+ new_offset = prev_offset + nmemb * size;
+ } while ((res_offset = uatomic_cmpxchg(&static_calloc_buf_offset,
+ prev_offset, new_offset)) != prev_offset);
return &static_calloc_buf[prev_offset];
}
tracepoint(ust_libc, realloc, ptr, size, retval);
return retval;
}
+
+void *memalign(size_t alignment, size_t size)
+{
+ static void *(*plibc_memalign)(size_t alignment, size_t size);
+ void *retval;
+
+ if (plibc_memalign == NULL) {
+ plibc_memalign = dlsym(RTLD_NEXT, "memalign");
+ if (plibc_memalign == NULL) {
+ fprintf(stderr, "memalignwrap: unable to find memalign\n");
+ return NULL;
+ }
+ }
+ retval = plibc_memalign(alignment, size);
+ tracepoint(ust_libc, memalign, alignment, size, retval);
+ return retval;
+}
+
+int posix_memalign(void **memptr, size_t alignment, size_t size)
+{
+ static int(*plibc_posix_memalign)(void **memptr, size_t alignment, size_t size);
+ int retval;
+
+ if (plibc_posix_memalign == NULL) {
+ plibc_posix_memalign = dlsym(RTLD_NEXT, "posix_memalign");
+ if (plibc_posix_memalign == NULL) {
+ fprintf(stderr, "posix_memalignwrap: unable to find posix_memalign\n");
+ return ENOMEM;
+ }
+ }
+ retval = plibc_posix_memalign(memptr, alignment, size);
+ tracepoint(ust_libc, posix_memalign, *memptr, alignment, size, retval);
+ return retval;
+}