NSThread: Fix behaviour and Implement setName on Win32

This commit is contained in:
hmelder 2024-04-18 21:10:45 -07:00 committed by Hugo Melder
parent 6f9af4349c
commit 8a93628ecb
2 changed files with 63 additions and 56 deletions

View file

@ -31,6 +31,7 @@
*/
#import "common.h"
#include <processthreadsapi.h>
#import "GSPThread.h"
@ -191,58 +192,14 @@ GSPrivateThreadID()
#endif
}
#if 0
/*
* NSThread setName: method for windows.
* FIXME ... This is code for the microsoft compiler;
* how do we make it work for gcc/clang?
*/
#if defined(_WIN32) && defined(HAVE_WINDOWS_H)
// Usage: SetThreadName (-1, "MainThread");
#include <windows.h>
const DWORD MS_VC_EXCEPTION=0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_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;
#pragma pack(pop)
static int SetThreadName(DWORD dwThreadID, const char *threadName)
{
THREADNAME_INFO info;
int result;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0,
sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
result = 0;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
result = -1;
}
}
#define PTHREAD_SETNAME(a) SetThreadName(-1, a)
#endif
#endif
#ifndef PTHREAD_SETNAME
#define PTHREAD_SETNAME(a) -1
#endif
#ifndef PTHREAD_GETNAME
#define PTHREAD_GETNAME() -1
#endif
@interface NSThread (Activation)
- (void) _makeThreadCurrent;
@ -1253,6 +1210,34 @@ unregisterActiveThread(NSThread *thread)
- (id) init
{
// SetThreadDescription() was added in Windows 10 1607 (Redstone 1)
#if defined(_WIN32) && (NTDDI_VERSION >= NTDDI_WIN10_RS1)
HANDLE current;
HRESULT hr;
PWSTR name;
NSString *threadName;
current = GetCurrentThread();
hr = GetThreadDescription(current, &name);
if (SUCCEEDED(hr))
{
threadName = [NSString stringWithCharacters: (const void *) name length: wcslen(name)];
ASSIGN(_name, threadName);
LocalFree(name);
}
#elif defined(PTHREAD_GETNAME)
NSString *threadName;
char name[16];
int status;
status = PTHREAD_GETNAME(name, 16);
if (status == 0)
{
threadName = [NSString stringWithCString: name encoding: NSUTF8StringEncoding];
ASSIGN(_name, threadName);
}
#endif
GS_CREATE_INTERNAL(NSThread);
pthread_spin_init(&lockInfo.spin, 0);
lockInfo.held = NSCreateHashTable(NSNonOwnedPointerHashCallBacks, 10);
@ -1316,11 +1301,20 @@ unregisterActiveThread(NSThread *thread)
{
if ([aName isKindOfClass: [NSString class]])
{
// SetThreadDescription() was added in Windows 10 1607 (Redstone 1)
#if defined(_WIN32) && (NTDDI_VERSION >= NTDDI_WIN10_RS1)
HANDLE current;
const void *utf16String;
current = GetCurrentThread();
utf16String = [aName cStringUsingEncoding: NSUnicodeStringEncoding];
SetThreadDescription(current, utf16String);
#elif defined(PTHREAD_SETNAME)
int i;
char buf[200];
if (YES == [aName getCString: buf
maxLength: sizeof(buf)
maxLength: sizeof(buf)
encoding: NSUTF8StringEncoding])
{
i = strlen(buf);
@ -1328,7 +1322,7 @@ unregisterActiveThread(NSThread *thread)
else
{
/* Too much for buffer ... truncate on a character boundary.
*/
*/
i = sizeof(buf) - 1;
if (buf[i] & 0x80)
{
@ -1347,7 +1341,7 @@ unregisterActiveThread(NSThread *thread)
if (PTHREAD_SETNAME(buf) == ERANGE)
{
/* Name must be too long ... gnu/linux uses 15 characters
*/
*/
if (i > 15)
{
i = 15;
@ -1357,7 +1351,7 @@ unregisterActiveThread(NSThread *thread)
i--;
}
/* too long a name ... truncate on a character boundary.
*/
*/
if (buf[i] & 0x80)
{
while (i > 0 && (buf[i] & 0x80))
@ -1375,13 +1369,14 @@ unregisterActiveThread(NSThread *thread)
break; // Success or some other error
}
}
}
#endif
}
}
- (void) setName: (NSString*)aName
{
ASSIGN(_name, aName);
#ifdef PTHREAD_SETNAME
if (YES == _active)
{
[self performSelector: @selector(_setName:)
@ -1389,7 +1384,6 @@ unregisterActiveThread(NSThread *thread)
withObject: aName
waitUntilDone: NO];
}
#endif
}
- (void) setStackSize: (NSUInteger)stackSize

View file

@ -1849,7 +1849,20 @@ if test $HAVE_WIN32_THREADS_AND_LOCKS = 0; then
[Description: Define setname function for pthread with three args])
;;
esac
# Check if we can get names of pthreads
AC_CACHE_CHECK([for pthread_getname_np()], gs_cv_pthread_getname_np,
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[char name[16]; pthread_getname_np(pthread_self(), name, 16);])],
[gs_cv_pthread_getname_np=generic])])
case $gs_cv_pthread_getname_np in
generic)
AC_DEFINE(PTHREAD_GETNAME(b,c), pthread_getname_np(pthread_self(),b,c),
[Description: Define getname function for pthread with two args (generic style)])
;;
esac
# Check if we have spinlock support
AC_CHECK_FUNCS(pthread_spin_lock)
fi