diff --git a/Makefile b/Makefile index bae8dceb..f958626b 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,7 @@ INSTALL_TARGETS := install-headers install-libs ifeq ($(LIBPHOENIX_PIC), y) CFLAGS += $(TARGET_PIC_FLAG) ifeq ($(LIBPHOENIX_SHARED), y) +CPPFLAGS += -DLIBPHOENIX_SHARED include shared.mk endif endif diff --git a/crt0-common.c b/crt0-common.c index 7842f9e6..61d9af45 100644 --- a/crt0-common.c +++ b/crt0-common.c @@ -72,6 +72,8 @@ extern int main(int argc, char **argv); char **environ; const char *argv_progname; +/* TLS cannot be used before initialized by dynamic linker in dynamically linked binaries. */ +int can_use_tls; __attribute__((noreturn)) void _startc(void (*cleanup)(void), int argc, char **argv, char **env) @@ -81,6 +83,9 @@ __attribute__((noreturn)) void _startc(void (*cleanup)(void), int argc, char **a _libc_init(); + /* At this point TLS is setup, as dynamic linker calls _startc after dealing with TLS. */ + can_use_tls = 1; + /* cleanup function is not NULL when the dynamic linker is used */ if (cleanup != NULL) { atexit(cleanup); diff --git a/errno/errno.c b/errno/errno.c index fccd3468..8c161bc3 100644 --- a/errno/errno.c +++ b/errno/errno.c @@ -23,6 +23,9 @@ static __thread int __errno_tls; +extern int can_use_tls; +static int errno_single = 0; + #else static int errno_global; @@ -58,7 +61,7 @@ int *__errno_location(void) return &errno_global; #else - return &__errno_tls; + return can_use_tls == 0 ? &errno_single : &__errno_tls; #endif } diff --git a/include/sys/threads.h b/include/sys/threads.h index 04d47197..5980de92 100644 --- a/include/sys/threads.h +++ b/include/sys/threads.h @@ -70,6 +70,13 @@ extern int spawnSyspage(const char *imap, const char *dmap, const char *name, ch extern int threadJoin(int tid, time_t timeout); +extern int beginthreadexsvc(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id); + + +__attribute__((noreturn)) +extern void endthreadsvc(void); + + extern int beginthreadex(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id); diff --git a/sys/threads.c b/sys/threads.c index b3545325..746d22cd 100644 --- a/sys/threads.c +++ b/sys/threads.c @@ -17,6 +17,48 @@ #include +#include +#include + +/* Provide stub definition of tls managing functions for statically linked programs. */ + +static void _libphoenix_stub(void) +{ +} + +extern void __attribute__((weak, alias("_libphoenix_stub"))) _rtld_tls_free_curr(void); +extern void __attribute__((weak, alias("_libphoenix_stub"))) _rtld_tls_allocate_curr(void); + + +/* FIXME: Hack to provide tls support in dynamically loaded binaries. */ +void beginthreadex_wrapper(void *arg) +{ + _rtld_tls_allocate_curr(); + + void *(*start)(void *) = ((void **)arg)[0]; + void *startArg = ((void **)arg)[1]; + + free(arg); + + start(startArg); +} + +int beginthreadex(void (*start)(void *), unsigned int priority, void *stack, unsigned int stacksz, void *arg, handle_t *id) +{ + void **startAndArg = (void **)malloc(sizeof(void *) * 2); + startAndArg[0] = start; + startAndArg[1] = arg; + return beginthreadexsvc(beginthreadex_wrapper, priority, stack, stacksz, startAndArg, id); +} + + +__attribute__((noreturn)) void endthread(void) +{ + _rtld_tls_free_curr(); + endthreadsvc(); +} + + int mutexCreate(handle_t *h) { static const struct lockAttr defaultAttr = { .type = PH_LOCK_NORMAL };