From d77a576daf76df4ea5c175ea156ade0ed7f844f1 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Wed, 19 Jan 2022 14:15:49 +0000 Subject: apr_thread: Use compiler's TLS to track the current apr_thread_t's pointer. All modern compilers provide a Thread Local Storage keyword that allows to store per-thread data efficiently (C++11 's thread_local, C11's _Thread_local, gcc/clang's __thread or MSVC's __declspec(thread)). Use that to have an apr_thread_t pointer associated with each thread created by apr_thread_create() or any native thread (like the process' initial thread) that registered itself with the new apr_thread_current_create() function. This mechanism allows to implement apr_thread_current() quite efficiently, if available, otherwise the function returns NULL. If available APR_HAS_THREAD_LOCAL is #define'd to 1 and the APR_THREAD_LOCAL macro is the keyword usable to register TLS variables natively. Both APR_HAS_THREAD_LOCAL and APR_THREAD_LOCAL are #undef'ined if the compiler does not provide the mechanism. This allows to test for the functionality at compile time. When APR_HAS_THREAD_LOCAL, the user can load his/her own TLS data with: apr_thread_data_get(&my_data, my_key, apr_thread_current()); and store them with: apr_thread_data_set(my_data, my_key, my_data_cleanup, apr_thread_current()); which can be nice to avoid the proliferation of native TLS keys. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897207 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_thread_proc.h | 37 ++++++++++++++++ threadproc/beos/thread.c | 85 ++++++++++++++++++++++++++++++++--- threadproc/netware/thread.c | 106 ++++++++++++++++++++++++++++++++++---------- threadproc/os2/thread.c | 84 ++++++++++++++++++++++++++++++++--- threadproc/unix/thread.c | 88 ++++++++++++++++++++++++++++++++---- threadproc/win32/thread.c | 91 +++++++++++++++++++++++++++++++++---- 6 files changed, 435 insertions(+), 56 deletions(-) diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h index b1bd01533..ab1e1a92d 100644 --- a/include/apr_thread_proc.h +++ b/include/apr_thread_proc.h @@ -209,8 +209,27 @@ typedef enum { /* Thread Function definitions */ +#undef APR_HAS_THREAD_LOCAL + #if APR_HAS_THREADS +/** + * APR_THREAD_LOCAL keyword mapping the compiler's. + */ +#if defined(__cplusplus) && __cplusplus >= 201103L +#define APR_THREAD_LOCAL thread_local +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 +#define APR_THREAD_LOCAL _Thread_local +#elif defined(__GNUC__) /* works for clang too */ +#define APR_THREAD_LOCAL __thread +#elif defined(WIN32) && defined(_MSC_VER) +#define APR_THREAD_LOCAL __declspec(thread) +#endif + +#ifdef APR_THREAD_LOCAL +#define APR_HAS_THREAD_LOCAL 1 +#endif + /** * Create and initialize a new threadattr variable * @param new_attr The newly created threadattr. @@ -269,6 +288,24 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new_thread, apr_thread_start_t func, void *data, apr_pool_t *cont); +/** + * Setup the current os_thread as an apr_thread + * @param current The current apr_thread set up (or reused) + * @param attr The threadattr associated with the current thread + * @param pool The parent pool of the current thread + * @return APR_SUCCESS, APR_EEXIST if the current thread is already set, + * any error otherwise + */ +APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, + apr_threadattr_t *attr, + apr_pool_t *pool); +/** + * Get the current thread + * @param The current apr_thread, NULL if it is not an apr_thread or if + * it could not be determined. + */ +APR_DECLARE(apr_thread_t *) apr_thread_current(void); + /** * Stop the current thread * @param thd The thread to stop diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 988f8f4ff..6a3e05806 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -62,32 +62,44 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } +#ifdef APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread; +#endif + static void *dummy_worker(void *opaque) { apr_thread_t *thd = (apr_thread_t*)opaque; void *ret; +#ifdef APR_HAS_THREAD_LOCAL + current_thread = thd; +#endif + apr_pool_owner_set(thd->pool, 0); ret = thd->func(thd, thd->data); if (thd->detached) { apr_pool_destroy(thd->pool); } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif 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) { - int32 temp; apr_status_t stat; 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); @@ -114,6 +126,22 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t (*new)->exitval = -1; (*new)->detached = (attr && apr_threadattr_detach_get(attr) == APR_DETACH); + 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) +{ + int32 temp; + apr_status_t stat; + + stat = alloc_thread(new, attr, func, data, pool); + if (stat != APR_SUCCESS) { + return stat; + } + if (attr) temp = attr->attr; else @@ -126,13 +154,46 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t /* Now we try to run it...*/ if (resume_thread((*new)->td) != B_NO_ERROR) { stat = errno; - apr_pool_destroy(p); + apr_pool_destroy((*new)->pool); return stat; } 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) { + return stat; + } + + (*current)->td = apr_os_thread_current(); + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#ifdef APR_HAS_THREAD_LOCAL + return current_thread; +#else + return NULL; +#endif +} + APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) { return find_thread(NULL); @@ -149,6 +210,9 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->detached) { apr_pool_destroy(thd->pool); } +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif exit_thread ((status_t)(retval)); } @@ -197,6 +261,10 @@ 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); } @@ -204,6 +272,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); } diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index a661ef886..993d2c60d 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -64,35 +64,44 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } +#ifdef APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread; +#endif + static void *dummy_worker(void *opaque) { apr_thread_t *thd = (apr_thread_t *)opaque; void *ret; +#ifdef APR_HAS_THREAD_LOCAL + current_thread = thd; +#endif + apr_pool_owner_set(thd->pool, 0); ret = thd->func(thd, thd->data); if (thd->detached) { apr_pool_destroy(thd->pool); } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif return ret; } -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 long flags = NX_THR_BIND_CONTEXT; - size_t stack_size = APR_DEFAULT_STACK_SIZE; 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); @@ -131,6 +140,24 @@ apr_status_t apr_thread_create(apr_thread_t **new, return APR_ENOMEM; } + 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 long flags = NX_THR_BIND_CONTEXT; + size_t stack_size = APR_DEFAULT_STACK_SIZE; + + stat = alloc_thread(new, attr, func, data, pool); + if (stat != APR_SUCCESS) { + return stat; + } + /* An original stack size of 0 will allow NXCreateThread() to * assign a default system stack size. An original stack * size of less than 0 will assign the APR default stack size. @@ -139,11 +166,11 @@ apr_status_t apr_thread_create(apr_thread_t **new, if (attr && (attr->stack_size >= 0)) { stack_size = attr->stack_size; } - + if (attr && attr->detach) { flags |= NX_THR_DETACHED; } - + (*new)->ctx = NXContextAlloc( /* void(*start_routine)(void *arg) */ (void (*)(void *)) dummy_worker, /* void *arg */ (*new), @@ -151,7 +178,7 @@ apr_status_t apr_thread_create(apr_thread_t **new, /* size_t stackSize */ stack_size, /* unsigned long flags */ NX_CTX_NORMAL, /* int *error */ &stat); - + (void) NXContextSetName( /* NXContext_t ctx */ (*new)->ctx, /* const char *name */ (*new)->thread_name); @@ -162,13 +189,46 @@ apr_status_t apr_thread_create(apr_thread_t **new, /* NXThreadId_t *thread_id */ &(*new)->td); if (stat) { - apr_pool_destroy(p); + apr_pool_destroy((*new)->pool); + return stat; + } + + 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) { return stat; } - + + (*current)->td = apr_os_thread_current(); + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif return APR_SUCCESS; } +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#ifdef APR_HAS_THREAD_LOCAL + return current_thread; +#else + return NULL; +#endif +} + apr_os_thread_t apr_os_thread_current() { return NXThreadGetId(); @@ -190,6 +250,9 @@ void apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->detached) { apr_pool_destroy(thd->pool); } +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif NXThreadExit(NULL); } @@ -227,26 +290,21 @@ apr_status_t apr_thread_detach(apr_thread_t *thd) apr_status_t apr_thread_data_get(void **data, const char *key, apr_thread_t *thread) { - if (thread != NULL) { - return apr_pool_userdata_get(data, key, thread->pool); - } - else { - data = NULL; + if (thread == NULL) { + *data = NULL; return APR_ENOTHREAD; } + return apr_pool_userdata_get(data, key, thread->pool); } 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_pool_userdata_set(data, key, cleanup, thread->pool); - } - else { - data = NULL; + if (thread == NULL) { return APR_ENOTHREAD; } + return apr_pool_userdata_set(data, key, cleanup, thread->pool); } APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index 2891f0577..ffb663e90 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -68,30 +68,43 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } +#ifdef APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread; +#endif + static void dummy_worker(void *opaque) { +#ifdef APR_HAS_THREAD_LOCAL + current_thread = thread; +#endif + apr_thread_t *thread = (apr_thread_t *)opaque; apr_pool_owner_set(thread->pool, 0); thread->exitval = thread->func(thread, thread->data); if (thd->attr->attr & APR_THREADATTR_DETACHED) { apr_pool_destroy(thread->pool); } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif } -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; 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); @@ -124,19 +137,66 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t } (*new)->attr = attr; - (*new)->tid = _beginthread(dummy_worker, NULL, + 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; + + stat = alloc_thread(new, attr, func, data, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + (*new)->tid = _beginthread(dummy_worker, NULL, (*new)->attr->stacksize > 0 ? (*new)->attr->stacksize : APR_THREAD_STACKSIZE, (*new)); if ((*new)->tid < 0) { stat = errno; - apr_pool_destroy(p); + apr_pool_destroy((*new)->pool); return stat; } 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(new, attr, NULL, NULL, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + (*current)->tid = apr_os_thread_current(); + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#ifdef APR_HAS_THREAD_LOCAL + return current_thread; +#else + return NULL; +#endif +} APR_DECLARE(apr_os_thread_t) apr_os_thread_current() @@ -155,6 +215,9 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->attr->attr & APR_THREADATTR_DETACHED) { apr_pool_destroy(thd->pool); } +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif _endthread(); } @@ -232,6 +295,10 @@ int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2) 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); } @@ -241,6 +308,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); } diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index d1ae872c6..eccda7f40 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -136,34 +136,44 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, #endif } +#ifdef APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread; +#endif + static void *dummy_worker(void *opaque) { apr_thread_t *thread = (apr_thread_t*)opaque; void *ret; +#ifdef APR_HAS_THREAD_LOCAL + current_thread = thread; +#endif + apr_pool_owner_set(thread->pool, 0); ret = thread->func(thread, thread->data); if (thread->detached) { apr_pool_destroy(thread->pool); } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif 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; - pthread_attr_t *temp; 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); @@ -194,6 +204,23 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, return APR_ENOMEM; } + 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; + pthread_attr_t *temp; + + stat = alloc_thread(new, attr, func, data, pool); + if (stat != APR_SUCCESS) { + return stat; + } + if (attr) temp = &attr->attr; else @@ -203,13 +230,46 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, #ifdef HAVE_ZOS_PTHREADS stat = errno; #endif - apr_pool_destroy(p); + apr_pool_destroy((*new)->pool); + return stat; + } + + 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) { return stat; } + *(*current)->td = apr_os_thread_current(); + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif return APR_SUCCESS; } +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#ifdef APR_HAS_THREAD_LOCAL + return current_thread; +#else + return NULL; +#endif +} + APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) { return pthread_self(); @@ -228,6 +288,9 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, if (thd->detached) { apr_pool_destroy(thd->pool); } +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif pthread_exit(NULL); } @@ -297,6 +360,10 @@ APR_DECLARE(void) apr_thread_yield(void) 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); } @@ -304,6 +371,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); } diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 569268cd1..3d0cd535b 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -72,35 +72,45 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } +#ifdef APR_HAS_THREAD_LOCAL +static APR_THREAD_LOCAL apr_thread_t *current_thread; +#endif + static void *dummy_worker(void *opaque) { apr_thread_t *thd = (apr_thread_t *)opaque; void *ret; +#ifdef 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); } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif 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_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); @@ -125,6 +135,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 +160,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 +174,41 @@ 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) { + return stat; + } + + if (!(attr && attr->detach)) { + (*new)->td = apr_os_thread_current(); + } + +#ifdef APR_HAS_THREAD_LOCAL + current_thread = *current; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_thread_t *) apr_thread_current(void) +{ +#ifdef 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 +216,9 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (!thd->td) { /* detached? */ apr_pool_destroy(thd->pool); } +#ifdef APR_HAS_THREAD_LOCAL + current_thread = NULL; +#endif _endthreadex(0); } @@ -209,6 +275,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 +286,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); } -- cgit v1.2.1 From 3c0a292ceeabd8a58a984b3279097f033b44659c Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Mon, 24 Jan 2022 14:16:04 +0000 Subject: apr_thread: Follow up to r1897179: abort_fn on apr_allocator_create() failure. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897419 13f79535-47bb-0310-9956-ffa450edef68 --- threadproc/beos/thread.c | 6 ++++-- threadproc/netware/thread.c | 6 ++++-- threadproc/os2/thread.c | 6 ++++-- threadproc/unix/thread.c | 6 ++++-- threadproc/win32/thread.c | 6 ++++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 6a3e05806..501678373 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -93,6 +93,7 @@ static apr_status_t alloc_thread(apr_thread_t **new, apr_pool_t *pool) { apr_status_t stat; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; @@ -104,10 +105,11 @@ static apr_status_t alloc_thread(apr_thread_t **new, */ 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; diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index 993d2c60d..86213a01f 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -95,6 +95,7 @@ static apr_status_t alloc_thread(apr_thread_t **new, apr_pool_t *pool) { apr_status_t stat; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; @@ -106,10 +107,11 @@ static apr_status_t alloc_thread(apr_thread_t **new, */ 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; diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index ffb663e90..bcb3d7b20 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -98,6 +98,7 @@ static apr_status_t alloc_thread(apr_thread_t **new, apr_pool_t *pool) { apr_status_t stat; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; @@ -109,10 +110,11 @@ static apr_status_t alloc_thread(apr_thread_t **new, */ 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; diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index eccda7f40..2b255252c 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -167,6 +167,7 @@ static apr_status_t alloc_thread(apr_thread_t **new, apr_pool_t *pool) { apr_status_t stat; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; @@ -178,10 +179,11 @@ static apr_status_t alloc_thread(apr_thread_t **new, */ 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; diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 3d0cd535b..281a44ac6 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -104,6 +104,7 @@ static apr_status_t alloc_thread(apr_thread_t **new, apr_pool_t *pool) { apr_status_t stat; + apr_abortfunc_t abort_fn = apr_pool_abort_get(pool); apr_allocator_t *allocator; apr_pool_t *p; @@ -115,10 +116,11 @@ static apr_status_t alloc_thread(apr_thread_t **new, */ 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; -- cgit v1.2.1 From 367a9c3c50b18fccf2ca899fc1ea01a221928673 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 25 Jan 2022 10:41:15 +0000 Subject: apr_thread: Follow up to r1897207: Don't NULLify current_thread on exit. It's not needed, when the thread exits it's not accessible anyway. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897445 13f79535-47bb-0310-9956-ffa450edef68 --- threadproc/beos/thread.c | 8 +------- threadproc/netware/thread.c | 8 +------- threadproc/os2/thread.c | 9 +-------- threadproc/unix/thread.c | 8 +------- threadproc/win32/thread.c | 5 +---- 5 files changed, 5 insertions(+), 33 deletions(-) diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 501678373..faa255b63 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -63,7 +63,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, } #ifdef APR_HAS_THREAD_LOCAL -static APR_THREAD_LOCAL apr_thread_t *current_thread; +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void *dummy_worker(void *opaque) @@ -81,9 +81,6 @@ static void *dummy_worker(void *opaque) apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif return ret; } @@ -212,9 +209,6 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->detached) { apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif exit_thread ((status_t)(retval)); } diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index 86213a01f..a160cb71d 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -65,7 +65,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, } #ifdef APR_HAS_THREAD_LOCAL -static APR_THREAD_LOCAL apr_thread_t *current_thread; +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void *dummy_worker(void *opaque) @@ -83,9 +83,6 @@ static void *dummy_worker(void *opaque) apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif return ret; } @@ -252,9 +249,6 @@ void apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->detached) { apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif NXThreadExit(NULL); } diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index bcb3d7b20..3c590a6dc 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -69,7 +69,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, } #ifdef APR_HAS_THREAD_LOCAL -static APR_THREAD_LOCAL apr_thread_t *current_thread; +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void dummy_worker(void *opaque) @@ -84,10 +84,6 @@ static void dummy_worker(void *opaque) if (thd->attr->attr & APR_THREADATTR_DETACHED) { apr_pool_destroy(thread->pool); } - -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif } @@ -217,9 +213,6 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (thd->attr->attr & APR_THREADATTR_DETACHED) { apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif _endthread(); } diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index 2b255252c..6d1874ac8 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -137,7 +137,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, } #ifdef APR_HAS_THREAD_LOCAL -static APR_THREAD_LOCAL apr_thread_t *current_thread; +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void *dummy_worker(void *opaque) @@ -155,9 +155,6 @@ static void *dummy_worker(void *opaque) apr_pool_destroy(thread->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif return ret; } @@ -290,9 +287,6 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, if (thd->detached) { apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif pthread_exit(NULL); } diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 281a44ac6..ee2070bc8 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -73,7 +73,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, } #ifdef APR_HAS_THREAD_LOCAL -static APR_THREAD_LOCAL apr_thread_t *current_thread; +static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void *dummy_worker(void *opaque) @@ -92,9 +92,6 @@ static void *dummy_worker(void *opaque) apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL - current_thread = NULL; -#endif return ret; } -- cgit v1.2.1 From 05023098b8283a21bf1c5229db6c6c73c6407a0e Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 25 Jan 2022 10:53:28 +0000 Subject: apr_thread: Follow up to r1897207: Make APR_HAS_THREAD_LOCAL a boolean.. .. rather than a defined(). git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897447 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_thread_proc.h | 10 +++++++--- threadproc/beos/thread.c | 8 ++++---- threadproc/netware/thread.c | 8 ++++---- threadproc/os2/thread.c | 8 ++++---- threadproc/unix/thread.c | 8 ++++---- threadproc/win32/thread.c | 10 +++++----- 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h index ab1e1a92d..270cb24b2 100644 --- a/include/apr_thread_proc.h +++ b/include/apr_thread_proc.h @@ -209,8 +209,6 @@ typedef enum { /* Thread Function definitions */ -#undef APR_HAS_THREAD_LOCAL - #if APR_HAS_THREADS /** @@ -228,6 +226,8 @@ typedef enum { #ifdef APR_THREAD_LOCAL #define APR_HAS_THREAD_LOCAL 1 +#else +#define APR_HAS_THREAD_LOCAL 0 #endif /** @@ -426,7 +426,11 @@ APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, apr_status_t (*cleanup) (void *), apr_threadkey_t *threadkey); -#endif +#else /* APR_HAS_THREADS */ + +#define APR_HAS_THREAD_LOCAL 0 + +#endif /* APR_HAS_THREADS */ /** * Create and initialize a new procattr variable diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index faa255b63..25bd0d2bb 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -62,7 +62,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif @@ -71,7 +71,7 @@ static void *dummy_worker(void *opaque) apr_thread_t *thd = (apr_thread_t*)opaque; void *ret; -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = thd; #endif @@ -178,7 +178,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, (*current)->td = apr_os_thread_current(); -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = *current; #endif return APR_SUCCESS; @@ -186,7 +186,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, APR_DECLARE(apr_thread_t *) apr_thread_current(void) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL return current_thread; #else return NULL; diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index a160cb71d..40b6d7259 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -64,7 +64,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif @@ -73,7 +73,7 @@ static void *dummy_worker(void *opaque) apr_thread_t *thd = (apr_thread_t *)opaque; void *ret; -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = thd; #endif @@ -213,7 +213,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, (*current)->td = apr_os_thread_current(); -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = *current; #endif return APR_SUCCESS; @@ -221,7 +221,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, APR_DECLARE(apr_thread_t *) apr_thread_current(void) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL return current_thread; #else return NULL; diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index 3c590a6dc..d23be9aed 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -68,13 +68,13 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif static void dummy_worker(void *opaque) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = thread; #endif @@ -181,7 +181,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, (*current)->tid = apr_os_thread_current(); -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = *current; #endif return APR_SUCCESS; @@ -189,7 +189,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, APR_DECLARE(apr_thread_t *) apr_thread_current(void) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL return current_thread; #else return NULL; diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index 6d1874ac8..d3eac6509 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -136,7 +136,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, #endif } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif @@ -145,7 +145,7 @@ static void *dummy_worker(void *opaque) apr_thread_t *thread = (apr_thread_t*)opaque; void *ret; -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = thread; #endif @@ -254,7 +254,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, *(*current)->td = apr_os_thread_current(); -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = *current; #endif return APR_SUCCESS; @@ -262,7 +262,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, APR_DECLARE(apr_thread_t *) apr_thread_current(void) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL return current_thread; #else return NULL; diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index ee2070bc8..c4fd81fff 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -72,7 +72,7 @@ APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, return APR_ENOTIMPL; } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL static APR_THREAD_LOCAL apr_thread_t *current_thread = NULL; #endif @@ -81,7 +81,7 @@ static void *dummy_worker(void *opaque) apr_thread_t *thd = (apr_thread_t *)opaque; void *ret; -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = thd; #endif @@ -193,7 +193,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, (*new)->td = apr_os_thread_current(); } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = *current; #endif return APR_SUCCESS; @@ -201,7 +201,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, APR_DECLARE(apr_thread_t *) apr_thread_current(void) { -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL return current_thread; #else return NULL; @@ -215,7 +215,7 @@ APR_DECLARE(void) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) if (!thd->td) { /* detached? */ apr_pool_destroy(thd->pool); } -#ifdef APR_HAS_THREAD_LOCAL +#if APR_HAS_THREAD_LOCAL current_thread = NULL; #endif _endthreadex(0); -- cgit v1.2.1 From 865e0f3805b4f46d77a43bc661fd793dbaaa7ff6 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 25 Jan 2022 20:14:55 +0000 Subject: apr_thread: Follow up to r1897207: Provide apr_thread_current_after_fork(). thread_local variables are not (always?) reset on fork(), so APR (and the user) needs a way to set the current_thread to NULL. Use apr_thread_current_after_fork() in apr_proc_fork()'s child process. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897470 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_thread_proc.h | 8 +++++++- threadproc/beos/proc.c | 3 +++ threadproc/beos/thread.c | 7 +++++++ threadproc/netware/proc.c | 3 +++ threadproc/netware/thread.c | 7 +++++++ threadproc/os2/proc.c | 3 +++ threadproc/os2/thread.c | 7 +++++++ threadproc/unix/proc.c | 3 +++ threadproc/unix/thread.c | 7 +++++++ threadproc/win32/thread.c | 7 +++++++ 10 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h index 270cb24b2..85f697dd2 100644 --- a/include/apr_thread_proc.h +++ b/include/apr_thread_proc.h @@ -289,7 +289,7 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new_thread, void *data, apr_pool_t *cont); /** - * Setup the current os_thread as an apr_thread + * Setup the current native thread as an apr_thread * @param current The current apr_thread set up (or reused) * @param attr The threadattr associated with the current thread * @param pool The parent pool of the current thread @@ -299,6 +299,12 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new_thread, APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, apr_threadattr_t *attr, apr_pool_t *pool); + +/** + * Clear the current thread after fork() + */ +APR_DECLARE(void) apr_thread_current_after_fork(void); + /** * Get the current thread * @param The current apr_thread, NULL if it is not an apr_thread or if diff --git a/threadproc/beos/proc.c b/threadproc/beos/proc.c index e3698082f..cd6f9a250 100644 --- a/threadproc/beos/proc.c +++ b/threadproc/beos/proc.c @@ -170,6 +170,9 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) } } +#if AP_HAS_THREAD_LOCAL + apr_thread_current_after_fork(); +#endif proc->pid = pid; proc->in = NULL; proc->out = NULL; diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 25bd0d2bb..435c2c8a9 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -184,6 +184,13 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, 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 diff --git a/threadproc/netware/proc.c b/threadproc/netware/proc.c index f5d24b21b..1a6de7b7b 100644 --- a/threadproc/netware/proc.c +++ b/threadproc/netware/proc.c @@ -226,6 +226,9 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) return errno; } else if (pid == 0) { +#if AP_HAS_THREAD_LOCAL + apr_thread_current_after_fork(); +#endif proc->pid = pid; proc->in = NULL; proc->out = NULL; diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index 40b6d7259..b45569e3f 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -219,6 +219,13 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, 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 diff --git a/threadproc/os2/proc.c b/threadproc/os2/proc.c index cd7500129..beb100908 100644 --- a/threadproc/os2/proc.c +++ b/threadproc/os2/proc.c @@ -227,6 +227,9 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) return errno; } else if (pid == 0) { +#if AP_HAS_THREAD_LOCAL + apr_thread_current_after_fork(); +#endif proc->pid = pid; proc->in = NULL; proc->out = NULL; diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index d23be9aed..fc3015088 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -187,6 +187,13 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, 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 diff --git a/threadproc/unix/proc.c b/threadproc/unix/proc.c index ed7a05fda..ad31c814f 100644 --- a/threadproc/unix/proc.c +++ b/threadproc/unix/proc.c @@ -234,6 +234,9 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) return errno; } else if (pid == 0) { +#if AP_HAS_THREAD_LOCAL + apr_thread_current_after_fork(); +#endif proc->pid = getpid(); /* Do the work needed for children PRNG(s). */ diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index d3eac6509..78b803727 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -260,6 +260,13 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, 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 diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index c4fd81fff..68251f881 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -199,6 +199,13 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, 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 -- cgit v1.2.1 From 8a39364cd53e4e8cbf6f06eced62726c0b8c1b84 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Wed, 26 Jan 2022 21:16:08 +0000 Subject: poll: Implement APR_POLLSET_NOCOPY for kqueue. Like with epoll, it allows to be lockless if the lifetime of the pollfd(s) is garanteed by the user. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897518 13f79535-47bb-0310-9956-ffa450edef68 --- poll/unix/epoll.c | 2 +- poll/unix/kqueue.c | 127 +++++++++++++++---------- poll/unix/port.c | 273 ++++++++++++++++++++++++++++++----------------------- 3 files changed, 234 insertions(+), 168 deletions(-) diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index c00a1094d..89c41a404 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -123,7 +123,7 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, } #endif - pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if ((flags & APR_POLLSET_THREADSAFE) && !(flags & APR_POLLSET_NOCOPY) && diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c index e8a1ef95b..aa4251f1b 100644 --- a/poll/unix/kqueue.c +++ b/poll/unix/kqueue.c @@ -75,9 +75,12 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t flags) { apr_status_t rv; - pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + + pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); + #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && + !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { @@ -99,14 +102,9 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, * for the same descriptor) */ pollset->p->setsize = 2 * size; - - pollset->p->ke_set = - (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent)); - - memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent)); + pollset->p->ke_set = apr_pcalloc(p, pollset->p->setsize * sizeof(struct kevent)); pollset->p->kqueue_fd = kqueue(); - if (pollset->p->kqueue_fd == -1) { pollset->p = NULL; return apr_get_netos_error(); @@ -133,9 +131,11 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t)); - APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + if (!(flags & APR_POLLSET_NOCOPY)) { + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + } return APR_SUCCESS; } @@ -144,20 +144,22 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { apr_os_sock_t fd; - pfd_elem_t *elem; + pfd_elem_t *elem = NULL; apr_status_t rv = APR_SUCCESS; - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); - if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->p->free_ring)); - APR_RING_REMOVE(elem, link); - } - else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; } - elem->pfd = *descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; @@ -167,7 +169,14 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLIN) { - EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); + if (pollset->flags & APR_POLLSET_NOCOPY) { + EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, + descriptor); + } + else { + EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, + elem); + } if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -176,7 +185,14 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { - EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); + if (pollset->flags & APR_POLLSET_NOCOPY) { + EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, + descriptor); + } + else { + EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, + elem); + } if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -184,14 +200,16 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } } - if (rv == APR_SUCCESS) { - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); - } - else { - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); - } + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + if (rv == APR_SUCCESS) { + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); + } + else { + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); + } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -199,12 +217,9 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { - pfd_elem_t *ep; apr_status_t rv; apr_os_sock_t fd; - pollset_lock_rings(); - if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } @@ -231,20 +246,26 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, } } - for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pfd_elem_t *ep; + + pollset_lock_rings(); - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), - ep, pfd_elem_t, link); - break; + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + break; + } } - } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -282,7 +303,13 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, const apr_pollfd_t *fd; for (i = 0, j = 0; i < ret; i++) { - fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; + if (pollset->flags & APR_POLLSET_NOCOPY) { + fd = (apr_pollfd_t *)pollset->p->ke_set[i].udata; + } + else { + fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; + } + if ((pollset->flags & APR_POLLSET_WAKEABLE) && fd->desc_type == APR_POLL_FILE && fd->desc.f == pollset->wakeup_pipe[0]) { @@ -305,13 +332,15 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); - /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), - pfd_elem_t, link); + /* Shift all PFDs in the Dead Ring to the Free Ring */ + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), + pfd_elem_t, link); - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } diff --git a/poll/unix/port.c b/poll/unix/port.c index 638a8cba7..f5c7a01c4 100644 --- a/poll/unix/port.c +++ b/poll/unix/port.c @@ -159,7 +159,7 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t flags) { apr_status_t rv = APR_SUCCESS; - pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, @@ -206,10 +206,12 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + } return rv; } @@ -222,19 +224,6 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, int res; apr_status_t rv = APR_SUCCESS; - pollset_lock_rings(); - - if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->p->free_ring)); - APR_RING_REMOVE(elem, link); - } - else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); - elem->on_query_ring = 0; - } - elem->pfd = *descriptor; - if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } @@ -242,27 +231,52 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - /* If another thread is polling, notify the kernel immediately; otherwise, - * wait until the next call to apr_pollset_poll(). - */ - if (apr_atomic_read32(&pollset->p->waiting)) { + if (pollset->flags & APR_POLLSET_NOCOPY) { res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, - get_event(descriptor->reqevents), (void *)elem); + get_event(descriptor->reqevents), (void *)descriptor); if (res < 0) { rv = apr_get_netos_error(); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); + } + } + else { + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->free_ring)); + APR_RING_REMOVE(elem, link); } else { - elem->on_query_ring = 1; - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + elem->on_query_ring = 0; + } + elem->pfd = *descriptor; + + /* If another thread is polling, notify the kernel immediately; otherwise, + * wait until the next call to apr_pollset_poll(). + */ + if (apr_atomic_read32(&pollset->p->waiting)) { + res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, + get_event(descriptor->reqevents), (void *)elem); + + if (res < 0) { + rv = apr_get_netos_error(); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, + pfd_elem_t, link); + } + else { + elem->on_query_ring = 1; + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, + pfd_elem_t, link); + } + } + else { + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); } - } - else { - APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); - } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -275,9 +289,7 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, apr_status_t rv = APR_SUCCESS; int res; int err = 0; - int found; - - pollset_lock_rings(); + int found = 0; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; @@ -286,34 +298,36 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - /* Search the add ring first. This ring is often shorter, - * and it often contains the descriptor being removed. - * (For the common scenario where apr_pollset_poll() - * returns activity for the descriptor and the descriptor - * is then removed from the pollset, it will have just - * been moved to the add ring by apr_pollset_poll().) - * - * If it is on the add ring, it isn't associated with the - * event port yet/anymore. - */ - found = 0; - for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->add_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - found = 1; - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), - ep, pfd_elem_t, link); - break; + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); + + /* Search the add ring first. This ring is often shorter, + * and it often contains the descriptor being removed. + * (For the common scenario where apr_pollset_poll() + * returns activity for the descriptor and the descriptor + * is then removed from the pollset, it will have just + * been moved to the add ring by apr_pollset_poll().) + * + * If it is on the add ring, it isn't associated with the + * event port yet/anymore. + */ + for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->add_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + found = 1; + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), + ep, pfd_elem_t, link); + break; + } } } if (!found) { res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd); - if (res < 0) { /* The expected case for this failure is that another * thread's call to port_getn() returned this fd and @@ -325,25 +339,29 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, rv = APR_NOTFOUND; } - for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - ep->on_query_ring = 0; - APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), - ep, pfd_elem_t, link); - if (ENOENT == err) { - rv = APR_SUCCESS; + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + if (ENOENT == err) { + rv = APR_SUCCESS; + } + break; } - break; } + pollset_unlock_rings(); } } - - pollset_unlock_rings(); + else if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_unlock_rings(); + } return rv; } @@ -363,73 +381,89 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, *num = 0; nget = 1; - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); - apr_atomic_inc32(&pollset->p->waiting); + apr_atomic_inc32(&pollset->p->waiting); - while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { - ep = APR_RING_FIRST(&(pollset->p->add_ring)); - APR_RING_REMOVE(ep, link); + while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { + ep = APR_RING_FIRST(&(pollset->p->add_ring)); + APR_RING_REMOVE(ep, link); - if (ep->pfd.desc_type == APR_POLL_SOCKET) { - fd = ep->pfd.desc.s->socketdes; - } - else { - fd = ep->pfd.desc.f->filedes; - } + if (ep->pfd.desc_type == APR_POLL_SOCKET) { + fd = ep->pfd.desc.s->socketdes; + } + else { + fd = ep->pfd.desc.f->filedes; + } - ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, - fd, get_event(ep->pfd.reqevents), ep); - if (ret < 0) { - rv = apr_get_netos_error(); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); - break; - } + ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, + fd, get_event(ep->pfd.reqevents), ep); + if (ret < 0) { + rv = apr_get_netos_error(); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); + break; + } - ep->on_query_ring = 1; - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); - } + ep->on_query_ring = 1; + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); + } - pollset_unlock_rings(); + pollset_unlock_rings(); - if (rv != APR_SUCCESS) { - apr_atomic_dec32(&pollset->p->waiting); - return rv; + if (rv != APR_SUCCESS) { + apr_atomic_dec32(&pollset->p->waiting); + return rv; + } } rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, pollset->nalloc, &nget, timeout); - /* decrease the waiting ASAP to reduce the window for calling - port_associate within apr_pollset_add() */ - apr_atomic_dec32(&pollset->p->waiting); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + /* decrease the waiting ASAP to reduce the window for calling + port_associate within apr_pollset_add() */ + apr_atomic_dec32(&pollset->p->waiting); - pollset_lock_rings(); + pollset_lock_rings(); + } for (i = 0, j = 0; i < nget; i++) { - ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; + const apr_poll_fd_t *pfd; + + if (pollset->flags & APR_POLLSET_NOCOPY) { + pfd = (apr_pollfd_t *)pollset->p->port_set[i].portev_user; + } + else { + ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; + pfd = &ep->pfd; + } + if ((pollset->flags & APR_POLLSET_WAKEABLE) && - ep->pfd.desc_type == APR_POLL_FILE && - ep->pfd.desc.f == pollset->wakeup_pipe[0]) { + pfd->desc_type == APR_POLL_FILE && + pfd->desc.f == pollset->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(&pollset->wakeup_set, pollset->wakeup_pipe); rv = APR_EINTR; } else { - pollset->p->result_set[j] = ep->pfd; + pollset->p->result_set[j] = *pfd; pollset->p->result_set[j].rtnevents = get_revent(pollset->p->port_set[i].portev_events); j++; } - /* If the ring element is still on the query ring, move it - * to the add ring for re-association with the event port - * later. (It may have already been moved to the dead ring - * by a call to pollset_remove on another thread.) - */ - if (ep->on_query_ring) { - APR_RING_REMOVE(ep, link); - ep->on_query_ring = 0; - APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, - pfd_elem_t, link); + + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + /* If the ring element is still on the query ring, move it + * to the add ring for re-association with the event port + * later. (It may have already been moved to the dead ring + * by a call to pollset_remove on another thread.) + */ + if (ep->on_query_ring) { + APR_RING_REMOVE(ep, link); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, + pfd_elem_t, link); + } } } if ((*num = j)) { /* any event besides wakeup pipe? */ @@ -439,10 +473,13 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + /* Shift all PFDs in the Dead Ring to the Free Ring */ + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), + pfd_elem_t, link); - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } -- cgit v1.2.1 From cda93a2e16d4272edc2d9967fb6e8339ec1d7749 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Wed, 26 Jan 2022 21:17:36 +0000 Subject: Revert r1897518 (spurious changes). git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897519 13f79535-47bb-0310-9956-ffa450edef68 --- poll/unix/epoll.c | 2 +- poll/unix/kqueue.c | 127 ++++++++++--------------- poll/unix/port.c | 273 +++++++++++++++++++++++------------------------------ 3 files changed, 168 insertions(+), 234 deletions(-) diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index 89c41a404..c00a1094d 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -123,7 +123,7 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, } #endif - pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); + pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if ((flags & APR_POLLSET_THREADSAFE) && !(flags & APR_POLLSET_NOCOPY) && diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c index aa4251f1b..e8a1ef95b 100644 --- a/poll/unix/kqueue.c +++ b/poll/unix/kqueue.c @@ -75,12 +75,9 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t flags) { apr_status_t rv; - - pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); - + pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && - !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { @@ -102,9 +99,14 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, * for the same descriptor) */ pollset->p->setsize = 2 * size; - pollset->p->ke_set = apr_pcalloc(p, pollset->p->setsize * sizeof(struct kevent)); + + pollset->p->ke_set = + (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent)); + + memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent)); pollset->p->kqueue_fd = kqueue(); + if (pollset->p->kqueue_fd == -1) { pollset->p = NULL; return apr_get_netos_error(); @@ -131,11 +133,9 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t)); - if (!(flags & APR_POLLSET_NOCOPY)) { - APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); - } + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); return APR_SUCCESS; } @@ -144,22 +144,20 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { apr_os_sock_t fd; - pfd_elem_t *elem = NULL; + pfd_elem_t *elem; apr_status_t rv = APR_SUCCESS; - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pollset_lock_rings(); + pollset_lock_rings(); - if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->p->free_ring)); - APR_RING_REMOVE(elem, link); - } - else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); - } - elem->pfd = *descriptor; + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->free_ring)); + APR_RING_REMOVE(elem, link); } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; @@ -169,14 +167,7 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLIN) { - if (pollset->flags & APR_POLLSET_NOCOPY) { - EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, - descriptor); - } - else { - EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, - elem); - } + EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -185,14 +176,7 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { - if (pollset->flags & APR_POLLSET_NOCOPY) { - EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, - descriptor); - } - else { - EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, - elem); - } + EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -200,26 +184,27 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - if (rv == APR_SUCCESS) { - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); - } - else { - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); - } - - pollset_unlock_rings(); + if (rv == APR_SUCCESS) { + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); + } + else { + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); } + pollset_unlock_rings(); + return rv; } static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { + pfd_elem_t *ep; apr_status_t rv; apr_os_sock_t fd; + pollset_lock_rings(); + if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } @@ -246,27 +231,21 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, } } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pfd_elem_t *ep; - - pollset_lock_rings(); + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { - for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), - ep, pfd_elem_t, link); - break; - } + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + break; } - - pollset_unlock_rings(); } + pollset_unlock_rings(); + return rv; } @@ -303,13 +282,7 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, const apr_pollfd_t *fd; for (i = 0, j = 0; i < ret; i++) { - if (pollset->flags & APR_POLLSET_NOCOPY) { - fd = (apr_pollfd_t *)pollset->p->ke_set[i].udata; - } - else { - fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; - } - + fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; if ((pollset->flags & APR_POLLSET_WAKEABLE) && fd->desc_type == APR_POLL_FILE && fd->desc.f == pollset->wakeup_pipe[0]) { @@ -332,15 +305,13 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pollset_lock_rings(); + pollset_lock_rings(); - /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), - pfd_elem_t, link); + /* Shift all PFDs in the Dead Ring to the Free Ring */ + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), + pfd_elem_t, link); - pollset_unlock_rings(); - } + pollset_unlock_rings(); return rv; } diff --git a/poll/unix/port.c b/poll/unix/port.c index f5c7a01c4..638a8cba7 100644 --- a/poll/unix/port.c +++ b/poll/unix/port.c @@ -159,7 +159,7 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t flags) { apr_status_t rv = APR_SUCCESS; - pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); + pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, @@ -206,12 +206,10 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); - } + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); return rv; } @@ -224,6 +222,19 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, int res; apr_status_t rv = APR_SUCCESS; + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + elem->on_query_ring = 0; + } + elem->pfd = *descriptor; + if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } @@ -231,53 +242,28 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - if (pollset->flags & APR_POLLSET_NOCOPY) { + /* If another thread is polling, notify the kernel immediately; otherwise, + * wait until the next call to apr_pollset_poll(). + */ + if (apr_atomic_read32(&pollset->p->waiting)) { res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, - get_event(descriptor->reqevents), (void *)descriptor); + get_event(descriptor->reqevents), (void *)elem); if (res < 0) { rv = apr_get_netos_error(); - } - } - else { - pollset_lock_rings(); - - if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->p->free_ring)); - APR_RING_REMOVE(elem, link); - } - else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); - elem->on_query_ring = 0; - } - elem->pfd = *descriptor; - - /* If another thread is polling, notify the kernel immediately; otherwise, - * wait until the next call to apr_pollset_poll(). - */ - if (apr_atomic_read32(&pollset->p->waiting)) { - res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, - get_event(descriptor->reqevents), (void *)elem); - - if (res < 0) { - rv = apr_get_netos_error(); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, - pfd_elem_t, link); - } - else { - elem->on_query_ring = 1; - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, - pfd_elem_t, link); - } + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); } else { - APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); + elem->on_query_ring = 1; + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); } - - pollset_unlock_rings(); + } + else { + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); } + pollset_unlock_rings(); + return rv; } @@ -289,7 +275,9 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, apr_status_t rv = APR_SUCCESS; int res; int err = 0; - int found = 0; + int found; + + pollset_lock_rings(); if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; @@ -298,36 +286,34 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pollset_lock_rings(); - - /* Search the add ring first. This ring is often shorter, - * and it often contains the descriptor being removed. - * (For the common scenario where apr_pollset_poll() - * returns activity for the descriptor and the descriptor - * is then removed from the pollset, it will have just - * been moved to the add ring by apr_pollset_poll().) - * - * If it is on the add ring, it isn't associated with the - * event port yet/anymore. - */ - for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->add_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - found = 1; - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), - ep, pfd_elem_t, link); - break; - } + /* Search the add ring first. This ring is often shorter, + * and it often contains the descriptor being removed. + * (For the common scenario where apr_pollset_poll() + * returns activity for the descriptor and the descriptor + * is then removed from the pollset, it will have just + * been moved to the add ring by apr_pollset_poll().) + * + * If it is on the add ring, it isn't associated with the + * event port yet/anymore. + */ + found = 0; + for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->add_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + found = 1; + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), + ep, pfd_elem_t, link); + break; } } if (!found) { res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd); + if (res < 0) { /* The expected case for this failure is that another * thread's call to port_getn() returned this fd and @@ -339,29 +325,25 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, rv = APR_NOTFOUND; } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - ep->on_query_ring = 0; - APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), - ep, pfd_elem_t, link); - if (ENOENT == err) { - rv = APR_SUCCESS; - } - break; + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + if (ENOENT == err) { + rv = APR_SUCCESS; } + break; } - pollset_unlock_rings(); } } - else if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pollset_unlock_rings(); - } + + pollset_unlock_rings(); return rv; } @@ -381,89 +363,73 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, *num = 0; nget = 1; - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - pollset_lock_rings(); + pollset_lock_rings(); - apr_atomic_inc32(&pollset->p->waiting); + apr_atomic_inc32(&pollset->p->waiting); - while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { - ep = APR_RING_FIRST(&(pollset->p->add_ring)); - APR_RING_REMOVE(ep, link); - - if (ep->pfd.desc_type == APR_POLL_SOCKET) { - fd = ep->pfd.desc.s->socketdes; - } - else { - fd = ep->pfd.desc.f->filedes; - } + while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { + ep = APR_RING_FIRST(&(pollset->p->add_ring)); + APR_RING_REMOVE(ep, link); - ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, - fd, get_event(ep->pfd.reqevents), ep); - if (ret < 0) { - rv = apr_get_netos_error(); - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); - break; - } + if (ep->pfd.desc_type == APR_POLL_SOCKET) { + fd = ep->pfd.desc.s->socketdes; + } + else { + fd = ep->pfd.desc.f->filedes; + } - ep->on_query_ring = 1; - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); + ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, + fd, get_event(ep->pfd.reqevents), ep); + if (ret < 0) { + rv = apr_get_netos_error(); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); + break; } - pollset_unlock_rings(); + ep->on_query_ring = 1; + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); + } - if (rv != APR_SUCCESS) { - apr_atomic_dec32(&pollset->p->waiting); - return rv; - } + pollset_unlock_rings(); + + if (rv != APR_SUCCESS) { + apr_atomic_dec32(&pollset->p->waiting); + return rv; } rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, pollset->nalloc, &nget, timeout); - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - /* decrease the waiting ASAP to reduce the window for calling - port_associate within apr_pollset_add() */ - apr_atomic_dec32(&pollset->p->waiting); + /* decrease the waiting ASAP to reduce the window for calling + port_associate within apr_pollset_add() */ + apr_atomic_dec32(&pollset->p->waiting); - pollset_lock_rings(); - } + pollset_lock_rings(); for (i = 0, j = 0; i < nget; i++) { - const apr_poll_fd_t *pfd; - - if (pollset->flags & APR_POLLSET_NOCOPY) { - pfd = (apr_pollfd_t *)pollset->p->port_set[i].portev_user; - } - else { - ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; - pfd = &ep->pfd; - } - + ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; if ((pollset->flags & APR_POLLSET_WAKEABLE) && - pfd->desc_type == APR_POLL_FILE && - pfd->desc.f == pollset->wakeup_pipe[0]) { + ep->pfd.desc_type == APR_POLL_FILE && + ep->pfd.desc.f == pollset->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(&pollset->wakeup_set, pollset->wakeup_pipe); rv = APR_EINTR; } else { - pollset->p->result_set[j] = *pfd; + pollset->p->result_set[j] = ep->pfd; pollset->p->result_set[j].rtnevents = get_revent(pollset->p->port_set[i].portev_events); j++; } - - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - /* If the ring element is still on the query ring, move it - * to the add ring for re-association with the event port - * later. (It may have already been moved to the dead ring - * by a call to pollset_remove on another thread.) - */ - if (ep->on_query_ring) { - APR_RING_REMOVE(ep, link); - ep->on_query_ring = 0; - APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, - pfd_elem_t, link); - } + /* If the ring element is still on the query ring, move it + * to the add ring for re-association with the event port + * later. (It may have already been moved to the dead ring + * by a call to pollset_remove on another thread.) + */ + if (ep->on_query_ring) { + APR_RING_REMOVE(ep, link); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, + pfd_elem_t, link); } } if ((*num = j)) { /* any event besides wakeup pipe? */ @@ -473,13 +439,10 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - if (!(pollset->flags & APR_POLLSET_NOCOPY)) { - /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), - pfd_elem_t, link); + /* Shift all PFDs in the Dead Ring to the Free Ring */ + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); - pollset_unlock_rings(); - } + pollset_unlock_rings(); return rv; } -- cgit v1.2.1 From 9155323a563d055a226a4e6cfc1f2fb9f8d2abf0 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Wed, 26 Jan 2022 21:20:18 +0000 Subject: poll: Implement APR_POLLSET_NOCOPY for kqueue. Like with epoll, it allows to be lockless if the lifetime of the pollfd(s) is garanteed by the user. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897520 13f79535-47bb-0310-9956-ffa450edef68 --- poll/unix/epoll.c | 2 +- poll/unix/kqueue.c | 127 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 79 insertions(+), 50 deletions(-) diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index c00a1094d..89c41a404 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -123,7 +123,7 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, } #endif - pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if ((flags & APR_POLLSET_THREADSAFE) && !(flags & APR_POLLSET_NOCOPY) && diff --git a/poll/unix/kqueue.c b/poll/unix/kqueue.c index e8a1ef95b..aa4251f1b 100644 --- a/poll/unix/kqueue.c +++ b/poll/unix/kqueue.c @@ -75,9 +75,12 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t flags) { apr_status_t rv; - pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + + pollset->p = apr_pcalloc(p, sizeof(apr_pollset_private_t)); + #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && + !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { @@ -99,14 +102,9 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, * for the same descriptor) */ pollset->p->setsize = 2 * size; - - pollset->p->ke_set = - (struct kevent *) apr_palloc(p, pollset->p->setsize * sizeof(struct kevent)); - - memset(pollset->p->ke_set, 0, pollset->p->setsize * sizeof(struct kevent)); + pollset->p->ke_set = apr_pcalloc(p, pollset->p->setsize * sizeof(struct kevent)); pollset->p->kqueue_fd = kqueue(); - if (pollset->p->kqueue_fd == -1) { pollset->p = NULL; return apr_get_netos_error(); @@ -133,9 +131,11 @@ static apr_status_t impl_pollset_create(apr_pollset_t *pollset, pollset->p->result_set = apr_palloc(p, pollset->p->setsize * sizeof(apr_pollfd_t)); - APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); - APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + if (!(flags & APR_POLLSET_NOCOPY)) { + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); + } return APR_SUCCESS; } @@ -144,20 +144,22 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { apr_os_sock_t fd; - pfd_elem_t *elem; + pfd_elem_t *elem = NULL; apr_status_t rv = APR_SUCCESS; - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); - if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->p->free_ring)); - APR_RING_REMOVE(elem, link); - } - else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; } - elem->pfd = *descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; @@ -167,7 +169,14 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLIN) { - EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); + if (pollset->flags & APR_POLLSET_NOCOPY) { + EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, + descriptor); + } + else { + EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, + elem); + } if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -176,7 +185,14 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { - EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); + if (pollset->flags & APR_POLLSET_NOCOPY) { + EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, + descriptor); + } + else { + EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, + elem); + } if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { @@ -184,14 +200,16 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, } } - if (rv == APR_SUCCESS) { - APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); - } - else { - APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); - } + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + if (rv == APR_SUCCESS) { + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); + } + else { + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); + } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -199,12 +217,9 @@ static apr_status_t impl_pollset_add(apr_pollset_t *pollset, static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { - pfd_elem_t *ep; apr_status_t rv; apr_os_sock_t fd; - pollset_lock_rings(); - if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } @@ -231,20 +246,26 @@ static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, } } - for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->p->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pfd_elem_t *ep; + + pollset_lock_rings(); - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), - ep, pfd_elem_t, link); - break; + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + break; + } } - } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -282,7 +303,13 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, const apr_pollfd_t *fd; for (i = 0, j = 0; i < ret; i++) { - fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; + if (pollset->flags & APR_POLLSET_NOCOPY) { + fd = (apr_pollfd_t *)pollset->p->ke_set[i].udata; + } + else { + fd = &((pfd_elem_t *)pollset->p->ke_set[i].udata)->pfd; + } + if ((pollset->flags & APR_POLLSET_WAKEABLE) && fd->desc_type == APR_POLL_FILE && fd->desc.f == pollset->wakeup_pipe[0]) { @@ -305,13 +332,15 @@ static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, } } - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); - /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), - pfd_elem_t, link); + /* Shift all PFDs in the Dead Ring to the Free Ring */ + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), + pfd_elem_t, link); - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } -- cgit v1.2.1 From df4d82325af245e6d56cfd82b6b3587dd9ca8ae9 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Wed, 26 Jan 2022 22:53:33 +0000 Subject: poll: Provide APR_POLLEXCL for exclusive wake up on systems that support it. epoll has EPOLLEXCLUSIVE, start with that. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897521 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_poll.h | 1 + poll/unix/epoll.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/include/apr_poll.h b/include/apr_poll.h index 482d6ee1d..a79a6046d 100644 --- a/include/apr_poll.h +++ b/include/apr_poll.h @@ -52,6 +52,7 @@ extern "C" { #define APR_POLLERR 0x010 /**< Pending error */ #define APR_POLLHUP 0x020 /**< Hangup occurred */ #define APR_POLLNVAL 0x040 /**< Descriptor invalid */ +#define APR_POLLEXCL 0x080 /**< Exclusive */ /** @} */ /** diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index 89c41a404..340f43db8 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -35,6 +35,10 @@ static apr_int16_t get_epoll_event(apr_int16_t event) rv |= EPOLLPRI; if (event & APR_POLLOUT) rv |= EPOLLOUT; +#ifdef EPOLLEXCLUSIVE + if (event & APR_POLLEXCL) + rv |= EPOLLEXCLUSIVE; +#endif /* APR_POLLNVAL is not handled by epoll. EPOLLERR and EPOLLHUP are return-only */ return rv; -- cgit v1.2.1 From ed69b77ae5419f23034d0b95fb37ab992da601fd Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Thu, 27 Jan 2022 13:50:16 +0000 Subject: poll: Follow up to r1897521: struct epoll_event's events field is unsigned int. EPOLLEXCLUSIVE is 1u << 28 so it doesn't fit in an int16_t, use unsigned for the native epoll events type. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897548 13f79535-47bb-0310-9956-ffa450edef68 --- poll/unix/epoll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poll/unix/epoll.c b/poll/unix/epoll.c index 340f43db8..7e811241d 100644 --- a/poll/unix/epoll.c +++ b/poll/unix/epoll.c @@ -25,9 +25,9 @@ #if defined(HAVE_EPOLL) -static apr_int16_t get_epoll_event(apr_int16_t event) +static unsigned get_epoll_event(apr_int16_t event) { - apr_int16_t rv = 0; + unsigned rv = 0; if (event & APR_POLLIN) rv |= EPOLLIN; @@ -44,7 +44,7 @@ static apr_int16_t get_epoll_event(apr_int16_t event) return rv; } -static apr_int16_t get_epoll_revent(apr_int16_t event) +static apr_int16_t get_epoll_revent(unsigned event) { apr_int16_t rv = 0; -- cgit v1.2.1 From 196c241c5980dba46bfc309cc4d92f7b3f543133 Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Thu, 27 Jan 2022 14:20:36 +0000 Subject: poll: Follow up to r1897521: Clarify what APR_POLLEXCL means. This is to avoid the thundering herd issue when multiple threads/processes poll on the same descriptor (usually listening/to-be-accept()ed descriptors). git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897549 13f79535-47bb-0310-9956-ffa450edef68 --- include/apr_poll.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/apr_poll.h b/include/apr_poll.h index a79a6046d..3cfbfc810 100644 --- a/include/apr_poll.h +++ b/include/apr_poll.h @@ -52,7 +52,7 @@ extern "C" { #define APR_POLLERR 0x010 /**< Pending error */ #define APR_POLLHUP 0x020 /**< Hangup occurred */ #define APR_POLLNVAL 0x040 /**< Descriptor invalid */ -#define APR_POLLEXCL 0x080 /**< Exclusive */ +#define APR_POLLEXCL 0x080 /**< Exclusive wake up */ /** @} */ /** -- cgit v1.2.1 From 832ec99195140a3356df7577f3d875253335068a Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Tue, 1 Feb 2022 08:45:39 +0000 Subject: * test/testbuckets.c (flatten_match): Avoid GCC 12 -Wformat-overflow warnings with sprintf. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897646 13f79535-47bb-0310-9956-ffa450edef68 --- test/testbuckets.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/testbuckets.c b/test/testbuckets.c index 2b789f1a0..3957f0e2d 100644 --- a/test/testbuckets.c +++ b/test/testbuckets.c @@ -100,12 +100,12 @@ static void flatten_match(abts_case *tc, const char *ctx, apr_size_t len = elen; char msg[200]; - sprintf(msg, "%s: flatten brigade", ctx); + apr_snprintf(msg, sizeof msg, "%s: flatten brigade", ctx); APR_ASSERT_SUCCESS(tc, msg, apr_brigade_flatten(bb, buf, &len)); - sprintf(msg, "%s: length match (%ld not %ld)", ctx, - (long)len, (long)elen); + apr_snprintf(msg, sizeof msg, "%s: length match (%ld not %ld)", ctx, + (long)len, (long)elen); ABTS_ASSERT(tc, msg, len == elen); - sprintf(msg, "%s: result match", ctx); + apr_snprintf(msg, sizeof msg, "%s: result match", ctx); ABTS_STR_NEQUAL(tc, expect, buf, len); free(buf); } -- cgit v1.2.1 From 89682a8e2e5eb498b6c4e4ff162052c7e2406a0b Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 8 Feb 2022 19:26:16 +0000 Subject: apr_thread: Follow up to r1897207: apr_thread_current_create() compilation. Fix compilation of apr_thread_current_create() for OS/2 and Windows. Set *current to NULL on failure. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1897879 13f79535-47bb-0310-9956-ffa450edef68 --- threadproc/beos/thread.c | 1 + threadproc/netware/thread.c | 1 + threadproc/os2/thread.c | 3 ++- threadproc/unix/thread.c | 1 + threadproc/win32/thread.c | 3 ++- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 435c2c8a9..f5752a81e 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -173,6 +173,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, stat = alloc_thread(current, attr, NULL, NULL, pool); if (stat != APR_SUCCESS) { + *current = NULL; return stat; } diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index b45569e3f..24122119a 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -208,6 +208,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, stat = alloc_thread(current, attr, NULL, NULL, pool); if (stat != APR_SUCCESS) { + *current = NULL; return stat; } diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index fc3015088..e0540188d 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -174,8 +174,9 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, return APR_EEXIST; } - stat = alloc_thread(new, attr, NULL, NULL, pool); + stat = alloc_thread(current, attr, NULL, NULL, pool); if (stat != APR_SUCCESS) { + *current = NULL; return stat; } diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index 78b803727..209fe7c86 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -249,6 +249,7 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, stat = alloc_thread(current, attr, NULL, NULL, pool); if (stat != APR_SUCCESS) { + *current = NULL; return stat; } diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 68251f881..7e1c1a8be 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -186,11 +186,12 @@ APR_DECLARE(apr_status_t) apr_thread_current_create(apr_thread_t **current, stat = alloc_thread(current, attr, NULL, NULL, pool); if (stat != APR_SUCCESS) { + *current = NULL; return stat; } if (!(attr && attr->detach)) { - (*new)->td = apr_os_thread_current(); + (*current)->td = apr_os_thread_current(); } #if APR_HAS_THREAD_LOCAL -- cgit v1.2.1