4 #include "pthread_impl.h"
8 #define malloc __libc_malloc
9 #define calloc __libc_calloc
10 #define realloc __libc_realloc
11 #define free __libc_free
15 pthread_t self = __pthread_self();
16 if (!self->dlerror_flag) return 0;
17 self->dlerror_flag = 0;
18 char *s = self->dlerror_buf;
20 return "Dynamic linker failed to allocate memory for error message";
25 /* Atomic singly-linked list, used to store list of thread-local dlerror
26 * buffers for deferred free. They cannot be freed at thread exit time
27 * because, by the time it's known they can be freed, the exiting thread
28 * is in a highly restrictive context where it cannot call (even the
29 * libc-internal) free. It also can't take locks; thus the atomic list. */
31 static void *volatile freebuf_queue;
33 void __dl_thread_cleanup(void)
35 pthread_t self = __pthread_self();
36 if (!self->dlerror_buf || self->dlerror_buf == (void *)-1)
41 *(void **)self->dlerror_buf = h;
42 } while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h);
45 hidden void __dl_vseterr(const char *fmt, va_list ap)
49 while (q && a_cas_p(&freebuf_queue, q, 0) != q);
59 pthread_t self = __pthread_self();
60 if (self->dlerror_buf != (void *)-1)
61 free(self->dlerror_buf);
62 size_t len = vsnprintf(0, 0, fmt, ap2);
63 if (len < sizeof(void *)) len = sizeof(void *);
65 char *buf = malloc(len+1);
67 vsnprintf(buf, len+1, fmt, ap);
71 self->dlerror_buf = buf;
72 self->dlerror_flag = 1;
75 hidden void __dl_seterr(const char *fmt, ...)
79 __dl_vseterr(fmt, ap);
83 static int stub_invalid_handle(void *h)
85 __dl_seterr("Invalid library handle %p", (void *)h);
89 weak_alias(stub_invalid_handle, __dl_invalid_handle);