xref: /php-src/TSRM/TSRM.h (revision 2d6bd164)
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 #elif __PIC__
158 # define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("initial-exec")))
159 #else
160 # define TSRM_TLS_MODEL_ATTR __attribute__((tls_model("local-exec")))
161 #endif
162 
163 #define TSRM_SHUFFLE_RSRC_ID(rsrc_id)		((rsrc_id)+1)
164 #define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id)		((rsrc_id)-1)
165 
166 #define TSRMG(id, type, element)	(TSRMG_BULK(id, type)->element)
167 #define TSRMG_BULK(id, type)	((type) (*((void ***) tsrm_get_ls_cache()))[TSRM_UNSHUFFLE_RSRC_ID(id)])
168 #define TSRMG_FAST(offset, type, element)	(TSRMG_FAST_BULK(offset, type)->element)
169 #define TSRMG_FAST_BULK(offset, type)	((type) (((char*) tsrm_get_ls_cache())+(offset)))
170 
171 #define TSRMG_STATIC(id, type, element)	(TSRMG_BULK_STATIC(id, type)->element)
172 #define TSRMG_BULK_STATIC(id, type)	((type) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(id)])
173 #define TSRMG_FAST_STATIC(offset, type, element)	(TSRMG_FAST_BULK_STATIC(offset, type)->element)
174 #define TSRMG_FAST_BULK_STATIC(offset, type)	((type) (((char*) TSRMLS_CACHE)+(offset)))
175 #define TSRMLS_MAIN_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR;
176 #define TSRMLS_MAIN_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE TSRM_TLS_MODEL_ATTR = NULL;
177 #define TSRMLS_CACHE_EXTERN() extern TSRM_TLS void *TSRMLS_CACHE;
178 #define TSRMLS_CACHE_DEFINE() TSRM_TLS void *TSRMLS_CACHE = NULL;
179 #define TSRMLS_CACHE_UPDATE() TSRMLS_CACHE = tsrm_get_ls_cache()
180 #define TSRMLS_CACHE _tsrm_ls_cache
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 #else /* non ZTS */
187 
188 #define tsrm_env_lock()
189 #define tsrm_env_unlock()
190 
191 #define TSRMG_STATIC(id, type, element)
192 #define TSRMLS_MAIN_CACHE_EXTERN()
193 #define TSRMLS_MAIN_CACHE_DEFINE()
194 #define TSRMLS_CACHE_EXTERN()
195 #define TSRMLS_CACHE_DEFINE()
196 #define TSRMLS_CACHE_UPDATE()
197 #define TSRMLS_CACHE
198 
199 #define TSRM_TLS
200 
201 #endif /* ZTS */
202 
203 #endif /* TSRM_H */
204