From 9b5c27af793a08fd17d1fde93e9512e76536f484 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 9 Apr 2024 09:03:30 +0200 Subject: C++ migration: YIELD() → std::this_thread::yield. plus more threading code cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lanes.cpp | 4 +- src/threading.cpp | 300 ++++++++++++++++++++++++------------------------------ src/threading.h | 208 ++++++++++--------------------------- 3 files changed, 193 insertions(+), 319 deletions(-) (limited to 'src') diff --git a/src/lanes.cpp b/src/lanes.cpp index 12cd7ef..f5d5130 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -502,7 +502,7 @@ static int universe_gc( lua_State* L) while (U->selfdestruct_first != SELFDESTRUCT_END) { // give threads time to act on their cancel - YIELD(); + std::this_thread::yield(); // count the number of cancelled thread that didn't have the time to act yet int n{ 0 }; { @@ -529,7 +529,7 @@ static int universe_gc( lua_State* L) // They are no longer listed in the selfdestruct chain, but they still have to lua_close(). while (U->selfdestructing_count.load(std::memory_order_acquire) > 0) { - YIELD(); + std::this_thread::yield(); } } diff --git a/src/threading.cpp b/src/threading.cpp index bc1852f..aab2fa7 100644 --- a/src/threading.cpp +++ b/src/threading.cpp @@ -97,64 +97,28 @@ THE SOFTWARE. * FAIL is for unexpected API return values - essentially programming * error in _this_ code. */ -#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) -static void FAIL( char const* funcname, int rc) -{ -#if defined( PLATFORM_XBOX) - fprintf( stderr, "%s() failed! (%d)\n", funcname, rc ); +#if defined(PLATFORM_XBOX) || defined(PLATFORM_WIN32) || defined(PLATFORM_POCKETPC) + static void FAIL(char const* funcname, int rc) + { +#if defined(PLATFORM_XBOX) + fprintf(stderr, "%s() failed! (%d)\n", funcname, rc); #else // PLATFORM_XBOX - char buf[256]; - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, nullptr); - fprintf( stderr, "%s() failed! [GetLastError() -> %d] '%s'", funcname, rc, buf); + char buf[256]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, nullptr); + fprintf(stderr, "%s() failed! [GetLastError() -> %d] '%s'", funcname, rc, buf); #endif // PLATFORM_XBOX #ifdef _MSC_VER - __debugbreak(); // give a chance to the debugger! + __debugbreak(); // give a chance to the debugger! #endif // _MSC_VER - abort(); -} + abort(); + } #endif // win32 build /*---=== Threading ===---*/ -//--- -// It may be meaningful to explicitly limit the new threads' C stack size. -// We should know how much Lua needs in the C stack, all Lua side allocations -// are done in heap so they don't count. -// -// Consequence of _not_ limiting the stack is running out of virtual memory -// with 1000-5000 threads on 32-bit systems. -// -// Note: using external C modules may be affected by the stack size check. -// if having problems, set back to '0' (default stack size of the system). -// -// Win32: 64K (?) -// Win64: xxx -// -// Linux x86: 2MB Ubuntu 7.04 via 'pthread_getstacksize()' -// Linux x64: xxx -// Linux ARM: xxx -// -// OS X 10.4.9: 512K -// valid values N * 4KB -// -#ifndef _THREAD_STACK_SIZE -# if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) || defined( PLATFORM_CYGWIN) -# define _THREAD_STACK_SIZE 0 - // Win32: does it work with less? -# elif (defined PLATFORM_OSX) -# define _THREAD_STACK_SIZE (524288/2) // 262144 - // OS X: "make test" works on 65536 and even below - // "make perftest" works on >= 4*65536 == 262144 (not 3*65536) -# elif (defined PLATFORM_LINUX) && (defined __i386) -# define _THREAD_STACK_SIZE (2097152/16) // 131072 - // Linux x86 (Ubuntu 7.04): "make perftest" works on /16 (not on /32) -# elif (defined PLATFORM_BSD) && (defined __i386) -# define _THREAD_STACK_SIZE (1048576/8) // 131072 - // FreeBSD 6.2 SMP i386: ("gmake perftest" works on /8 (not on /16) -# endif -#endif - +// ################################################################################################## +// ################################################################################################## #if THREADAPI == THREADAPI_WINDOWS static int const gs_prio_remap[] = @@ -170,12 +134,12 @@ static int const gs_prio_remap[] = // ############################################################################################### -void THREAD_SET_PRIORITY( int prio) +void THREAD_SET_PRIORITY(int prio) { // prio range [-3,+3] was checked by the caller - if (!SetThreadPriority( GetCurrentThread(), gs_prio_remap[prio + 3])) + if (!SetThreadPriority(GetCurrentThread(), gs_prio_remap[prio + 3])) { - FAIL( "THREAD_SET_PRIORITY", GetLastError()); + FAIL("THREAD_SET_PRIORITY", GetLastError()); } } @@ -194,86 +158,94 @@ void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_) void THREAD_SET_AFFINITY(unsigned int aff) { - if( !SetThreadAffinityMask( GetCurrentThread(), aff)) + if (!SetThreadAffinityMask(GetCurrentThread(), aff)) { - FAIL( "THREAD_SET_AFFINITY", GetLastError()); + FAIL("THREAD_SET_AFFINITY", GetLastError()); } } +// ############################################################################################### + #if !defined __GNUC__ - //see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - #define 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) +//see http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx +#define 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) #endif // !__GNUC__ - void THREAD_SETNAME( char const* _name) - { +void THREAD_SETNAME(char const* _name) +{ #if !defined __GNUC__ - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = _name; - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = _name; + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; - __try - { - RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } -#endif // !__GNUC__ + __try + { + RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); } + __except(EXCEPTION_EXECUTE_HANDLER) + { + } +#endif // !__GNUC__ +} +// ################################################################################################## +// ################################################################################################## #else // THREADAPI == THREADAPI_PTHREAD - // PThread (Linux, OS X, ...) - // - // On OS X, user processes seem to be able to change priorities. - // On Linux, SCHED_RR and su privileges are required.. !-( - // - #include - #include - -# if (defined(__MINGW32__) || defined(__MINGW64__)) && defined pthread_attr_setschedpolicy -# if pthread_attr_setschedpolicy( A, S) == ENOTSUP - // from the mingw-w64 team: - // Well, we support pthread_setschedparam by which you can specify - // threading-policy. Nevertheless, yes we lack this function. In - // general its implementation is pretty much trivial, as on Win32 target - // just SCHED_OTHER can be supported. - #undef pthread_attr_setschedpolicy - static int pthread_attr_setschedpolicy( pthread_attr_t* attr, int policy) +// ################################################################################################## +// ################################################################################################## + +// PThread (Linux, OS X, ...) +// +// On OS X, user processes seem to be able to change priorities. +// On Linux, SCHED_RR and su privileges are required.. !-( +// +#include +#include + +#if (defined(__MINGW32__) || defined(__MINGW64__)) && defined pthread_attr_setschedpolicy +#if pthread_attr_setschedpolicy(A, S) == ENOTSUP +// from the mingw-w64 team: +// Well, we support pthread_setschedparam by which you can specify +// threading-policy. Nevertheless, yes we lack this function. In +// general its implementation is pretty much trivial, as on Win32 target +// just SCHED_OTHER can be supported. +#undef pthread_attr_setschedpolicy +static int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy) +{ + if (policy != SCHED_OTHER) { - if( policy != SCHED_OTHER) - { - return ENOTSUP; - } - return 0; + return ENOTSUP; } -# endif // pthread_attr_setschedpolicy() -# endif // defined(__MINGW32__) || defined(__MINGW64__) + return 0; +} +#endif // pthread_attr_setschedpolicy() +#endif // defined(__MINGW32__) || defined(__MINGW64__) - static void _PT_FAIL( int rc, const char *name, const char *file, int line ) { +static void _PT_FAIL( int rc, const char *name, const char *file, int line ) +{ const char *why= (rc==EINVAL) ? "EINVAL" : - (rc==EBUSY) ? "EBUSY" : - (rc==EPERM) ? "EPERM" : - (rc==ENOMEM) ? "ENOMEM" : - (rc==ESRCH) ? "ESRCH" : - (rc==ENOTSUP) ? "ENOTSUP": - //... - ""; + (rc==EBUSY) ? "EBUSY" : + (rc==EPERM) ? "EPERM" : + (rc==ENOMEM) ? "ENOMEM" : + (rc==ESRCH) ? "ESRCH" : + (rc==ENOTSUP) ? "ENOTSUP": + //... + ""; fprintf( stderr, "%s %d: %s failed, %d %s\n", file, line, name, rc, why ); abort(); - } - #define PT_CALL( call ) { int rc= call; if (rc!=0) _PT_FAIL( rc, #call, __FILE__, __LINE__ ); } +} +#define PT_CALL( call ) { int rc= call; if (rc!=0) _PT_FAIL( rc, #call, __FILE__, __LINE__ ); } // array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range static int const gs_prio_remap[] = @@ -376,14 +348,6 @@ static int const gs_prio_remap[] = // // TBD: Find right values for Cygwin // -# elif defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC) - // any other value not supported by win32-pthread as of version 2.9.1 -# define _PRIO_MODE SCHED_OTHER - - // PTHREAD_SCOPE_PROCESS not supported by win32-pthread as of version 2.9.1 - //#define _PRIO_SCOPE PTHREAD_SCOPE_SYSTEM // but do we need this at all to start with? - THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL - # else # error "Unknown OS: not implemented!" # endif @@ -404,17 +368,17 @@ static int select_prio(int prio /* -3..+3 */) return gs_prio_remap[prio + 3]; } -void THREAD_SET_PRIORITY( int prio) +void THREAD_SET_PRIORITY(int prio) { #ifdef PLATFORM_LINUX - if( sudo) // only root-privileged process can change priorities + if (!sudo) // only root-privileged process can change priorities + return; #endif // PLATFORM_LINUX - { - struct sched_param sp; - // prio range [-3,+3] was checked by the caller - sp.sched_priority = gs_prio_remap[ prio + 3]; - PT_CALL( pthread_setschedparam( pthread_self(), _PRIO_MODE, &sp)); - } + + struct sched_param sp; + // prio range [-3,+3] was checked by the caller + sp.sched_priority = gs_prio_remap[prio + 3]; + PT_CALL(pthread_setschedparam(pthread_self(), _PRIO_MODE, &sp)); } // ################################################################################################# @@ -422,69 +386,75 @@ void THREAD_SET_PRIORITY( int prio) void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_) { #ifdef PLATFORM_LINUX - if (sudo) // only root-privileged process can change priorities + if (!sudo) // only root-privileged process can change priorities + return; #endif // PLATFORM_LINUX - { - struct sched_param sp; - // prio range [-3,+3] was checked by the caller - sp.sched_priority = gs_prio_remap[prio_ + 3]; - PT_CALL(pthread_setschedparam(static_cast(thread_.native_handle()), _PRIO_MODE, &sp)); - } + + struct sched_param sp; + // prio range [-3,+3] was checked by the caller + sp.sched_priority = gs_prio_remap[prio_ + 3]; + PT_CALL(pthread_setschedparam(static_cast(thread_.native_handle()), _PRIO_MODE, &sp)); } // ################################################################################################# -void THREAD_SET_AFFINITY( unsigned int aff) +void THREAD_SET_AFFINITY(unsigned int aff) { int bit = 0; #ifdef __NetBSD__ - cpuset_t *cpuset = cpuset_create(); + cpuset_t* cpuset = cpuset_create(); if (cpuset == nullptr) - _PT_FAIL( errno, "cpuset_create", __FILE__, __LINE__-2 ); + _PT_FAIL(errno, "cpuset_create", __FILE__, __LINE__ - 2); #define CPU_SET(b, s) cpuset_set(b, *(s)) #else cpu_set_t cpuset; - CPU_ZERO( &cpuset); + CPU_ZERO(&cpuset); #endif - while( aff != 0) + while (aff != 0) { - if( aff & 1) + if (aff & 1) { - CPU_SET( bit, &cpuset); + CPU_SET(bit, &cpuset); } - ++ bit; + ++bit; aff >>= 1; } #ifdef __ANDROID__ - PT_CALL( sched_setaffinity( pthread_self(), sizeof(cpu_set_t), &cpuset)); + PT_CALL(sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &cpuset)); #elif defined(__NetBSD__) - PT_CALL( pthread_setaffinity_np( pthread_self(), cpuset_size(cpuset), cpuset)); - cpuset_destroy( cpuset); + PT_CALL(pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset), cpuset)); + cpuset_destroy(cpuset); #else - PT_CALL( pthread_setaffinity_np( pthread_self(), sizeof(cpu_set_t), &cpuset)); + PT_CALL(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)); #endif } - void THREAD_SETNAME( char const* _name) - { - // exact API to set the thread name is platform-dependant - // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github. +// ################################################################################################# + +void THREAD_SETNAME(char const* _name) +{ + // exact API to set the thread name is platform-dependant + // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github. #if defined PLATFORM_BSD && !defined __NetBSD__ - pthread_set_name_np( pthread_self(), _name); + pthread_set_name_np(pthread_self(), _name); #elif defined PLATFORM_BSD && defined __NetBSD__ - pthread_setname_np( pthread_self(), "%s", (void *)_name); + pthread_setname_np(pthread_self(), "%s", (void*) _name); #elif defined PLATFORM_LINUX - #if LINUX_USE_PTHREAD_SETNAME_NP - pthread_setname_np( pthread_self(), _name); - #else // LINUX_USE_PTHREAD_SETNAME_NP - prctl(PR_SET_NAME, _name, 0, 0, 0); - #endif // LINUX_USE_PTHREAD_SETNAME_NP +#if LINUX_USE_PTHREAD_SETNAME_NP + pthread_setname_np(pthread_self(), _name); +#else // LINUX_USE_PTHREAD_SETNAME_NP + prctl(PR_SET_NAME, _name, 0, 0, 0); +#endif // LINUX_USE_PTHREAD_SETNAME_NP #elif defined PLATFORM_QNX || defined PLATFORM_CYGWIN - pthread_setname_np( pthread_self(), _name); + pthread_setname_np(pthread_self(), _name); #elif defined PLATFORM_OSX - pthread_setname_np(_name); -#elif defined PLATFORM_WIN32 || defined PLATFORM_POCKETPC - PT_CALL( pthread_setname_np( pthread_self(), _name)); + pthread_setname_np(_name); +#else + fprintf(stderr, "THREAD_SETNAME: unsupported platform\n"); + abort(); #endif - } +} + #endif // THREADAPI == THREADAPI_PTHREAD +// ################################################################################################# +// ################################################################################################# diff --git a/src/threading.h b/src/threading.h index 82c8f52..c443c82 100644 --- a/src/threading.h +++ b/src/threading.h @@ -16,22 +16,24 @@ #define THREADAPI THREADAPI_PTHREAD #endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) -/*---=== Locks & Signals ===--- -*/ +static constexpr int THREAD_PRIO_DEFAULT{ -999 }; +// ################################################################################################## +// ################################################################################################## #if THREADAPI == THREADAPI_WINDOWS - #if defined( PLATFORM_XBOX) - #include - #else // !PLATFORM_XBOX - #define WIN32_LEAN_AND_MEAN - // CONDITION_VARIABLE needs version 0x0600+ - // _WIN32_WINNT value is already defined by MinGW, but not by MSVC - #ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0600 - #endif // _WIN32_WINNT - #include - #endif // !PLATFORM_XBOX - #include + +#if defined(PLATFORM_XBOX) +#include +#else // !PLATFORM_XBOX +#define WIN32_LEAN_AND_MEAN +// CONDITION_VARIABLE needs version 0x0600+ +// _WIN32_WINNT value is already defined by MinGW, but not by MSVC +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 +#endif // _WIN32_WINNT +#include +#endif // !PLATFORM_XBOX +#include /* #define XSTR(x) STR(x) @@ -39,148 +41,50 @@ #pragma message( "The value of _WIN32_WINNT: " XSTR(_WIN32_WINNT)) */ - // MSDN: http://msdn2.microsoft.com/en-us/library/ms684254.aspx - // - // CRITICAL_SECTION can be used for simple code protection. Mutexes are - // needed for use with the SIGNAL system. - // - - #if _WIN32_WINNT < 0x0600 // CONDITION_VARIABLE aren't available, use a signal - - struct SIGNAL_T - { - CRITICAL_SECTION signalCS; - CRITICAL_SECTION countCS; - HANDLE waitEvent; - HANDLE waitDoneEvent; - LONG waitersCount; - }; - - - #else // CONDITION_VARIABLE are available, use them +static constexpr int THREAD_PRIO_MIN{ -3 }; +static constexpr int THREAD_PRIO_MAX{ +3 }; - #define SIGNAL_T CONDITION_VARIABLE - #define MUTEX_INIT( ref) InitializeCriticalSection( ref) - #define MUTEX_FREE( ref) DeleteCriticalSection( ref) - #define MUTEX_LOCK( ref) EnterCriticalSection( ref) - #define MUTEX_UNLOCK( ref) LeaveCriticalSection( ref) - - #endif // CONDITION_VARIABLE are available - - #define MUTEX_RECURSIVE_INIT(ref) MUTEX_INIT(ref) /* always recursive in Win32 */ - - using THREAD_RETURN_T = unsigned int; - - #define YIELD() Sleep(0) - #define THREAD_CALLCONV __stdcall +// ################################################################################################## +// ################################################################################################## #else // THREADAPI == THREADAPI_PTHREAD - // PThread (Linux, OS X, ...) - - // looks like some MinGW installations don't support PTW32_INCLUDE_WINDOWS_H, so let's include it ourselves, just in case - #if defined(PLATFORM_WIN32) - #include - #endif // PLATFORM_WIN32 - #include - - #ifdef PLATFORM_LINUX - #if defined(__GLIBC__) - # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP - #else - # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE - #endif - #else - /* OS X, ... */ - # define _MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE - #endif - - #define MUTEX_INIT(ref) pthread_mutex_init(ref, nullptr) - #define MUTEX_RECURSIVE_INIT(ref) \ - { pthread_mutexattr_t a; pthread_mutexattr_init( &a ); \ - pthread_mutexattr_settype( &a, _MUTEX_RECURSIVE ); \ - pthread_mutex_init(ref,&a); pthread_mutexattr_destroy( &a ); \ - } - #define MUTEX_FREE(ref) pthread_mutex_destroy(ref) - #define MUTEX_LOCK(ref) pthread_mutex_lock(ref) - #define MUTEX_UNLOCK(ref) pthread_mutex_unlock(ref) - - using THREAD_RETURN_T = void *; - - using SIGNAL_T = pthread_cond_t; - - // Yield is non-portable: - // - // OS X 10.4.8/9 has pthread_yield_np() - // Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined - // FreeBSD 6.2 has pthread_yield() - // ... - // - #if defined( PLATFORM_OSX) - #define YIELD() pthread_yield_np() - #else - #define YIELD() sched_yield() - #endif - #define THREAD_CALLCONV -#endif //THREADAPI == THREADAPI_PTHREAD - -/*---=== Threading ===--- -*/ - -#define THREAD_PRIO_DEFAULT (-999) - -#if THREADAPI == THREADAPI_WINDOWS - -# define THREAD_PRIO_MIN (-3) -# define THREAD_PRIO_MAX (+3) - -#else // THREADAPI == THREADAPI_PTHREAD - - /* Platforms that have a timed 'pthread_join()' can get away with a simpler - * implementation. Others will use a condition variable. - */ -# if defined __WINPTHREADS_VERSION -//# define USE_PTHREAD_TIMEDJOIN -# endif // __WINPTHREADS_VERSION - -# ifdef USE_PTHREAD_TIMEDJOIN -# ifdef PLATFORM_OSX -# error "No 'pthread_timedjoin()' on this system" -# else - /* Linux, ... */ -# define PTHREAD_TIMEDJOIN pthread_timedjoin_np -# endif -# endif - -# if defined(PLATFORM_LINUX) - extern volatile bool sudo; -# ifdef LINUX_SCHED_RR -# define THREAD_PRIO_MIN (sudo ? -3 : 0) -# else -# define THREAD_PRIO_MIN (0) -# endif -# define THREAD_PRIO_MAX (sudo ? +3 : 0) -# else -# define THREAD_PRIO_MIN (-3) -# define THREAD_PRIO_MAX (+3) -# endif +// ################################################################################################## +// ################################################################################################## + +// PThread (Linux, OS X, ...) + +// looks like some MinGW installations don't support PTW32_INCLUDE_WINDOWS_H, so let's include it ourselves, just in case +#if defined(PLATFORM_WIN32) +#include +#endif // PLATFORM_WIN32 +#include + +// Yield is non-portable: +// +// OS X 10.4.8/9 has pthread_yield_np() +// Linux 2.4 has pthread_yield() if _GNU_SOURCE is #defined +// FreeBSD 6.2 has pthread_yield() +// ... +// + +#if defined(PLATFORM_LINUX) +extern volatile bool sudo; +# ifdef LINUX_SCHED_RR +# define THREAD_PRIO_MIN (sudo ? -3 : 0) +# else +static constexpr int THREAD_PRIO_MIN{ 0 }; +#endif +# define THREAD_PRIO_MAX (sudo ? +3 : 0) +#else +static constexpr int THREAD_PRIO_MIN{ -3 }; +static constexpr int THREAD_PRIO_MAX{ +3 }; +#endif #endif // THREADAPI == THREADAPI_WINDOWS +// ################################################################################################## +// ################################################################################################## -/* -* Win32 and PTHREAD_TIMEDJOIN allow waiting for a thread with a timeout. -* Posix without PTHREAD_TIMEDJOIN needs to use a condition variable approach. -*/ -#define THREADWAIT_TIMEOUT 1 -#define THREADWAIT_CONDVAR 2 - -#if THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) -#define THREADWAIT_METHOD THREADWAIT_TIMEOUT -#else // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) -#define THREADWAIT_METHOD THREADWAIT_CONDVAR -#endif // THREADAPI == THREADAPI_WINDOWS || (defined PTHREAD_TIMEDJOIN) - - -void THREAD_SETNAME( char const* _name); -void THREAD_SET_PRIORITY( int prio); -void THREAD_SET_AFFINITY( unsigned int aff); +void THREAD_SETNAME(char const* _name); +void THREAD_SET_PRIORITY(int prio); +void THREAD_SET_AFFINITY(unsigned int aff); void JTHREAD_SET_PRIORITY(std::jthread& thread_, int prio_); -- cgit v1.2.3-55-g6feb