diff options
Diffstat (limited to 'threadproc/win32/thread.c')
-rw-r--r-- | threadproc/win32/thread.c | 102 |
1 files changed, 91 insertions, 11 deletions
diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 569268cd1..7e1c1a8be 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -72,43 +72,52 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } +#if APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; +#endif + static void *dummy_worker(void *opaque) { apr_thread_t *thd = (apr_thread_t *)opaque; void *ret; +#if APR_HAS_THREAD_LOCAL + current_thread = thd; +#endif + TlsSetValue(tls_apr_thread, thd->td); apr_pool_owner_set(thd->pool, 0); ret = thd->func(thd, thd->data); if (!thd->td) { /* detached? */ apr_pool_destroy(thd->pool); } + return ret; } -APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, - apr_threadattr_t *attr, - apr_thread_start_t func, - void *data, apr_pool_t *pool) +static apr_status_t alloc_thread(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, void *data, + apr_pool_t *pool) { apr_status_t stat; - unsigned temp; - HANDLE handle; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; - + /* The thread can be detached anytime (from the creation or later with * apr_thread_detach), so it needs its own pool and allocator to not * depend on a parent pool which could be destroyed before the thread - * exits. The allocator needs no mutex obviously since the pool should + * exits. The allocator needs no mutex obviously since the pool should * not be used nor create children pools outside the thread. */ stat = apr_allocator_create(&allocator); if (stat != APR_SUCCESS) { + if (abort_fn) + abort_fn(stat); return stat; } - stat = apr_pool_create_unmanaged_ex(&p, apr_pool_abort_get(pool), - allocator); + stat = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator); if (stat != APR_SUCCESS) { apr_allocator_destroy(allocator); return stat; @@ -125,6 +134,23 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, (*new)->data = data; (*new)->func = func; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, apr_pool_t *pool) +{ + apr_status_t stat; + unsigned temp; + HANDLE handle; + + stat = alloc_thread(new, attr, func, data, pool); + if (stat != APR_SUCCESS) { + return stat; + } + /* Use 0 for default Thread Stack Size, because that will * default the stack to the same size as the calling thread. */ @@ -133,9 +159,10 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker, (*new), 0, &temp)) == 0) { stat = APR_FROM_OS_ERROR(_doserrno); - apr_pool_destroy(p); + apr_pool_destroy((*new)->pool); return stat; } + if (attr && attr->detach) { CloseHandle(handle); } @@ -146,6 +173,49 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, + apr_threadattr_t *attr, + apr_pool_t *pool) +{ + apr_status_t stat; + + *current = apr_thread_current(); + if (*current) { + return APR_EEXIST; + } + + stat = alloc_thread(current, attr, NULL, NULL, pool); + if (stat != APR_SUCCESS) { + *current = NULL; + return stat; + } + + if (!(attr && attr->detach)) { + (*current)->td = apr_os_thread_current(); + } + +#if APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_thread_current_after_fork(void) +{ +#if APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif +} + +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#if APR_HAS_THREAD_LOCAL + return current_thread; +#else + return NULL; +#endif +} + APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) { thd->exited = 1; @@ -153,6 +223,9 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (!thd->td) { /* detached? */ apr_pool_destroy(thd->pool); } +#if APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif _endthreadex(0); } @@ -209,6 +282,10 @@ APR_DECLARE(void) apr_thread_yield() APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread) { + if (thread == NULL) { + *data = NULL; + return APR_ENOTHREAD; + } return apr_pool_userdata_get(data, key, thread->pool); } @@ -216,6 +293,9 @@ APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, apr_status_t (*cleanup) (void *), apr_thread_t *thread) { + if (thread == NULL) { + return APR_ENOTHREAD; + } return apr_pool_userdata_set(data, key, cleanup, thread->pool); } |