27RCSIDH(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;
99static 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); \
189int _fr_atexit_thread_local(
char const *
file,
int line,
198bool 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.