Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef P99_CLIB_H
00014 #define P99_CLIB_H 1
00015
00016 #include "p99_for.h"
00017 #include "p99_new.h"
00018
00019
00020 # if __STDC_VERSION__ < 201100L
00021
00022 # include "p99_atomic.h"
00023
00024
00025
00026 # if (_XOPEN_SOURCE >= 600) || defined(P00_DOXYGEN)
00027
00034 #define p00_has_feature_aligned_alloc 1
00035 #define p00_has_extension_aligned_alloc 1
00036 #define p00_has_feature_quick_exit 1
00037 #define p00_has_extension_quick_exit 1
00038 #if defined(P99_LIFO_POP) || defined(P00_DOXYGEN)
00039 # define p00_has_feature_quick_exit_thread_safe 1
00040 # define p00_has_extension_quick_exit_thread_safe 1
00041 #endif
00042
00048 p99_inline
00049 void *aligned_alloc(size_t p00_alignment, size_t p00_size) {
00050 void * p00_ret = 0;
00051 int err = posix_memalign(&p00_ret, p00_alignment, p00_size);
00052
00053
00054
00055 if (err && p00_ret) {
00056 free(p00_ret);
00057 p00_ret = 0;
00058 }
00059 return p00_ret;
00060 }
00061
00062 typedef struct p00_aqe_el p00_aqe_el;
00063 P99_POINTER_TYPE(p00_aqe_el);
00064 #ifndef P00_DOXYGEN
00065 # if p99_has_feature(quick_exit_thread_safe)
00066 P99_DECLARE_ATOMIC(p00_aqe_el_ptr);
00067 typedef _Atomic(p00_aqe_el_ptr) p00_aqe_list;
00068 # else
00069 typedef p00_aqe_el_ptr p00_aqe_list;
00070 # endif
00071 #endif
00072
00073 typedef void p00_aqe_func(void);
00074
00075 struct p00_aqe_el {
00076 p00_aqe_el_ptr p99_lifo;
00077 p00_aqe_func * p00_func;
00078 };
00079
00080
00081 p99_inline
00082 p00_aqe_el* p00_aqe_el_init(p00_aqe_el * p00_obj, p00_aqe_func* p00_func) {
00083 if (p00_obj) {
00084 *p00_obj = (p00_aqe_el) { .p00_func = p00_func };
00085 }
00086 return p00_obj;
00087 }
00088
00089 p99_inline
00090 p00_aqe_el* p00_at_quick_exit_top(p00_aqe_list* p00_l) {
00091 #if p99_has_feature(quick_exit_thread_safe)
00092 return P99_LIFO_TOP(p00_l);
00093 #else
00094 return *p00_l;
00095 #endif
00096 }
00097
00098 p99_inline
00099 void p00_at_quick_exit_push(p00_aqe_list* p00_l, p00_aqe_el* p00_el) {
00100 #if p99_has_feature(quick_exit_thread_safe)
00101 P99_LIFO_PUSH(p00_l, p00_el);
00102 #else
00103 p00_el->p99_lifo = *p00_l;
00104 *p00_l = p00_el;
00105 #endif
00106 }
00107
00108 p99_inline
00109 p00_aqe_el* p00_at_quick_exit_pop(p00_aqe_list* p00_l) {
00110 #if p99_has_feature(quick_exit_thread_safe)
00111 return P99_LIFO_POP(p00_l);
00112 #else
00113 p00_aqe_el *p00_el = p00_at_quick_exit_top(p00_l);
00114 if (p00_el) {
00115 *p00_l = p00_el->p99_lifo;
00116 p00_el->p99_lifo = 0;
00117 }
00118 return p00_el;
00119 #endif
00120 }
00121
00122
00123
00124 P99_WEAK(p00_aqe)
00125 p00_aqe_list p00_at_quick_exit;
00126
00127 p99_inline
00128 int at_quick_exit(void (*p00_func)(void)) {
00129 int ret = 0;
00130 p00_aqe_el *el = P99_NEW(p00_aqe_el, p00_func);
00131 ret = !el;
00132 if (P99_LIKELY(!ret)) p00_at_quick_exit_push(&p00_at_quick_exit, el);
00133 return ret;
00134 }
00135
00136 p99_inline
00137 _Noreturn void quick_exit(int status) {
00138 for (;;) {
00139 p00_aqe_el *el = p00_at_quick_exit_pop(&p00_at_quick_exit);
00140 if (P99_UNLIKELY(!el)) break;
00141 p00_aqe_func * p00_func = el->p00_func;
00142 free(el);
00143 p00_func();
00144 }
00145 _Exit(status);
00146 }
00147
00148 P99_WEAK(p00_at_thrd_exit)
00149 p99_tss p00_at_thrd_exit;
00150
00151 #define P00_AT_THRD_EXIT \
00152 (*(p00_aqe_list*)p00_thread_local_get(&(p00_at_thrd_exit), sizeof(p00_aqe_list*)))
00153
00154 P99_SETJMP_INLINE(p00_run_at_thrd_exit)
00155 void p00_run_at_thrd_exit(void * li) {
00156 p00_aqe_list* list = li;
00157 for (;;) {
00158 p00_aqe_el *el = p00_at_quick_exit_pop(list);
00159 if (P99_UNLIKELY(!el)) break;
00160 p00_aqe_func * p00_func = el->p00_func;
00161 free(el);
00162 p00_func();
00163 }
00164 }
00165
00166 p99_tss p00_at_thrd_exit = { .p00_func = p00_run_at_thrd_exit, };
00167
00168
00176 p99_inline
00177 int at_thrd_exit(void (*p00_func)(void)) {
00178 int ret = 0;
00179 p00_aqe_el *el = P99_NEW(p00_aqe_el, p00_func);
00180 ret = !el;
00181 if (P99_LIKELY(!ret)) p00_at_quick_exit_push(&P00_AT_THRD_EXIT, el);
00182 return ret;
00183 }
00184
00189 # endif
00190 # endif
00191 #endif