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@zend.com> |
10 +----------------------------------------------------------------------+
16 #if !defined(__CYGWIN__) && defined(WIN32)
18 # include "tsrm_config.w32.h"
20 # include <tsrm_config.h>
25 # define TSRM_API __declspec(dllexport)
27 # define TSRM_API __declspec(dllimport)
29 #elif defined(__GNUC__) && __GNUC__ >= 4
30 # define TSRM_API __attribute__ ((__visibility__("default")))
36 typedef __int64 tsrm_intptr_t
;
37 typedef unsigned __int64 tsrm_uintptr_t
;
39 typedef long tsrm_intptr_t
;
40 typedef unsigned long tsrm_uintptr_t
;
43 /* Only compile multi-threading functions if we're in ZTS mode */
47 # ifndef TSRM_INCLUDE_FULL_WINDOWS_HEADERS
48 # define WIN32_LEAN_AND_MEAN
51 # include <shellapi.h>
54 #elif defined(PTHREADS)
56 #elif defined(TSRM_ST)
58 #elif defined(BETHREADS)
59 #include <kernel/OS.h>
63 typedef int ts_rsrc_id
;
65 /* Define THREAD_T and MUTEX_T */
67 # define THREAD_T DWORD
68 # define MUTEX_T CRITICAL_SECTION *
70 # define THREAD_T pth_t
71 # define MUTEX_T pth_mutex_t *
72 #elif defined(PTHREADS)
73 # define THREAD_T pthread_t
74 # define MUTEX_T pthread_mutex_t *
76 # define THREAD_T SYS_THREAD
77 # define MUTEX_T CRITICAL
79 # define THREAD_T PIThread *
80 # define MUTEX_T PISync *
81 #elif defined(TSRM_ST)
82 # define THREAD_T st_thread_t
83 # define MUTEX_T st_mutex_t
84 #elif defined(BETHREADS)
85 # define THREAD_T thread_id
90 # define MUTEX_T beos_ben *
97 typedef void (*ts_allocate_ctor
)(void *, void ***);
98 typedef void (*ts_allocate_dtor
)(void *, void ***);
100 #define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
108 /* startup/shutdown */
109 TSRM_API
int tsrm_startup(int expected_threads
, int expected_resources
, int debug_level
, char *debug_filename
);
110 TSRM_API
void tsrm_shutdown(void);
112 /* allocates a new thread-safe-resource id */
113 TSRM_API ts_rsrc_id
ts_allocate_id(ts_rsrc_id
*rsrc_id
, size_t size
, ts_allocate_ctor ctor
, ts_allocate_dtor dtor
);
115 #define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
116 #define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
123 #if (defined (__GNUC__) && __GNUC__ > 2 ) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX)
124 # define TSRM_UNEXPECTED(condition) __builtin_expect(condition, 0)
126 # define TSRM_UNEXPECTED(condition) (condition)
129 #include "hphp/util/thread-local.h"
131 typedef std::vector
<void*> TSRMStorageVector
;
132 extern DECLARE_THREAD_LOCAL(TSRMStorageVector
, tsrm_thread_resources
);
133 void * ts_init_resource(int id
);
136 void* ts_resource_from_vector(const TSRMStorageVector
& vec
, ts_rsrc_id id
) {
139 if (TSRM_UNEXPECTED(vec
.size() <= TSRM_UNSHUFFLE_RSRC_ID(id
))) {
140 return ts_init_resource(id
);
142 ret
= vec
[TSRM_UNSHUFFLE_RSRC_ID(id
)];
143 if (TSRM_UNEXPECTED(ret
== nullptr)) {
144 return ts_init_resource(id
);
152 static inline void *ts_resource_ex(ts_rsrc_id id
, THREAD_T
*th_id
) {
153 assert(th_id
== NULL
); // unimplemented
154 return HPHP::ts_resource_from_vector(*HPHP::tsrm_thread_resources
, id
);
158 /* fetches the requested resource for the current thread */
159 TSRM_API
void *ts_resource_ex(ts_rsrc_id id
, THREAD_T
*th_id
);
161 #define ts_resource(id) ts_resource_ex(id, NULL)
163 /* frees all resources allocated for the current thread */
164 TSRM_API
void ts_free_thread(void);
166 /* frees all resources allocated for all threads except current */
167 void ts_free_worker_threads(void);
169 /* deallocates all occurrences of a given id */
170 TSRM_API
void ts_free_id(ts_rsrc_id id
);
174 #define TSRM_ERROR_LEVEL_ERROR 1
175 #define TSRM_ERROR_LEVEL_CORE 2
176 #define TSRM_ERROR_LEVEL_INFO 3
178 typedef void (*tsrm_thread_begin_func_t
)(THREAD_T thread_id
, void ***tsrm_ls
);
179 typedef void (*tsrm_thread_end_func_t
)(THREAD_T thread_id
, void ***tsrm_ls
);
182 TSRM_API
int tsrm_error(int level
, const char *format
, ...);
183 TSRM_API
void tsrm_error_set(int level
, char *debug_filename
);
185 /* utility functions */
186 TSRM_API THREAD_T
tsrm_thread_id(void);
187 TSRM_API MUTEX_T
tsrm_mutex_alloc(void);
188 TSRM_API
void tsrm_mutex_free(MUTEX_T mutexp
);
189 TSRM_API
int tsrm_mutex_lock(MUTEX_T mutexp
);
190 TSRM_API
int tsrm_mutex_unlock(MUTEX_T mutexp
);
191 #ifdef HAVE_SIGPROCMASK
192 TSRM_API
int tsrm_sigmask(int how
, const sigset_t
*set
, sigset_t
*oldset
);
195 TSRM_API
void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler
);
196 TSRM_API
void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler
);
198 /* these 3 APIs should only be used by people that fully understand the threading model
199 * used by PHP/Zend and the selected SAPI. */
200 TSRM_API
void *tsrm_new_interpreter_context(void);
201 TSRM_API
void *tsrm_set_interpreter_context(void *new_ctx
);
202 TSRM_API
void tsrm_free_interpreter_context(void *context
);
206 #define TSRMLS_FETCH() void ***tsrm_ls = reinterpret_cast<void***>(HPHP::tsrm_thread_resources.get())
207 #define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
208 #define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
209 #define TSRMG(id, type, element) \
210 (static_cast<type>(HPHP::ts_resource_from_vector( \
211 *reinterpret_cast<HPHP::TSRMStorageVector*>(tsrm_ls), id))->element)
214 #define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)
215 #define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
216 #define TSRMLS_SET_CTX(ctx) ctx = (void ***) tsrm_ls
217 #define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
221 #define TSRMLS_D void ***tsrm_ls
222 #define TSRMLS_DC , TSRMLS_D
223 #define TSRMLS_C tsrm_ls
224 #define TSRMLS_CC , TSRMLS_C
234 #define TSRMLS_FETCH()
235 #define TSRMLS_FETCH_FROM_CTX(ctx)
236 #define TSRMLS_SET_CTX(ctx)
237 #define TSRMLS_D void