summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkettenis <>2017-12-05 13:45:31 +0000
committerkettenis <>2017-12-05 13:45:31 +0000
commit600f75bb29d99689e97396445d8fe7607c8d33e5 (patch)
treedab90ef1694b0d3420749f26041ad61fede3edd7
parentf0409c3cf441cd4fbcb4a68a09598bca8eeefb46 (diff)
downloadopenbsd-600f75bb29d99689e97396445d8fe7607c8d33e5.tar.gz
openbsd-600f75bb29d99689e97396445d8fe7607c8d33e5.tar.bz2
openbsd-600f75bb29d99689e97396445d8fe7607c8d33e5.zip
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@
-rw-r--r--src/lib/libc/include/thread_private.h3
-rw-r--r--src/lib/libc/stdlib/atexit.c54
-rw-r--r--src/lib/libc/stdlib/atexit.h4
3 files changed, 58 insertions, 3 deletions
diff --git a/src/lib/libc/include/thread_private.h b/src/lib/libc/include/thread_private.h
index fd530d7dff..ae8d554a8a 100644
--- a/src/lib/libc/include/thread_private.h
+++ b/src/lib/libc/include/thread_private.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: thread_private.h,v 1.32 2017/11/04 22:53:57 jca Exp $ */ 1/* $OpenBSD: thread_private.h,v 1.33 2017/12/05 13:45:31 kettenis Exp $ */
2 2
3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ 3/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */
4 4
@@ -394,6 +394,7 @@ void _spinunlock(volatile _atomic_lock_t *);
394void _rthread_debug(int, const char *, ...) 394void _rthread_debug(int, const char *, ...)
395 __attribute__((__format__ (printf, 2, 3))); 395 __attribute__((__format__ (printf, 2, 3)));
396pid_t _thread_dofork(pid_t (*_sys_fork)(void)); 396pid_t _thread_dofork(pid_t (*_sys_fork)(void));
397void _thread_finalize(void);
397 398
398/* 399/*
399 * Threading syscalls not declared in system headers 400 * Threading syscalls not declared in system headers
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index 83cc1282a9..dc117a3752 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: atexit.c,v 1.24 2015/11/10 04:14:03 guenther Exp $ */ 1/* $OpenBSD: atexit.c,v 1.25 2017/12/05 13:45:31 kettenis Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Daniel Hartmeier 3 * Copyright (c) 2002 Daniel Hartmeier
4 * All rights reserved. 4 * All rights reserved.
@@ -31,12 +31,24 @@
31 31
32#include <sys/types.h> 32#include <sys/types.h>
33#include <sys/mman.h> 33#include <sys/mman.h>
34#include <dlfcn.h>
35#include <elf.h>
36#pragma weak _DYNAMIC
34#include <stdlib.h> 37#include <stdlib.h>
35#include <string.h> 38#include <string.h>
36#include <unistd.h> 39#include <unistd.h>
37#include "atexit.h" 40#include "atexit.h"
38#include "atfork.h" 41#include "atfork.h"
39#include "thread_private.h" 42#include "thread_private.h"
43#include "tib.h"
44
45typeof(dlctl) dlctl asm("_dlctl") __attribute__((weak));
46
47struct thread_atexit_fn {
48 void (*func)(void *);
49 void *arg;
50 struct thread_atexit_fn *next;
51};
40 52
41struct atexit *__atexit; 53struct atexit *__atexit;
42static int restartloop; 54static int restartloop;
@@ -121,6 +133,43 @@ atexit(void (*fn)(void))
121} 133}
122DEF_STRONG(atexit); 134DEF_STRONG(atexit);
123 135
136__weak_alias(__cxa_thread_atexit, __cxa_thread_atexit_impl);
137
138int
139__cxa_thread_atexit_impl(void (*func)(void *), void *arg, void *dso)
140{
141 struct thread_atexit_fn *fnp;
142 struct tib *tib = TIB_GET();
143
144 fnp = calloc(1, sizeof(struct thread_atexit_fn));
145 if (fnp == NULL)
146 return -1;
147
148 if (_DYNAMIC)
149 dlctl(NULL, DL_REFERENCE, dso);
150
151 fnp->func = func;
152 fnp->arg = arg;
153 fnp->next = tib->tib_atexit;
154 tib->tib_atexit = fnp;
155
156 return 0;
157}
158DEF_STRONG(__cxa_thread_atexit_impl);
159
160void
161_thread_finalize(void)
162{
163 struct tib *tib = TIB_GET();
164
165 while (tib->tib_atexit) {
166 struct thread_atexit_fn *fnp = tib->tib_atexit;
167 tib->tib_atexit = fnp->next;
168 fnp->func(fnp->arg);
169 free(fnp);
170 }
171}
172
124/* 173/*
125 * Call all handlers registered with __cxa_atexit() for the shared 174 * Call all handlers registered with __cxa_atexit() for the shared
126 * object owning 'dso'. 175 * object owning 'dso'.
@@ -134,6 +183,9 @@ __cxa_finalize(void *dso)
134 int n, pgsize = getpagesize(); 183 int n, pgsize = getpagesize();
135 static int call_depth; 184 static int call_depth;
136 185
186 if (dso == NULL)
187 _thread_finalize();
188
137 _ATEXIT_LOCK(); 189 _ATEXIT_LOCK();
138 call_depth++; 190 call_depth++;
139 191
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
index e2e821de04..d9bfed852f 100644
--- a/src/lib/libc/stdlib/atexit.h
+++ b/src/lib/libc/stdlib/atexit.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: atexit.h,v 1.10 2015/10/25 18:01:24 guenther Exp $ */ 1/* $OpenBSD: atexit.h,v 1.11 2017/12/05 13:45:31 kettenis Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Daniel Hartmeier 4 * Copyright (c) 2002 Daniel Hartmeier
@@ -46,7 +46,9 @@ extern struct atexit *__atexit; /* points to head of LIFO stack */
46__END_HIDDEN_DECLS 46__END_HIDDEN_DECLS
47 47
48int __cxa_atexit(void (*)(void *), void *, void *); 48int __cxa_atexit(void (*)(void *), void *, void *);
49int __cxa_thread_atexit(void (*)(void *), void *, void *);
49void __cxa_finalize(void *); 50void __cxa_finalize(void *);
50 51
51PROTO_NORMAL(__cxa_atexit); 52PROTO_NORMAL(__cxa_atexit);
53PROTO_STD_DEPRECATED(__cxa_thread_atexit);
52PROTO_NORMAL(__cxa_finalize); 54PROTO_NORMAL(__cxa_finalize);