27RCSIDH(atexit_h,
"$Id: 6bff98f54c5da57ff98267e112dbb6c310d76b42 $")
31#include <freeradius-devel/util/talloc.h>
58#define fr_atexit_global(_func, _uctx) _atexit_global(__FILE__, __LINE__, _func, _uctx)
74#ifdef TLS_STORAGE_CLASS
75# define _Thread_local TLS_STORAGE_CLASS
87 if (init_func)
if (init_func(uctx) < 0)
return -1;
98static inline int fr_atexit_talloc_free(
void *to_free)
126#define fr_atexit_global_once_ret(_ret, _init, _free, _uctx) \
128 static atomic_bool _init_done = false; \
129 static pthread_mutex_t _init_mutex = PTHREAD_MUTEX_INITIALIZER; \
130 void *_our_uctx = _uctx; \
132 if (unlikely(!atomic_load(&_init_done))) { \
133 pthread_mutex_lock(&_init_mutex); \
134 if (!atomic_load(&_init_done)) { \
135 if (_fr_atexit_global_once_funcs(_init, _free, _our_uctx) < 0) { \
138 atomic_store(&_init_done, true); \
140 pthread_mutex_unlock(&_init_mutex); \
165#define fr_atexit_global_once(_init, _free, _uctx) \
166 fr_atexit_global_once_ret(&(int){ 0 }, _init, _free, _uctx)
181# define fr_atexit_thread_local(_name, _free, _uctx) \
183 void *_our_uctx = _uctx; \
184 _fr_atexit_thread_local(__FILE__, __LINE__, _free, _our_uctx); \
188int _fr_atexit_thread_local(
char const *
file,
int line,
197bool fr_atexit_thread_is_exiting(
void);
209# define __Thread_local
210# define fr_atexit_global_once(_init, _free, _uctx) \
212 static bool _init_done = false; \
213 void * _our_uctx = _uctx; \
214 if (unlikely(!_init_done)) { \
216 fr_atexit_global(_free, _our_uctx); \
220# define fr_atexit_thread_local(_name, _free, _uctx) \
222 static bool _init_done = false; \
223 void * _our_uctx = _uctx; \
224 if (unlikely(!_init_done)) { \
225 fr_atexit_global(_free, _our_uctx); \
230# define fr_atexit_thread_local_disarm(...) fr_atexit_global_disarm(__VA_ARGS__)
231# define fr_atexit_thread_local_disarm_all(...) fr_atexit_global_disarm_all(__VA_ARGS__)
232# 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.