1 /*
2  * (c) 2004-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  *
9  * As a special exception, you may use this file as part of a free software
10  * library without restriction.  Specifically, if other files instantiate
11  * templates or use macros or inline functions from this file, or you compile
12  * this file and link it with other files to produce an executable, this
13  * file does not by itself cause the resulting executable to be covered by
14  * the GNU General Public License.  This exception does not however
15  * invalidate any other reasons why the executable file might be covered by
16  * the GNU General Public License.
17  */
18 
19 #include "cxx_atexit.h"
20 
21 #define NUM_ATEXIT	64
22 
23 struct __exit_handler
24 {
25   void (*f)(void *);
26   void *arg;
27   void *dso_handle;
28 };
29 
30 static __exit_handler __atexitlist[NUM_ATEXIT];
31 static volatile unsigned atexit_counter;
__cxa_atexit(void (* f)(void *),void * arg,void * dso_handle)32 int __cxa_atexit(void (*f)(void*), void *arg, void *dso_handle)
33 {
34   unsigned c = atexit_counter++;
35   if (c >= NUM_ATEXIT)
36     return -1;
37 
38   __atexitlist[c].f = f;
39   __atexitlist[c].arg = arg;
40   __atexitlist[c].dso_handle = dso_handle;
41 
42   return 0;
43 }
44 
45 extern void *__dso_handle __attribute__((weak));
46 
atexit(void (* f)(void))47 int atexit(void (*f)(void))
48 {
49   return __cxa_atexit((void (*)(void*))f, 0, (!&__dso_handle)?0:__dso_handle);
50 }
51 
__cxa_finalize(void * dso_handle)52 void __cxa_finalize(void *dso_handle)
53 {
54   unsigned co = atexit_counter;
55   if (co > NUM_ATEXIT)
56     co = NUM_ATEXIT;
57 
58   while(co)
59     {
60       __exit_handler *h = &__atexitlist[--co];
61       if (h->f && (dso_handle == 0 || h->dso_handle == dso_handle))
62         {
63           h->f(h->arg);
64           h->f = 0;
65         }
66     }
67 }
68