Index: TSRM/TSRM.c =================================================================== RCS file: /repository/TSRM/TSRM.c,v retrieving revision 1.61.2.3 diff -u -r1.61.2.3 TSRM.c --- TSRM/TSRM.c 16 Jul 2005 11:50:59 -0000 1.61.2.3 +++ TSRM/TSRM.c 30 Aug 2005 17:33:51 -0000 @@ -94,12 +94,28 @@ #if defined(PTHREADS) /* Thread local storage */ static pthread_key_t tls_key; +# define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what)) +# define tsrm_tls_get() pthread_getspecific(tls_key) + #elif defined(TSRM_ST) static int tls_key; +# define tsrm_tls_set(what) st_thread_setspecific(tls_key, (void*)(what)) +# define tsrm_tls_get() st_thread_getspecific(tls_key) + #elif defined(TSRM_WIN32) static DWORD tls_key; +# define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what)) +# define tsrm_tls_get() TlsGetValue(tls_key) + #elif defined(BETHREADS) static int32 tls_key; +# define tsrm_tls_set(what) tls_set(tls_key, (void*)(what)) +# define tsrm_tls_get() (tsrm_tls_entry*)tls_get(tls_key) + +#else +# define tsrm_tls_set(what) +# define tsrm_tls_get() NULL +# warning tsrm_set_interpreter_context is probably broken on this platform #endif /* Startup TSRM (call once for the entire process) */ @@ -268,16 +284,8 @@ (*thread_resources_ptr)->thread_id = thread_id; (*thread_resources_ptr)->next = NULL; -#if defined(PTHREADS) /* Set thread local storage to this new thread resources structure */ - pthread_setspecific(tls_key, (void *) *thread_resources_ptr); -#elif defined(TSRM_ST) - st_thread_setspecific(tls_key, (void *) *thread_resources_ptr); -#elif defined(TSRM_WIN32) - TlsSetValue(tls_key, (void *) *thread_resources_ptr); -#elif defined(BETHREADS) - tls_set(tls_key, (void*) *thread_resources_ptr); -#endif + tsrm_tls_set(*thread_resources_ptr); if (tsrm_new_thread_begin_handler) { tsrm_new_thread_begin_handler(thread_id, &((*thread_resources_ptr)->storage)); @@ -321,22 +329,13 @@ if(tsrm_tls_table) { #endif if (!th_id) { -#if defined(PTHREADS) /* Fast path for looking up the resources for the current * thread. Its used by just about every call to * ts_resource_ex(). This avoids the need for a mutex lock * and our hashtable lookup. */ - thread_resources = pthread_getspecific(tls_key); -#elif defined(TSRM_ST) - thread_resources = st_thread_getspecific(tls_key); -#elif defined(TSRM_WIN32) - thread_resources = TlsGetValue(tls_key); -#elif defined(BETHREADS) - thread_resources = (tsrm_tls_entry*)tls_get(tls_key); -#else - thread_resources = NULL; -#endif + thread_resources = tsrm_tls_get(); + if (thread_resources) { TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id)); /* Read a specific resource from the thread's resources. @@ -387,6 +386,65 @@ #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; + + while (thread_resources) { + next = thread_resources->next; + + for (i=0; icount; i++) { + if (resource_types_table[i].dtor) { + resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage); + } + } + for (i=0; icount; i++) { + free(thread_resources->storage[i]); + } + free(thread_resources->storage); + free(thread_resources); + thread_resources = next; + } +} + +void *tsrm_set_interpreter_context(void *new_ctx) +{ + tsrm_tls_entry *current; + + current = tsrm_tls_get(); + + /* TODO: unlink current from the global linked list, and replace it + * it with the new context, protected by mutex where/if appropriate */ + + /* Set thread local storage to this new thread resources structure */ + tsrm_tls_set(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; + + thread_id = tsrm_thread_id(); + tsrm_mutex_lock(tsmm_mutex); + + current = tsrm_tls_get(); + + allocate_new_resource(&new_ctx, thread_id); + + /* 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) @@ -417,11 +475,7 @@ } else { tsrm_tls_table[hash_value] = thread_resources->next; } -#if defined(PTHREADS) - pthread_setspecific(tls_key, 0); -#elif defined(TSRM_WIN32) - TlsSetValue(tls_key, 0); -#endif + tsrm_tls_set(0); free(thread_resources); break; } Index: TSRM/TSRM.h =================================================================== RCS file: /repository/TSRM/TSRM.h,v retrieving revision 1.43.2.3 diff -u -r1.43.2.3 TSRM.h --- TSRM/TSRM.h 11 Mar 2005 11:12:07 -0000 1.43.2.3 +++ TSRM/TSRM.h 30 Aug 2005 17:33:51 -0000 @@ -132,6 +132,13 @@ TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler); TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler); +/* these 3 APIs should only be used by people that fully understand the threading model + * used by PHP/Zend and the selected SAPI. */ +TSRM_API void *tsrm_new_interpreter_context(void); +TSRM_API void *tsrm_set_interpreter_context(void *new_ctx); +TSRM_API void tsrm_free_interpreter_context(void *context); +#define TSRM_INTERPRETER_PATCH_APPLIED + #define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1) #define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)