From 0afcdeda897cccf53b8f99c1eb030fd52ee9ee99 Mon Sep 17 00:00:00 2001 From: kettenis Date: Tue, 5 Dec 2017 13:45:31 +0000 Subject: [PATCH] Implement __cxa_thread_atexit to support C++11 thread_local scope. The interface is also made available as __cxa_thread_atexit_impl to satisfy the needs of GNU libstdc++. ok guenther@, millert@ --- lib/libc/Symbols.list | 2 ++ lib/libc/include/thread_private.h | 3 +- lib/libc/shlib_version | 2 +- lib/libc/stdlib/atexit.c | 54 ++++++++++++++++++++++++++++++- lib/libc/stdlib/atexit.h | 4 ++- lib/libc/thread/rthread.c | 3 +- 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/lib/libc/Symbols.list b/lib/libc/Symbols.list index d6346040a78..63420faebdd 100644 --- a/lib/libc/Symbols.list +++ b/lib/libc/Symbols.list @@ -1466,6 +1466,8 @@ random /* stdlib */ _Exit __cxa_atexit +__cxa_thread_atexit +__cxa_thread_atexit_impl __cxa_finalize __isthreaded a64l diff --git a/lib/libc/include/thread_private.h b/lib/libc/include/thread_private.h index fd530d7dff1..ae8d554a8ab 100644 --- a/lib/libc/include/thread_private.h +++ b/lib/libc/include/thread_private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: thread_private.h,v 1.32 2017/11/04 22:53:57 jca Exp $ */ +/* $OpenBSD: thread_private.h,v 1.33 2017/12/05 13:45:31 kettenis Exp $ */ /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman */ @@ -394,6 +394,7 @@ void _spinunlock(volatile _atomic_lock_t *); void _rthread_debug(int, const char *, ...) __attribute__((__format__ (printf, 2, 3))); pid_t _thread_dofork(pid_t (*_sys_fork)(void)); +void _thread_finalize(void); /* * Threading syscalls not declared in system headers diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index 7fe672d9c92..858859a0e22 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ major=92 -minor=0 +minor=1 # note: If changes were made to include/thread_private.h or if system # calls were added/changed then librthread/shlib_version also be updated. diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c index 83cc1282a98..dc117a37524 100644 --- a/lib/libc/stdlib/atexit.c +++ b/lib/libc/stdlib/atexit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atexit.c,v 1.24 2015/11/10 04:14:03 guenther Exp $ */ +/* $OpenBSD: atexit.c,v 1.25 2017/12/05 13:45:31 kettenis Exp $ */ /* * Copyright (c) 2002 Daniel Hartmeier * All rights reserved. @@ -31,12 +31,24 @@ #include #include +#include +#include +#pragma weak _DYNAMIC #include #include #include #include "atexit.h" #include "atfork.h" #include "thread_private.h" +#include "tib.h" + +typeof(dlctl) dlctl asm("_dlctl") __attribute__((weak)); + +struct thread_atexit_fn { + void (*func)(void *); + void *arg; + struct thread_atexit_fn *next; +}; struct atexit *__atexit; static int restartloop; @@ -121,6 +133,43 @@ atexit(void (*fn)(void)) } DEF_STRONG(atexit); +__weak_alias(__cxa_thread_atexit, __cxa_thread_atexit_impl); + +int +__cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso) +{ + struct thread_atexit_fn *fnp; + struct tib *tib = TIB_GET(); + + fnp = calloc(1, sizeof(struct thread_atexit_fn)); + if (fnp == NULL) + return -1; + + if (_DYNAMIC) + dlctl(NULL, DL_REFERENCE, dso); + + fnp->func = func; + fnp->arg = arg; + fnp->next = tib->tib_atexit; + tib->tib_atexit = fnp; + + return 0; +} +DEF_STRONG(__cxa_thread_atexit_impl); + +void +_thread_finalize(void) +{ + struct tib *tib = TIB_GET(); + + while (tib->tib_atexit) { + struct thread_atexit_fn *fnp = tib->tib_atexit; + tib->tib_atexit = fnp->next; + fnp->func(fnp->arg); + free(fnp); + } +} + /* * Call all handlers registered with __cxa_atexit() for the shared * object owning 'dso'. @@ -134,6 +183,9 @@ __cxa_finalize(void *dso) int n, pgsize = getpagesize(); static int call_depth; + if (dso == NULL) + _thread_finalize(); + _ATEXIT_LOCK(); call_depth++; diff --git a/lib/libc/stdlib/atexit.h b/lib/libc/stdlib/atexit.h index e2e821de04b..d9bfed852f6 100644 --- a/lib/libc/stdlib/atexit.h +++ b/lib/libc/stdlib/atexit.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atexit.h,v 1.10 2015/10/25 18:01:24 guenther Exp $ */ +/* $OpenBSD: atexit.h,v 1.11 2017/12/05 13:45:31 kettenis Exp $ */ /* * Copyright (c) 2002 Daniel Hartmeier @@ -46,7 +46,9 @@ extern struct atexit *__atexit; /* points to head of LIFO stack */ __END_HIDDEN_DECLS int __cxa_atexit(void (*)(void *), void *, void *); +int __cxa_thread_atexit(void (*)(void *), void *, void *); void __cxa_finalize(void *); PROTO_NORMAL(__cxa_atexit); +PROTO_STD_DEPRECATED(__cxa_thread_atexit); PROTO_NORMAL(__cxa_finalize); diff --git a/lib/libc/thread/rthread.c b/lib/libc/thread/rthread.c index 66405cf477a..f26e85ffd31 100644 --- a/lib/libc/thread/rthread.c +++ b/lib/libc/thread/rthread.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread.c,v 1.6 2017/11/04 22:53:57 jca Exp $ */ +/* $OpenBSD: rthread.c,v 1.7 2017/12/05 13:45:31 kettenis Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst * All Rights Reserved. @@ -137,6 +137,7 @@ pthread_exit(void *retval) oclfn->fn(oclfn->arg); free(oclfn); } + _thread_finalize(); _rthread_tls_destructors(thread); if (_thread_cb.tc_thread_release != NULL) -- 2.20.1