diff options
Diffstat (limited to 'TSRM/TSRM.c')
-rw-r--r-- | TSRM/TSRM.c | 145 |
1 files changed, 85 insertions, 60 deletions
diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index 9fb8abd3a4..ed1f24f8b8 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -55,8 +55,9 @@ static int resource_types_table_size; static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */ /* New thread handlers */ -static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler; -static tsrm_thread_end_func_t tsrm_new_thread_end_handler; +static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler = NULL; +static tsrm_thread_end_func_t tsrm_new_thread_end_handler = NULL; +static tsrm_shutdown_func_t tsrm_shutdown_handler = NULL; /* Debug support */ int tsrm_error(int level, const char *format, ...); @@ -125,9 +126,11 @@ static int32 tls_key; # warning tsrm_set_interpreter_context is probably broken on this platform #endif +TSRM_TLS uint8_t in_main_thread = 0; + /* Startup TSRM (call once for the entire process) */ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename) -{ +{/*{{{*/ #if defined(GNUPTH) pth_init(); pth_key_create(&tls_key, 0); @@ -142,6 +145,9 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu tls_key = tls_allocate(); #endif + /* ensure singleton */ + in_main_thread = 1; + tsrm_error_file = stderr; tsrm_error_set(debug_level, debug_filename); tsrm_tls_table_size = expected_threads; @@ -164,18 +170,21 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu tsmm_mutex = tsrm_mutex_alloc(); - tsrm_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL; - TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources)); return 1; -} +}/*}}}*/ /* Shutdown TSRM (call once for the entire process) */ TSRM_API void tsrm_shutdown(void) -{ +{/*{{{*/ int i; + if (!in_main_thread) { + /* ensure singleton */ + return; + } + if (tsrm_tls_table) { for (i=0; i<tsrm_tls_table_size; i++) { tsrm_tls_entry *p = tsrm_tls_table[i], *next_p; @@ -218,12 +227,18 @@ TSRM_API void tsrm_shutdown(void) #elif defined(TSRM_WIN32) TlsFree(tls_key); #endif -} + if (tsrm_shutdown_handler) { + tsrm_shutdown_handler(); + } + tsrm_new_thread_begin_handler = NULL; + tsrm_new_thread_end_handler = NULL; + tsrm_shutdown_handler = NULL; +}/*}}}*/ /* allocates a new thread-safe-resource id */ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor) -{ +{/*{{{*/ int i; TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size)); @@ -274,11 +289,11 @@ TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id)); return *rsrc_id; -} +}/*}}}*/ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id) -{ +{/*{{{*/ int i; TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id)); @@ -314,25 +329,16 @@ static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_ } tsrm_mutex_unlock(tsmm_mutex); -} +}/*}}}*/ /* fetches the requested resource for the current thread */ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id) -{ +{/*{{{*/ THREAD_T thread_id; int hash_value; tsrm_tls_entry *thread_resources; -#ifdef NETWARE - /* The below if loop is added for NetWare to fix an abend while unloading PHP - * when an Apache unload command is issued on the system console. - * While exiting from PHP, at the end for some reason, this function is called - * with tsrm_tls_table = NULL. When this happened, the server abends when - * tsrm_tls_table is accessed since it is NULL. - */ - if(tsrm_tls_table) { -#endif if (!th_id) { /* Fast path for looking up the resources for the current * thread. Its used by just about every call to @@ -386,15 +392,12 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id) * changes to the structure as we read it. */ TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count); -#ifdef NETWARE - } /* if(tsrm_tls_table) */ -#endif -} +}/*}}}*/ /* frees an interpreter context. You are responsible for making sure that * it is not linked into the TSRM hash, and not marked as the current interpreter */ void tsrm_free_interpreter_context(void *context) -{ +{/*{{{*/ tsrm_tls_entry *next, *thread_resources = (tsrm_tls_entry*)context; int i; @@ -413,10 +416,10 @@ void tsrm_free_interpreter_context(void *context) free(thread_resources); thread_resources = next; } -} +}/*}}}*/ void *tsrm_set_interpreter_context(void *new_ctx) -{ +{/*{{{*/ tsrm_tls_entry *current; current = tsrm_tls_get(); @@ -429,12 +432,12 @@ void *tsrm_set_interpreter_context(void *new_ctx) /* return old context, so caller can restore it when they're done */ return current; -} +}/*}}}*/ /* allocates a new interpreter context */ void *tsrm_new_interpreter_context(void) -{ +{/*{{{*/ tsrm_tls_entry *new_ctx, *current; THREAD_T thread_id; @@ -448,12 +451,12 @@ void *tsrm_new_interpreter_context(void) /* switch back to the context that was in use prior to our creation * of the new one */ return tsrm_set_interpreter_context(current); -} +}/*}}}*/ /* frees all resources allocated for the current thread */ void ts_free_thread(void) -{ +{/*{{{*/ tsrm_tls_entry *thread_resources; int i; THREAD_T thread_id = tsrm_thread_id(); @@ -490,12 +493,12 @@ void ts_free_thread(void) thread_resources = thread_resources->next; } tsrm_mutex_unlock(tsmm_mutex); -} +}/*}}}*/ /* frees all resources allocated for all threads except current */ void ts_free_worker_threads(void) -{ +{/*{{{*/ tsrm_tls_entry *thread_resources; int i; THREAD_T thread_id = tsrm_thread_id(); @@ -536,12 +539,12 @@ void ts_free_worker_threads(void) } } tsrm_mutex_unlock(tsmm_mutex); -} +}/*}}}*/ /* deallocates all occurrences of a given id */ void ts_free_id(ts_rsrc_id id) -{ +{/*{{{*/ int i; int j = TSRM_UNSHUFFLE_RSRC_ID(id); @@ -570,7 +573,7 @@ void ts_free_id(ts_rsrc_id id) tsrm_mutex_unlock(tsmm_mutex); TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id)); -} +}/*}}}*/ @@ -581,7 +584,7 @@ void ts_free_id(ts_rsrc_id id) /* Obtain the current thread id */ TSRM_API THREAD_T tsrm_thread_id(void) -{ +{/*{{{*/ #ifdef TSRM_WIN32 return GetCurrentThreadId(); #elif defined(GNUPTH) @@ -597,12 +600,12 @@ TSRM_API THREAD_T tsrm_thread_id(void) #elif defined(BETHREADS) return find_thread(NULL); #endif -} +}/*}}}*/ /* Allocate a mutex */ TSRM_API MUTEX_T tsrm_mutex_alloc(void) -{ +{/*{{{*/ MUTEX_T mutexp; #ifdef TSRM_WIN32 mutexp = malloc(sizeof(CRITICAL_SECTION)); @@ -628,12 +631,12 @@ TSRM_API MUTEX_T tsrm_mutex_alloc(void) printf("Mutex created thread: %d\n",mythreadid()); #endif return( mutexp ); -} +}/*}}}*/ /* Free a mutex */ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp) -{ +{/*{{{*/ if (mutexp) { #ifdef TSRM_WIN32 DeleteCriticalSection(mutexp); @@ -657,7 +660,7 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp) #ifdef THR_DEBUG printf("Mutex freed thread: %d\n",mythreadid()); #endif -} +}/*}}}*/ /* @@ -665,7 +668,7 @@ TSRM_API void tsrm_mutex_free(MUTEX_T mutexp) A return value of 0 indicates success */ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp) -{ +{/*{{{*/ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id())); #ifdef TSRM_WIN32 EnterCriticalSection(mutexp); @@ -689,7 +692,7 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp) return acquire_sem(mutexp->sem); return 0; #endif -} +}/*}}}*/ /* @@ -697,7 +700,7 @@ TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp) A return value of 0 indicates success */ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp) -{ +{/*{{{*/ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id())); #ifdef TSRM_WIN32 LeaveCriticalSection(mutexp); @@ -721,14 +724,14 @@ TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp) return release_sem(mutexp->sem); return 0; #endif -} +}/*}}}*/ /* Changes the signal mask of the calling thread */ #ifdef HAVE_SIGPROCMASK TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset) -{ +{/*{{{*/ TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Changed sigmask in thread: %ld", tsrm_thread_id())); /* TODO: add support for other APIs */ #ifdef PTHREADS @@ -736,27 +739,35 @@ TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset) #else return sigprocmask(how, set, oldset); #endif -} +}/*}}}*/ #endif TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler) -{ +{/*{{{*/ void *retval = (void *) tsrm_new_thread_begin_handler; tsrm_new_thread_begin_handler = new_thread_begin_handler; return retval; -} +}/*}}}*/ TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler) -{ +{/*{{{*/ void *retval = (void *) tsrm_new_thread_end_handler; tsrm_new_thread_end_handler = new_thread_end_handler; return retval; -} +}/*}}}*/ + +TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler) +{/*{{{*/ + void *retval = (void *) tsrm_shutdown_handler; + + tsrm_shutdown_handler = shutdown_handler; + return retval; +}/*}}}*/ /* @@ -765,7 +776,7 @@ TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread #if TSRM_DEBUG int tsrm_error(int level, const char *format, ...) -{ +{/*{{{*/ if (level<=tsrm_error_level) { va_list args; int size; @@ -780,12 +791,12 @@ int tsrm_error(int level, const char *format, ...) } else { return 0; } -} +}/*}}}*/ #endif void tsrm_error_set(int level, char *debug_filename) -{ +{/*{{{*/ tsrm_error_level = level; #if TSRM_DEBUG @@ -802,11 +813,25 @@ void tsrm_error_set(int level, char *debug_filename) tsrm_error_file = stderr; } #endif -} +}/*}}}*/ TSRM_API void *tsrm_get_ls_cache(void) -{ +{/*{{{*/ return tsrm_tls_get(); -} +}/*}}}*/ + +TSRM_API uint8_t tsrm_is_main_thread(void) +{/*{{{*/ + return in_main_thread; +}/*}}}*/ #endif /* ZTS */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: sw=4 ts=4 fdm=marker + * vim<600: sw=4 ts=4 + */ |