Subversion Repositories Kolibri OS

Rev

Rev 4874 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4874 Rev 4921
1
/*
1
/*
2
 * COmmon routine to call call registered atexit-like routines.
2
 * COmmon routine to call call registered atexit-like routines.
3
 */
3
 */
4
 
4
 
5
 
5
 
6
#include 
6
#include 
7
#include 
7
#include 
8
#include 
8
#include 
9
#include "atexit.h"
9
#include "atexit.h"
10
 
10
 
11
/* Make this a weak reference to avoid pulling in free.  */
11
/* Make this a weak reference to avoid pulling in free.  */
12
void free(void *) _ATTRIBUTE((__weak__));
12
void free(void *) _ATTRIBUTE((__weak__));
-
 
13
 
-
 
14
__LOCK_INIT_RECURSIVE(, __atexit_lock);
13
 
15
 
14
#ifndef __SINGLE_THREAD__
16
#ifdef _REENT_GLOBAL_ATEXIT
15
extern _LOCK_RECURSIVE_T __atexit_lock;
17
struct _atexit *_global_atexit = _NULL;
16
#endif
18
#endif
17
 
19
 
18
#ifdef _WANT_REGISTER_FINI
20
#ifdef _WANT_REGISTER_FINI
19
 
21
 
20
/* If "__libc_fini" is defined, finalizers (either
22
/* If "__libc_fini" is defined, finalizers (either
21
   "__libc_fini_array", or "_fini", as appropriate) will be run after
23
   "__libc_fini_array", or "_fini", as appropriate) will be run after
22
   all user-specified atexit handlers.  For example, you can define
24
   all user-specified atexit handlers.  For example, you can define
23
   "__libc_fini" to "_fini" in your linker script if you want the C
25
   "__libc_fini" to "_fini" in your linker script if you want the C
24
   library, rather than startup code, to register finalizers.  If you
26
   library, rather than startup code, to register finalizers.  If you
25
   do that, then your startup code need not contain references to
27
   do that, then your startup code need not contain references to
26
   "atexit" or "exit".  As a result, only applications that reference
28
   "atexit" or "exit".  As a result, only applications that reference
27
   "exit" explicitly will pull in finalization code.
29
   "exit" explicitly will pull in finalization code.
28
 
30
 
29
   The choice of whether to register finalizers from libc or from
31
   The choice of whether to register finalizers from libc or from
30
   startup code is deferred to link-time, rather than being a
32
   startup code is deferred to link-time, rather than being a
31
   configure-time option, so that the same C library binary can be
33
   configure-time option, so that the same C library binary can be
32
   used with multiple BSPs, some of which register finalizers from
34
   used with multiple BSPs, some of which register finalizers from
33
   startup code, while others defer to the C library.  */
35
   startup code, while others defer to the C library.  */
34
extern char __libc_fini __attribute__((weak));
36
extern char __libc_fini __attribute__((weak));
35
 
37
 
36
/* Register the application finalization function with atexit.  These
38
/* Register the application finalization function with atexit.  These
37
   finalizers should run last.  Therefore, we want to call atexit as
39
   finalizers should run last.  Therefore, we want to call atexit as
38
   soon as possible.  */
40
   soon as possible.  */
39
static void 
41
static void 
40
register_fini(void) __attribute__((constructor (0)));
42
register_fini(void) __attribute__((constructor (0)));
41
 
43
 
42
static void 
44
static void 
43
register_fini(void)
45
register_fini(void)
44
{
46
{
45
  if (&__libc_fini) {
47
  if (&__libc_fini) {
46
#ifdef HAVE_INITFINI_ARRAY
48
#ifdef HAVE_INITFINI_ARRAY
47
    extern void __libc_fini_array (void);
49
    extern void __libc_fini_array (void);
48
    atexit (__libc_fini_array);
50
    atexit (__libc_fini_array);
49
#else
51
#else
50
    extern void _fini (void);
52
    extern void _fini (void);
51
    atexit (_fini);
53
    atexit (_fini);
52
#endif
54
#endif
53
  }
55
  }
54
}
56
}
55
 
57
 
56
#endif /* _WANT_REGISTER_FINI  */
58
#endif /* _WANT_REGISTER_FINI  */
57
 
59
 
58
/*
60
/*
59
 * Call registered exit handlers.  If D is null then all handlers are called,
61
 * Call registered exit handlers.  If D is null then all handlers are called,
60
 * otherwise only the handlers from that DSO are called.
62
 * otherwise only the handlers from that DSO are called.
61
 */
63
 */
62
 
64
 
63
void 
65
void 
64
_DEFUN (__call_exitprocs, (code, d),
66
_DEFUN (__call_exitprocs, (code, d),
65
	int code _AND _PTR d)
67
	int code _AND _PTR d)
66
{
68
{
67
  register struct _atexit *p;
69
  register struct _atexit *p;
68
  struct _atexit **lastp;
70
  struct _atexit **lastp;
69
  register struct _on_exit_args * args;
71
  register struct _on_exit_args * args;
70
  register int n;
72
  register int n;
71
  int i;
73
  int i;
72
  void (*fn) (void);
74
  void (*fn) (void);
73
 
75
 
74
 
76
 
75
#ifndef __SINGLE_THREAD__
77
#ifndef __SINGLE_THREAD__
76
  __lock_acquire_recursive(__atexit_lock);
78
  __lock_acquire_recursive(__atexit_lock);
77
#endif
79
#endif
78
 
80
 
79
 restart:
81
 restart:
80
 
82
 
81
  p = _GLOBAL_REENT->_atexit;
83
  p = _GLOBAL_ATEXIT;
82
  lastp = &_GLOBAL_REENT->_atexit;
84
  lastp = &_GLOBAL_ATEXIT;
83
  while (p)
85
  while (p)
84
    {
86
    {
85
#ifdef _REENT_SMALL
87
#ifdef _REENT_SMALL
86
      args = p->_on_exit_args_ptr;
88
      args = p->_on_exit_args_ptr;
87
#else
89
#else
88
      args = &p->_on_exit_args;
90
      args = &p->_on_exit_args;
89
#endif
91
#endif
90
      for (n = p->_ind - 1; n >= 0; n--)
92
      for (n = p->_ind - 1; n >= 0; n--)
91
	{
93
	{
92
	  int ind;
94
	  int ind;
93
 
95
 
94
	  i = 1 << n;
96
	  i = 1 << n;
95
 
97
 
96
	  /* Skip functions not from this dso.  */
98
	  /* Skip functions not from this dso.  */
97
	  if (d && (!args || args->_dso_handle[n] != d))
99
	  if (d && (!args || args->_dso_handle[n] != d))
98
	    continue;
100
	    continue;
99
 
101
 
100
	  /* Remove the function now to protect against the
102
	  /* Remove the function now to protect against the
101
	     function calling exit recursively.  */
103
	     function calling exit recursively.  */
102
	  fn = p->_fns[n];
104
	  fn = p->_fns[n];
103
	  if (n == p->_ind - 1)
105
	  if (n == p->_ind - 1)
104
	    p->_ind--;
106
	    p->_ind--;
105
	  else
107
	  else
106
	    p->_fns[n] = NULL;
108
	    p->_fns[n] = NULL;
107
 
109
 
108
	  /* Skip functions that have already been called.  */
110
	  /* Skip functions that have already been called.  */
109
	  if (!fn)
111
	  if (!fn)
110
	    continue;
112
	    continue;
111
 
113
 
112
	  ind = p->_ind;
114
	  ind = p->_ind;
113
 
115
 
114
	  /* Call the function.  */
116
	  /* Call the function.  */
115
	  if (!args || (args->_fntypes & i) == 0)
117
	  if (!args || (args->_fntypes & i) == 0)
116
	    fn ();
118
	    fn ();
117
	  else if ((args->_is_cxa & i) == 0)
119
	  else if ((args->_is_cxa & i) == 0)
118
	    (*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]);
120
	    (*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]);
119
	  else
121
	  else
120
	    (*((void (*)(_PTR)) fn))(args->_fnargs[n]);
122
	    (*((void (*)(_PTR)) fn))(args->_fnargs[n]);
121
 
123
 
122
	  /* The function we called call atexit and registered another
124
	  /* The function we called call atexit and registered another
123
	     function (or functions).  Call these new functions before
125
	     function (or functions).  Call these new functions before
124
	     continuing with the already registered functions.  */
126
	     continuing with the already registered functions.  */
125
	  if (ind != p->_ind || *lastp != p)
127
	  if (ind != p->_ind || *lastp != p)
126
	    goto restart;
128
	    goto restart;
127
	}
129
	}
128
 
130
 
129
#ifndef _ATEXIT_DYNAMIC_ALLOC
131
#ifndef _ATEXIT_DYNAMIC_ALLOC
130
      break;
132
      break;
131
#else
133
#else
132
      /* Don't dynamically free the atexit array if free is not
134
      /* Don't dynamically free the atexit array if free is not
133
	 available.  */
135
	 available.  */
134
      if (!free)
136
      if (!free)
135
	break;
137
	break;
136
 
138
 
137
      /* Move to the next block.  Free empty blocks except the last one,
139
      /* Move to the next block.  Free empty blocks except the last one,
138
	 which is part of _GLOBAL_REENT.  */
140
	 which is part of _GLOBAL_REENT.  */
139
      if (p->_ind == 0 && p->_next)
141
      if (p->_ind == 0 && p->_next)
140
	{
142
	{
141
	  /* Remove empty block from the list.  */
143
	  /* Remove empty block from the list.  */
142
	  *lastp = p->_next;
144
	  *lastp = p->_next;
143
#ifdef _REENT_SMALL
145
#ifdef _REENT_SMALL
144
	  if (args)
146
	  if (args)
145
	    free (args);
147
	    free (args);
146
#endif
148
#endif
147
	  free (p);
149
	  free (p);
148
	  p = *lastp;
150
	  p = *lastp;
149
	}
151
	}
150
      else
152
      else
151
	{
153
	{
152
	  lastp = &p->_next;
154
	  lastp = &p->_next;
153
	  p = p->_next;
155
	  p = p->_next;
154
	}
156
	}
155
#endif
157
#endif
156
    }
158
    }
157
#ifndef __SINGLE_THREAD__
159
#ifndef __SINGLE_THREAD__
158
  __lock_release_recursive(__atexit_lock);
160
  __lock_release_recursive(__atexit_lock);
159
#endif
161
#endif
160
 
162
 
161
}
163
}