Implement pthread_setname_np and pthread_getname_np These should be compatible with Linux, pthreads-win32 (Linux mode) and Cygwin implementations (but not OSX, BSD or pthreads-win32 (BSD mode)). Based on MSDN code[1]. [1] https://msdn.microsoft.com/en-us/library/xcb2z8hs%28v=vs.71%29.aspx
diff --git a/mingw-w64-libraries/winpthreads/include/pthread.h b/mingw-w64-libraries/winpthreads/include/pthread.h index f63d328..355bdae 100644 --- a/mingw-w64-libraries/winpthreads/include/pthread.h +++ b/mingw-w64-libraries/winpthreads/include/pthread.h
@@ -314,6 +314,9 @@ int WINPTHREAD_API pthread_create(pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg); int WINPTHREAD_API pthread_join(pthread_t t, void **res); int WINPTHREAD_API pthread_detach(pthread_t t); +int WINPTHREAD_API pthread_setname_np(pthread_t thread, const char *name); +int WINPTHREAD_API pthread_getname_np(pthread_t thread, char *name, size_t len); + int WINPTHREAD_API pthread_rwlock_init(pthread_rwlock_t *rwlock_, const pthread_rwlockattr_t *attr); int WINPTHREAD_API pthread_rwlock_wrlock(pthread_rwlock_t *l);
diff --git a/mingw-w64-libraries/winpthreads/src/thread.c b/mingw-w64-libraries/winpthreads/src/thread.c index 141faf0..5c40f12 100644 --- a/mingw-w64-libraries/winpthreads/src/thread.c +++ b/mingw-w64-libraries/winpthreads/src/thread.c
@@ -21,6 +21,7 @@ */ #include <windows.h> +#include <strsafe.h> #include <stdio.h> #include <malloc.h> #include <signal.h> @@ -52,6 +53,60 @@ static size_t idListMax = 0; static pthread_t idListNextId = 0; +#if !defined(_MSC_VER) || defined (USE_VEH_FOR_MSC_SETTHREADNAME) +static void *SetThreadName_VEH_handle = NULL; + +static LONG __stdcall +SetThreadName_VEH (PEXCEPTION_POINTERS ExceptionInfo) +{ + if (ExceptionInfo->ExceptionRecord != NULL && + ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SET_THREAD_NAME) + return EXCEPTION_CONTINUE_EXECUTION; + + return EXCEPTION_CONTINUE_SEARCH; +} +#endif + +typedef struct _THREADNAME_INFO +{ + DWORD dwType; /* must be 0x1000 */ + LPCSTR szName; /* pointer to name (in user addr space) */ + DWORD dwThreadID; /* thread ID (-1=caller thread) */ + DWORD dwFlags; /* reserved for future use, must be zero */ +} THREADNAME_INFO; + +static void +SetThreadName (DWORD dwThreadID, LPCSTR szThreadName) +{ + THREADNAME_INFO info; + DWORD infosize; + + info.dwType = 0x1000; + info.szName = szThreadName; + info.dwThreadID = dwThreadID; + info.dwFlags = 0; + + infosize = sizeof (info) / sizeof (DWORD); + +#if defined(_MSC_VER) && !defined (USE_VEH_FOR_MSC_SETTHREADNAME) + __try + { + RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (DWORD *) &info); + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } +#else + /* Without a debugger we *must* have an exception handler, + * otherwise raising an exception will crash the process. + */ + if ((!IsDebuggerPresent ()) && (SetThreadName_VEH_handle == NULL)) + return; + + RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (DWORD *) &info); +#endif +} + /* Search the list idList for an element with identifier ID. If found, its associated _pthread_v pointer is returned, otherwise NULL. @@ -234,6 +289,8 @@ free (sv->keyval); if (sv->keyval_set) free (sv->keyval_set); + if (sv->thread_name) + free (sv->thread_name); memset (sv, 0, sizeof(struct _pthread_v)); if (pthr_last == NULL) pthr_root = pthr_last = sv; @@ -326,8 +383,22 @@ if (dwReason == DLL_PROCESS_DETACH) { +#if !defined(_MSC_VER) || defined (USE_VEH_FOR_MSC_SETTHREADNAME) + if (lpreserved == NULL && SetThreadName_VEH_handle != NULL) + { + RemoveVectoredExceptionHandler (SetThreadName_VEH_handle); + SetThreadName_VEH_handle = NULL; + } +#endif free_pthread_mem (); } + else if (dwReason == DLL_PROCESS_ATTACH) + { +#if !defined(_MSC_VER) || defined (USE_VEH_FOR_MSC_SETTHREADNAME) + SetThreadName_VEH_handle = AddVectoredExceptionHandler (1, &SetThreadName_VEH); + /* Can't do anything on error anyway, check for NULL later */ +#endif + } else if (dwReason == DLL_THREAD_DETACH) { if (_pthread_tls != 0xffffffff) @@ -1667,3 +1738,61 @@ return 0; } +int +pthread_setname_np (pthread_t thread, const char *name) +{ + struct _pthread_v *tv; + char *stored_name; + + if (name == NULL) + return EINVAL; + + tv = __pth_gpointer_locked (thread); + if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL + || tv->h == INVALID_HANDLE_VALUE) + return ESRCH; + + stored_name = strdup (name); + if (stored_name == NULL) + return ENOMEM; + + if (tv->thread_name != NULL) + free (tv->thread_name); + + tv->thread_name = stored_name; + SetThreadName (tv->tid, name); + return 0; +} + +int +pthread_getname_np (pthread_t thread, char *name, size_t len) +{ + HRESULT result; + struct _pthread_v *tv; + + if (name == NULL) + return EINVAL; + + tv = __pth_gpointer_locked (thread); + if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL + || tv->h == INVALID_HANDLE_VALUE) + return ESRCH; + + if (len < 1) + return ERANGE; + + if (tv->thread_name == NULL) + { + name[0] = '\0'; + return 0; + } + + if (strlen (tv->thread_name) >= len) + return ERANGE; + + result = StringCchCopyNA (name, len, tv->thread_name, len - 1); + if (SUCCEEDED (result)) + return 0; + + return ERANGE; +}
diff --git a/mingw-w64-libraries/winpthreads/src/thread.h b/mingw-w64-libraries/winpthreads/src/thread.h index 07cfc24..caaf058 100644 --- a/mingw-w64-libraries/winpthreads/src/thread.h +++ b/mingw-w64-libraries/winpthreads/src/thread.h
@@ -29,6 +29,7 @@ #define LIFE_THREAD 0xBAB1F00D #define DEAD_THREAD 0xDEADBEEF +#define EXCEPTION_SET_THREAD_NAME ((DWORD) 0x406D1388) typedef struct _pthread_v _pthread_v; struct _pthread_v @@ -48,6 +49,7 @@ unsigned int keymax; void **keyval; unsigned char *keyval_set; + char *thread_name; pthread_spinlock_t spin_keys; DWORD tid; int rwlc;