~aleteoryx/muditaos

ref: 660c2211e21f7581fec7b803233436c98e620836 muditaos/module-bsp/board/rt1051/os/__atexit.c -rw-r--r-- 4.4 KiB
660c2211 — Marcin Zieliński [MOS-23] Back button works as save button in Notes 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 *  Common routine to implement atexit-like functionality.
 *
 *  This is also the key function to be configured as lite exit, a size-reduced
 *  implementation of exit that doesn't invoke clean-up functions such as _fini
 *  or global destructors.
 *
 *  Default (without lite exit) call graph is like:
 *  _start -> atexit -> __register_exitproc
 *  _start -> __libc_init_array -> __cxa_atexit -> __register_exitproc
 *  on_exit -> __register_exitproc
 *  _start -> exit -> __call_exitprocs
 *
 *  Here an -> means arrow tail invokes arrow head. All invocations here
 *  are non-weak reference in current newlib/libgloss.
 *
 *  Lite exit makes some of above calls as weak reference, so that size expansive
 *  functions __register_exitproc and __call_exitprocs may not be linked. These
 *  calls are:
 *    _start w-> atexit
 *    __cxa_atexit w-> __register_exitproc
 *    exit w-> __call_exitprocs
 *
 *  Lite exit also makes sure that __call_exitprocs will be referenced as non-weak
 *  whenever __register_exitproc is referenced as non-weak.
 *
 *  Thus with lite exit libs, a program not explicitly calling atexit or on_exit
 *  will escape from the burden of cleaning up code. A program with atexit or on_exit
 *  will work consistently to normal libs.
 *
 *  Lite exit is enabled with --enable-lite-exit, and is controlled with macro
 *  _LITE_EXIT.
 */

#include <stddef.h>
#include <stdlib.h>
#include <reent.h>
#include <sys/lock.h>
#include "atexit.h"

/* Make this a weak reference to avoid pulling in malloc.  */
#ifndef MALLOC_PROVIDED
void *malloc(size_t) _ATTRIBUTE((__weak__));
#endif

#ifdef _LITE_EXIT
/* As __call_exitprocs is weak reference in lite exit, make a
   non-weak reference to it here.  */
const void *__atexit_dummy = &__call_exitprocs;
#endif

#ifndef __SINGLE_THREAD__
extern _LOCK_RECURSIVE_T __atexit_recursive_mutex;
#endif

#ifdef _REENT_GLOBAL_ATEXIT
static struct _atexit _global_atexit0 = _ATEXIT_INIT;
#define _GLOBAL_ATEXIT0 (&_global_atexit0)
#else
#define _GLOBAL_ATEXIT0 (&_GLOBAL_REENT->_atexit0)
#endif

/*
 * Register a function to be performed at exit or on shared library unload.
 */

int __register_exitproc(int type, void (*fn)(void), void *arg, void *d)
{
    struct _on_exit_args *args;
    register struct _atexit *p;

#ifndef __SINGLE_THREAD__
    __lock_acquire_recursive(__atexit_recursive_mutex);
#endif

    p = _GLOBAL_ATEXIT;
    if (p == NULL) {
        _GLOBAL_ATEXIT = p = _GLOBAL_ATEXIT0;
#ifdef _REENT_SMALL
        extern struct _on_exit_args *const __on_exit_args _ATTRIBUTE((weak));
        if (&__on_exit_args != NULL)
            p->_on_exit_args_ptr = __on_exit_args;
#endif /* def _REENT_SMALL */
    }
    if (p->_ind >= _ATEXIT_SIZE) {
#if !defined(_ATEXIT_DYNAMIC_ALLOC) || !defined(MALLOC_PROVIDED)
#ifndef __SINGLE_THREAD__
        __lock_release_recursive(__atexit_recursive_mutex);
#endif
        return -1;
#else
        p = (struct _atexit *)malloc(sizeof *p);
        if (p == NULL) {
#ifndef __SINGLE_THREAD__
            __lock_release_recursive(__atexit_recursive_mutex);
#endif
            return -1;
        }
        p->_ind                   = 0;
        p->_next                  = _GLOBAL_ATEXIT;
        _GLOBAL_ATEXIT            = p;
#ifndef _REENT_SMALL
        p->_on_exit_args._fntypes = 0;
        p->_on_exit_args._is_cxa  = 0;
#else
        p->_on_exit_args_ptr = NULL;
#endif
#endif
    }

    if (type != __et_atexit) {
#ifdef _REENT_SMALL
        args = p->_on_exit_args_ptr;
        if (args == NULL) {
#ifndef _ATEXIT_DYNAMIC_ALLOC
#ifndef __SINGLE_THREAD__
            __lock_release_recursive(__atexit_recursive_mutex);
#endif
            return -1;
#else
            if (malloc)
                args = malloc(sizeof *p->_on_exit_args_ptr);

            if (args == NULL) {
#ifndef __SINGLE_THREAD__
                __lock_release(__atexit_recursive_mutex);
#endif
                return -1;
            }
            args->_fntypes       = 0;
            args->_is_cxa        = 0;
            p->_on_exit_args_ptr = args;
#endif
        }
#else
        args                      = &p->_on_exit_args;
#endif
        args->_fnargs[p->_ind] = arg;
        args->_fntypes |= (1 << p->_ind);
        args->_dso_handle[p->_ind] = d;
        if (type == __et_cxa)
            args->_is_cxa |= (1 << p->_ind);
    }
    p->_fns[p->_ind++] = fn;
#ifndef __SINGLE_THREAD__
    __lock_release_recursive(__atexit_recursive_mutex);
#endif
    return 0;
}