27 RCSIDH(atexit_h,
"$Id: 0b1721146657499c29e423cbfcebad73f41bdec4 $")
32 #include <freeradius-devel/util/talloc.h>
59 #define fr_atexit_global(_func, _uctx) _atexit_global(__FILE__, __LINE__, _func, _uctx)
75 #ifdef TLS_STORAGE_CLASS
76 # define _Thread_local TLS_STORAGE_CLASS
88 if (init_func)
if (init_func(
uctx) < 0)
return -1;
99 static inline int fr_atexit_talloc_free(
void *to_free)
127 #define fr_atexit_global_once_ret(_ret, _init, _free, _uctx) \
129 static atomic_bool _init_done = false; \
130 static pthread_mutex_t _init_mutex = PTHREAD_MUTEX_INITIALIZER; \
131 void *_our_uctx = _uctx; \
133 if (unlikely(!atomic_load(&_init_done))) { \
134 pthread_mutex_lock(&_init_mutex); \
135 if (!atomic_load(&_init_done)) { \
136 if (_fr_atexit_global_once_funcs(_init, _free, _our_uctx) < 0) { \
139 atomic_store(&_init_done, true); \
141 pthread_mutex_unlock(&_init_mutex); \
166 #define fr_atexit_global_once(_init, _free, _uctx) \
167 fr_atexit_global_once_ret(&(int){ 0 }, _init, _free, _uctx)
182 # define fr_atexit_thread_local(_name, _free, _uctx) \
184 void *_our_uctx = _uctx; \
185 _fr_atexit_thread_local(__FILE__, __LINE__, _free, _our_uctx); \
189 int _fr_atexit_thread_local(
char const *
file,
int line,
198 bool fr_atexit_thread_is_exiting(
void);
210 # define __Thread_local
211 # define fr_atexit_global_once(_init, _free, _uctx) \
213 static bool _init_done = false; \
214 void * _our_uctx = _uctx; \
215 if (unlikely(!_init_done)) { \
217 fr_atexit_global(_free, _our_uctx); \
221 # define fr_atexit_thread_local(_name, _free, _uctx) \
223 static bool _init_done = false; \
224 void * _our_uctx = _uctx; \
225 if (unlikely(!_init_done)) { \
226 fr_atexit_global(_free, _our_uctx); \
231 # define fr_atexit_thread_local_disarm(...) fr_atexit_global_disarm(__VA_ARGS__)
232 # define fr_atexit_thread_local_disarm_all(...) fr_atexit_global_disarm_all(__VA_ARGS__)
233 # define fr_atexit_thread_trigger_all(...)
int(* fr_atexit_t)(void *uctx)
Destructor callback.
unsigned int fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx)
Remove a specific global destructor (without executing it)
#define fr_atexit_thread_trigger_all(...)
#define fr_atexit_thread_local_disarm(...)
int fr_atexit_global_setup(void)
Setup the atexit handler, should be called at the start of a program's execution.
void fr_atexit_global_disarm_all(void)
Remove all global destructors (without executing them)
#define fr_atexit_thread_local_disarm_all(...)
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
bool fr_atexit_is_exiting(void)
Return whether we're currently in the teardown phase.
int fr_atexit_global_trigger_all(void)
Cause all global free triggers to fire.
int fr_atexit_trigger(bool uctx_scope, fr_atexit_t func, void const *uctx)
Iterates through all thread local destructor lists, causing destructor to be triggered.
int _atexit_global(char const *file, int line, fr_atexit_t func, void const *uctx)
Add a free function to be called when the process exits.
fr_dcursor_eval_t void const * uctx