From e1db51383b07bc79d6d43a12fe304d54726f9b75 Mon Sep 17 00:00:00 2001 From: Phil Vachon Date: Fri, 1 Aug 2025 17:01:24 -0400 Subject: [PATCH] Use OS-provided thread ID primitives Truncating 64-bit thread IDs to 32-bits can result in collisions on systems with large numbers of CPUs. GetCurrentThreadId() does this, and there are fairly easy to reproduce collisions on systems with ~128 CPU cores. The `GetCurrentThreadId` API should wrap an OS-specific way of providing the current thread ID. Keep the XOR-folded pointer as a fallback for OSes which aren't explicitly supported. This fixes failures in TestSynchCritical that are readily reproducible on such systems.. Tested on FreeBSD 14.3 and various Linux variants on x86_64. --- winpr/libwinpr/thread/thread.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index d9b04fc91..d6c546768 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -29,6 +29,13 @@ #include +#if defined(__MACOSX__) || defined(__FreeBSD__) +#include +#elif defined(__linux__) +#include + +#endif + #ifndef MIN #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif @@ -911,11 +918,20 @@ HANDLE _GetCurrentThread(VOID) DWORD GetCurrentThreadId(VOID) { +#if defined(__FreeBSD__) || defined(__MACOSX__) + int tid = pthread_getthreadid_np(); + return tid; +#elif defined(__linux__) + pid_t tid = syscall(SYS_gettid); + return tid; +#else +#warning Using possibly broken GetCurrentThreadId pthread_t tid = pthread_self(); /* Since pthread_t can be 64-bits on some systems, take just the */ /* lower 32-bits of it for the thread ID returned by this function. */ uintptr_t ptid = WINPR_REINTERPRET_CAST(tid, pthread_t, uintptr_t); - return ptid & UINT32_MAX; + return (ptid & UINT32_MAX) ^ (ptid >> 32); +#endif } typedef struct