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.
This commit is contained in:
Phil Vachon
2025-08-01 17:01:24 -04:00
committed by Phil Vachon
parent 774ee652a9
commit e1db51383b

View File

@@ -29,6 +29,13 @@
#include <winpr/thread.h>
#if defined(__MACOSX__) || defined(__FreeBSD__)
#include <pthread_np.h>
#elif defined(__linux__)
#include <sys/syscall.h>
#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