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
);