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;