diff options
-rw-r--r-- | build/apr_threads.m4 | 24 | ||||
-rw-r--r-- | configure.in | 1 | ||||
-rw-r--r-- | include/apr_thread_proc.h | 23 | ||||
-rw-r--r-- | include/arch/win32/apr_arch_misc.h | 10 | ||||
-rw-r--r-- | test/testthread.c | 31 | ||||
-rw-r--r-- | threadproc/beos/thread.c | 14 | ||||
-rw-r--r-- | threadproc/netware/thread.c | 12 | ||||
-rw-r--r-- | threadproc/os2/thread.c | 14 | ||||
-rw-r--r-- | threadproc/unix/thread.c | 55 | ||||
-rw-r--r-- | threadproc/win32/thread.c | 72 |
10 files changed, 256 insertions, 0 deletions
diff --git a/build/apr_threads.m4 b/build/apr_threads.m4 index 6895c3a67..98e17de1b 100644 --- a/build/apr_threads.m4 +++ b/build/apr_threads.m4 @@ -312,3 +312,27 @@ elif test "$apr_cv_mutex_robust_shared" = "np"; then [Define if non-posix/portable cross-process robust mutexes are available]) fi ]) + + +dnl Check for pthread_setname_np +dnl Note: Only detects two-arg version +AC_DEFUN([APR_CHECK_PTHREAD_SETNAME_NP], [ +AC_CACHE_CHECK([for pthread_setname_np support], +[apr_cv_pthread_setname_np], [ +AC_TRY_COMPILE([ +#include <pthread.h> +],[ +pthread_t td = pthread_self(); +pthread_setname_np(td, "name"); +],[ + apr_cv_pthread_setname_np=yes +],[ + apr_cv_pthread_setname_np=no +])]) + +if test "$apr_cv_pthread_setname_np" = "yes"; then + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], 1, + [Define if pthread_setname_np is available]) +fi +])dnl + diff --git a/configure.in b/configure.in index 2d8ddd493..7ad0f5700 100644 --- a/configure.in +++ b/configure.in @@ -947,6 +947,7 @@ else APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG APR_CHECK_PTHREAD_RECURSIVE_MUTEX + APR_CHECK_PTHREAD_SETNAME_NP AC_CHECK_FUNCS([pthread_key_delete pthread_rwlock_init \ pthread_attr_setguardsize pthread_yield]) diff --git a/include/apr_thread_proc.h b/include/apr_thread_proc.h index b9a7dd1fc..d9fe12a28 100644 --- a/include/apr_thread_proc.h +++ b/include/apr_thread_proc.h @@ -340,6 +340,29 @@ APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd); /** + * Get name of thread + * @param name The variable where is will be stored name of thread. + * @param thread The thread that name required to get. + * Current thread will be used if @param thread is NULL. + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_thread_name_get(char **name, + apr_thread_t *thread, + apr_pool_t *pool); + +/** + * Set name of thread + * @param name The name of thread must be setted. If name is to long, then + * name stripped to max length supported by operation system. + * @param thread The thread that name will be changed. + * Current thread will be used if @param thread is NULL. + * @param cont The pool to use for temporary allocations + */ +APR_DECLARE(apr_status_t) apr_thread_name_set(const char *name, + apr_thread_t *thread, + apr_pool_t *pool); + +/** * force the current thread to yield the processor */ APR_DECLARE(void) apr_thread_yield(void); diff --git a/include/arch/win32/apr_arch_misc.h b/include/arch/win32/apr_arch_misc.h index eb8ec0838..4d8ec6162 100644 --- a/include/arch/win32/apr_arch_misc.h +++ b/include/arch/win32/apr_arch_misc.h @@ -293,4 +293,14 @@ APR_DECLARE_LATE_DLL_FUNC(DLL_API_MS_WIN_DOWNLEVEL_SHELL32_L1_1_0, LPWSTR *, (LPCWSTR lpCmdLine, int *pNumArgs), (lpCmdLine, pNumArgs)); +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, GetThreadDescription, 0, ( + HANDLE hThread, + PWSTR *ppszThreadDescription), + (hThread, ppszThreadDescription)); + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, SetThreadDescription, 0, ( + HANDLE hThread, + PCWSTR lpThreadDescription), + (hThread, lpThreadDescription)); + #endif /* ! MISC_H */ diff --git a/test/testthread.c b/test/testthread.c index 6eb8ebc6d..72f3ddd0a 100644 --- a/test/testthread.c +++ b/test/testthread.c @@ -107,6 +107,36 @@ static void check_thread_once(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, 1, value); } +static void thread_name(abts_case *tc, void *data) +{ + apr_status_t rv; + char *name; + + rv = apr_thread_name_set("thread-1", NULL, p); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_thread_name_set is not implemented.") + return ; + } + + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_thread_name_get(&name, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "thread-1", name); + + rv = apr_thread_name_set("thread-1", NULL, p); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_thread_name_set is not implemented.") + return ; + } + + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_thread_name_get(&name, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "thread-1", name); +} + #else static void threads_not_impl(abts_case *tc, void *data) @@ -128,6 +158,7 @@ abts_suite *testthread(abts_suite *suite) abts_run_test(suite, join_threads, NULL); abts_run_test(suite, check_locks, NULL); abts_run_test(suite, check_thread_once, NULL); + abts_run_test(suite, thread_name, NULL); #endif return suite; diff --git a/threadproc/beos/thread.c b/threadproc/beos/thread.c index 4f9d0408e..bf297330f 100644 --- a/threadproc/beos/thread.c +++ b/threadproc/beos/thread.c @@ -345,3 +345,17 @@ APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, } APR_POOL_IMPLEMENT_ACCESSOR(thread) + +APR_DECLARE(apr_status_t) apr_thread_name_set(const char* name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_name_get(apr_thread_t *thread, + char **name, + apr_pool_t pool) +{ + return APR_ENOTIMPL; +} diff --git a/threadproc/netware/thread.c b/threadproc/netware/thread.c index 8d3bfd2b0..822d2e24f 100644 --- a/threadproc/netware/thread.c +++ b/threadproc/netware/thread.c @@ -356,4 +356,16 @@ APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, APR_POOL_IMPLEMENT_ACCESSOR(thread) +APR_DECLARE(apr_status_t) apr_thread_name_set(const char *name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} +APR_DECLARE(apr_status_t) apr_thread_name_get(char ** name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +}
\ No newline at end of file diff --git a/threadproc/os2/thread.c b/threadproc/os2/thread.c index 32acb3704..1ea7954dc 100644 --- a/threadproc/os2/thread.c +++ b/threadproc/os2/thread.c @@ -261,6 +261,20 @@ APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_thread_name_set(const char *name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_name_get(char ** name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + void apr_thread_yield() diff --git a/threadproc/unix/thread.c b/threadproc/unix/thread.c index d90d05f46..70a7c5d30 100644 --- a/threadproc/unix/thread.c +++ b/threadproc/unix/thread.c @@ -22,6 +22,11 @@ #if APR_HAVE_PTHREAD_H +/* Unfortunately the kernel headers do not export the TASK_COMM_LEN + macro. So we have to define it here. Used in apr_thread_name_get and + apr_thread_name_set functions */ +#define TASK_COMM_LEN 16 + /* Destroy the threadattr object */ static apr_status_t threadattr_cleanup(void *data) { @@ -279,6 +284,56 @@ APR_DECLARE(apr_thread_t *) apr_thread_current(void) #endif } +APR_DECLARE(apr_status_t) apr_thread_name_set(const char *name, + apr_thread_t *thread, + apr_pool_t *pool) +{ +#if HAVE_PTHREAD_SETNAME_NP + pthread_t td; + + size_t name_len; + if (!name) { + return APR_BADARG; + } + + if (thread) { + td = *thread->td; + } + else { + td = pthread_self(); + } + + name_len = strlen(name); + if (name_len >= TASK_COMM_LEN) { + name = name + name_len - TASK_COMM_LEN + 1; + } + + return pthread_setname_np(td, name); +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_thread_name_get(char **name, + apr_thread_t *thread, + apr_pool_t *pool) +{ +#if HAVE_PTHREAD_SETNAME_NP + pthread_t td; + if (thread) { + td = *thread->td; + } + else { + td = pthread_self(); + } + + *name = apr_pcalloc(pool, TASK_COMM_LEN); + return pthread_getname_np(td, *name, TASK_COMM_LEN); +#else + return APR_ENOTIMPL; +#endif +} + APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) { return pthread_self(); diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 9d1a0f5d3..502c317a8 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -24,6 +24,7 @@ #include <process.h> #endif #include "apr_arch_misc.h" +#include "apr_arch_utf8.h" /* Chosen for us by apr_initialize */ DWORD tls_apr_thread = 0; @@ -303,6 +304,77 @@ APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, return apr_pool_userdata_set(data, key, cleanup, thread->pool); } +APR_DECLARE(apr_status_t) apr_thread_name_set(const char *name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + apr_wchar_t *wname; + apr_size_t wname_len; + apr_size_t name_len; + apr_status_t rv; + HANDLE thread_handle; + + if (!APR_HAVE_LATE_DLL_FUNC(SetThreadDescription)) { + return APR_ENOTIMPL; + } + + if (thread) { + thread_handle = thread->td; + } + else { + thread_handle = GetCurrentThread(); + } + + name_len = strlen(name) + 1; + wname_len = name_len; + wname = apr_palloc(pool, wname_len * sizeof(apr_wchar_t)); + rv = apr_conv_utf8_to_ucs2(name, &name_len, wname, &wname_len); + if (rv) { + return rv; + } + + if (!apr_winapi_SetThreadDescription(thread_handle, wname)) { + return apr_get_os_error(); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_name_get(char **name, + apr_thread_t *thread, + apr_pool_t *pool) +{ + apr_wchar_t *wname; + apr_size_t wname_len; + apr_size_t name_len; + apr_status_t rv; + HANDLE thread_handle; + + if (!APR_HAVE_LATE_DLL_FUNC(GetThreadDescription)) { + return APR_ENOTIMPL; + } + + if (thread) { + thread_handle = thread->td; + } + else { + thread_handle = GetCurrentThread(); + } + + if (!apr_winapi_GetThreadDescription(thread_handle, &wname)) { + return apr_get_os_error(); + } + + wname_len = wcslen(wname) + 1; + + name_len = wname_len * 3; + *name = apr_palloc(pool, name_len); + + rv = apr_conv_ucs2_to_utf8(wname, &wname_len, *name, &name_len); + LocalFree(wname); + + return rv; +} APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) { |