summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/atexit.c
diff options
context:
space:
mode:
authorkettenis <>2017-12-05 13:45:31 +0000
committerkettenis <>2017-12-05 13:45:31 +0000
commit600f75bb29d99689e97396445d8fe7607c8d33e5 (patch)
treedab90ef1694b0d3420749f26041ad61fede3edd7 /src/lib/libc/stdlib/atexit.c
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@
Diffstat (limited to 'src/lib/libc/stdlib/atexit.c')
-rw-r--r--src/lib/libc/stdlib/atexit.c54
1 files changed, 53 insertions, 1 deletions
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