OSDN Git Service

310b691746d2ecb6b24bd85f1e91416995cea54f
[pf3gnuchains/pf3gnuchains4x.git] / newlib / libc / stdlib / __atexit.c
1 /*
2  *  Common routine to implement atexit-like functionality.
3  */
4
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <reent.h>
8 #include <sys/lock.h>
9 #include "atexit.h"
10
11
12 /*
13  * Register a function to be performed at exit or on shared library unload.
14  */
15
16 int
17 _DEFUN (__register_exitproc,
18         (type, fn, arg, d),
19         int type _AND
20         void (*fn) (void) _AND
21         void *arg _AND
22         void *d)
23 {
24   struct _on_exit_args * args;
25   register struct _atexit *p;
26
27 #ifndef __SINGLE_THREAD__
28   __LOCK_INIT(static, lock);
29
30   __lock_acquire(lock);
31 #endif
32
33   p = _GLOBAL_REENT->_atexit;
34   if (p == NULL)
35     _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
36   if (p->_ind >= _ATEXIT_SIZE)
37     {
38       p = (struct _atexit *) malloc (sizeof *p);
39       if (p == NULL)
40         {
41 #ifndef __SINGLE_THREAD__
42           __lock_release(lock);
43 #endif
44           return -1;
45         }
46       p->_ind = 0;
47       p->_next = _GLOBAL_REENT->_atexit;
48       _GLOBAL_REENT->_atexit = p;
49 #ifndef _REENT_SMALL
50       p->_on_exit_args._fntypes = 0;
51 #ifdef __REENT_HAS_CXA_SUPPORT
52       p->_on_exit_args._is_cxa = 0;
53 #endif
54 #endif
55     }
56
57   if (type != __et_atexit)
58     {
59 #ifdef _REENT_SMALL
60       args = p->_on_exit_args_ptr;
61       if (args == NULL)
62         {
63           args = malloc (sizeof * p->_on_exit_args_ptr);
64           if (args == NULL)
65             {
66 #ifndef __SINGLE_THREAD__
67               __lock_release(lock);
68 #endif
69               return -1;
70             }
71           args->_fntypes = 0;
72           args->_is_cxa = 0;
73 #ifdef __REENT_HAS_CXA_SUPPORT
74           p->_on_exit_args_ptr = args;
75 #endif
76         }
77 #else
78       args = &p->_on_exit_args;
79 #endif
80       args->_fnargs[p->_ind] = arg;
81       args->_fntypes |= (1 << p->_ind);
82 #ifdef __REENT_HAS_CXA_SUPPORT
83       args->_dso_handle[p->_ind] = d;
84       if (type == __et_cxa)
85         args->_is_cxa |= (1 << p->_ind);
86 #endif
87     }
88   p->_fns[p->_ind++] = fn;
89 #ifndef __SINGLE_THREAD__
90   __lock_release(lock);
91 #endif
92   return 0;
93 }