1 /* 2 +----------------------------------------------------------------------+ 3 | Thread Safe Resource Manager | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1999-2011, Andi Gutmans, Sascha Schumann, Zeev Suraski | 6 | This source file is subject to the TSRM license, that is bundled | 7 | with this package in the file LICENSE | 8 +----------------------------------------------------------------------+ 9 | Authors: Zeev Suraski <zeev@php.net> | 10 +----------------------------------------------------------------------+ 11 */ 12 13 #ifndef TSRM_H 14 #define TSRM_H 15 16 #if !defined(__CYGWIN__) && defined(_WIN32) 17 # define TSRM_WIN32 18 # include <Zend/zend_config.w32.h> 19 #else 20 # include <main/php_config.h> 21 #endif 22 23 #include <stdint.h> 24 #include <stdbool.h> 25 26 #ifdef TSRM_WIN32 27 # ifdef TSRM_EXPORTS 28 # define TSRM_API __declspec(dllexport) 29 # else 30 # define TSRM_API __declspec(dllimport) 31 # endif 32 #elif defined(__GNUC__) && __GNUC__ >= 4 33 # define TSRM_API __attribute__ ((visibility("default"))) 34 #else 35 # define TSRM_API 36 #endif 37 38 typedef intptr_t tsrm_intptr_t; 39 typedef uintptr_t tsrm_uintptr_t; 40 41 /* Only compile multi-threading functions if we're in ZTS mode */ 42 #ifdef ZTS 43 44 #ifdef TSRM_WIN32 45 # ifndef TSRM_INCLUDE_FULL_WINDOWS_HEADERS 46 # define WIN32_LEAN_AND_MEAN 47 # endif 48 #else 49 # include <pthread.h> 50 #endif 51 52 #if SIZEOF_SIZE_T == 4 53 # define TSRM_ALIGNED_SIZE(size) \ 54 (((size) + INT32_C(15)) & ~INT32_C(15)) 55 #else 56 # define TSRM_ALIGNED_SIZE(size) \ 57 (((size) + INT64_C(15)) & ~INT64_C(15)) 58 #endif 59 60 typedef int ts_rsrc_id; 61 62 /* Define THREAD_T and MUTEX_T */ 63 #ifdef TSRM_WIN32 64 # define THREAD_T DWORD 65 # define MUTEX_T CRITICAL_SECTION * 66 #else 67 # define THREAD_T pthread_t 68 # define MUTEX_T pthread_mutex_t * 69 #endif 70 71 #include <signal.h> 72 73 typedef void (*ts_allocate_ctor)(void *); 74 typedef void (*ts_allocate_dtor)(void *); 75 76 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts 77 78 #ifdef __cplusplus 79 extern "C" { 80 #endif 81 82 /* startup/shutdown */ 83 TSRM_API bool tsrm_startup(int expected_threads, int expected_resources, int debug_level, const char *debug_filename); 84 TSRM_API void tsrm_shutdown(void); 85 86 /* environ lock API */ 87 TSRM_API void tsrm_env_lock(void); 88 TSRM_API void tsrm_env_unlock(void); 89 90 /* allocates a new thread-safe-resource id */ 91 TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor); 92 93 /* Fast resource in reserved (pre-allocated) space */ 94 TSRM_API void tsrm_reserve(size_t size); 95 TSRM_API ts_rsrc_id ts_allocate_fast_id(ts_rsrc_id *rsrc_id, size_t *offset, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor); 96 97 /* fetches the requested resource for the current thread */ 98 TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id); 99 #define ts_resource(id) ts_resource_ex(id, NULL) 100 101 /* frees all resources allocated for the current thread */ 102 TSRM_API void ts_free_thread(void); 103 104 /* deallocates all occurrences of a given id */ 105 TSRM_API void ts_free_id(ts_rsrc_id id); 106 107 /* Runs a callback on all resources of the given id. 108 * The caller is responsible for ensuring the underlying resources don't data-race. */ 109 TSRM_API void ts_apply_for_id(ts_rsrc_id id, void (*cb)(void *)); 110 111 /* Debug support */ 112 #define TSRM_ERROR_LEVEL_ERROR 1 113 #define TSRM_ERROR_LEVEL_CORE 2 114 #define TSRM_ERROR_LEVEL_INFO 3 115 116 typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id); 117 typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id); 118 typedef void (*tsrm_shutdown_func_t)(void); 119 120 121 TSRM_API int tsrm_error(int level, const char *format, ...); 122 TSRM_API void tsrm_error_set(int level, const char *debug_filename); 123 124 /* utility functions */ 125 TSRM_API THREAD_T tsrm_thread_id(void); 126 TSRM_API MUTEX_T tsrm_mutex_alloc(void); 127 TSRM_API void tsrm_mutex_free(MUTEX_T mutexp); 128 TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp); 129 TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp); 130 #ifdef HAVE_SIGPROCMASK 131 TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset); 132 #endif 133 134 TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler); 135 TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler); 136 TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler); 137 138 TSRM_API void *tsrm_get_ls_cache(void); 139 TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void); 140 TSRM_API bool tsrm_is_main_thread(void); 141 TSRM_API bool tsrm_is_shutdown(void); 142 TSRM_API const char *tsrm_api_name(void); 143 TSRM_API bool tsrm_is_managed_thread(void); 144 145 #ifdef TSRM_WIN32 146 # define TSRM_TLS __declspec(thread) 147 #else 148 # define TSRM_TLS __thread 149 #endif 150 151 #ifndef __has_attribute 152 # define __has_attribute(x) 0 153 #endif 154 155 #if !__has_attribute(tls_model) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__MUSL__) || defined(__HAIKU__) 156 # define TSRM_TLS_MODEL_ATTR 157 # define TSRM_TLS_MODEL_DEFAULT 158 #elif __PIC__ 159 # define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec"))) 160 # define TSRM_TLS_MODEL_INITIAL_EXEC 161 #else 162 # define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("local-exec"))) 163 # define TSRM_TLS_MODEL_LOCAL_EXEC 164 #endif 165 166 #define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1) 167 #define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1) 168 169 #define TSRMG(id, type, element) (TSRMG_BULK(id, type)->element) 170 #define TSRMG_BULK(id, type) ((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)]) 171 #define TSRMG_FAST(offset, type, element) (TSRMG_FAST_BULK(offset, type)->element) 172 #define TSRMG_FAST_BULK(offset, type) ((type) (((char*) tsrm_get_ls_cache())+(offset))) 173 174 #define TSRMG_STATIC(id, type, element) (TSRMG_BULK_STATIC(id, type)->element) 175 #define TSRMG_BULK_STATIC(id, type) ((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)]) 176 #define TSRMG_FAST_STATIC(offset, type, element) (TSRMG_FAST_BULK_STATIC(offset, type)->element) 177 #define TSRMG_FAST_BULK_STATIC(offset, type) ((type) (((char*) TSRMLS_CACHE)+(offset))) 178 #define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR; 179 #define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL; 180 #define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE; 181 #define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL; 182 #define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache() 183 #define TSRMLS_CACHE _tsrm_ls_cache 184 185 #ifdef __cplusplus 186 } 187 #endif 188 189 #else /* non ZTS */ 190 191 #define tsrm_env_lock() 192 #define tsrm_env_unlock() 193 194 #define TSRMG_STATIC(id, type, element) 195 #define TSRMLS_MAIN_CACHE_EXTERN() 196 #define TSRMLS_MAIN_CACHE_DEFINE() 197 #define TSRMLS_CACHE_EXTERN() 198 #define TSRMLS_CACHE_DEFINE() 199 #define TSRMLS_CACHE_UPDATE() 200 #define TSRMLS_CACHE 201 202 #define TSRM_TLS 203 204 #endif /* ZTS */ 205 206 #endif /* TSRM_H */ 207