1*f6dc9357SAndroid Build Coastguard Worker /* Threads.h -- multithreading library 2*f6dc9357SAndroid Build Coastguard Worker 2024-03-28 : Igor Pavlov : Public domain */ 3*f6dc9357SAndroid Build Coastguard Worker 4*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_THREADS_H 5*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_THREADS_H 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32 8*f6dc9357SAndroid Build Coastguard Worker #include "7zWindows.h" 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker #else 11*f6dc9357SAndroid Build Coastguard Worker 12*f6dc9357SAndroid Build Coastguard Worker #include "Compiler.h" 13*f6dc9357SAndroid Build Coastguard Worker 14*f6dc9357SAndroid Build Coastguard Worker // #define Z7_AFFINITY_DISABLE 15*f6dc9357SAndroid Build Coastguard Worker #if defined(__linux__) 16*f6dc9357SAndroid Build Coastguard Worker #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) 17*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_AFFINITY_DISABLE 18*f6dc9357SAndroid Build Coastguard Worker #define Z7_AFFINITY_SUPPORTED 19*f6dc9357SAndroid Build Coastguard Worker // #pragma message(" ==== Z7_AFFINITY_SUPPORTED") 20*f6dc9357SAndroid Build Coastguard Worker #if !defined(_GNU_SOURCE) 21*f6dc9357SAndroid Build Coastguard Worker // #pragma message(" ==== _GNU_SOURCE set") 22*f6dc9357SAndroid Build Coastguard Worker // we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL 23*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER 24*f6dc9357SAndroid Build Coastguard Worker #define _GNU_SOURCE 25*f6dc9357SAndroid Build Coastguard Worker Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER 26*f6dc9357SAndroid Build Coastguard Worker #endif 27*f6dc9357SAndroid Build Coastguard Worker #endif 28*f6dc9357SAndroid Build Coastguard Worker #endif 29*f6dc9357SAndroid Build Coastguard Worker #endif 30*f6dc9357SAndroid Build Coastguard Worker 31*f6dc9357SAndroid Build Coastguard Worker #include <pthread.h> 32*f6dc9357SAndroid Build Coastguard Worker 33*f6dc9357SAndroid Build Coastguard Worker #endif 34*f6dc9357SAndroid Build Coastguard Worker 35*f6dc9357SAndroid Build Coastguard Worker #include "7zTypes.h" 36*f6dc9357SAndroid Build Coastguard Worker 37*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN 38*f6dc9357SAndroid Build Coastguard Worker 39*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32 40*f6dc9357SAndroid Build Coastguard Worker 41*f6dc9357SAndroid Build Coastguard Worker WRes HandlePtr_Close(HANDLE *h); 42*f6dc9357SAndroid Build Coastguard Worker WRes Handle_WaitObject(HANDLE h); 43*f6dc9357SAndroid Build Coastguard Worker 44*f6dc9357SAndroid Build Coastguard Worker typedef HANDLE CThread; 45*f6dc9357SAndroid Build Coastguard Worker 46*f6dc9357SAndroid Build Coastguard Worker #define Thread_CONSTRUCT(p) { *(p) = NULL; } 47*f6dc9357SAndroid Build Coastguard Worker #define Thread_WasCreated(p) (*(p) != NULL) 48*f6dc9357SAndroid Build Coastguard Worker #define Thread_Close(p) HandlePtr_Close(p) 49*f6dc9357SAndroid Build Coastguard Worker // #define Thread_Wait(p) Handle_WaitObject(*(p)) 50*f6dc9357SAndroid Build Coastguard Worker 51*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE 52*f6dc9357SAndroid Build Coastguard Worker // if (USE_THREADS_CreateThread is defined), we use _beginthreadex() 53*f6dc9357SAndroid Build Coastguard Worker // if (USE_THREADS_CreateThread is not definned), we use CreateThread() 54*f6dc9357SAndroid Build Coastguard Worker #define USE_THREADS_CreateThread 55*f6dc9357SAndroid Build Coastguard Worker #endif 56*f6dc9357SAndroid Build Coastguard Worker 57*f6dc9357SAndroid Build Coastguard Worker typedef 58*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_THREADS_CreateThread 59*f6dc9357SAndroid Build Coastguard Worker DWORD 60*f6dc9357SAndroid Build Coastguard Worker #else 61*f6dc9357SAndroid Build Coastguard Worker unsigned 62*f6dc9357SAndroid Build Coastguard Worker #endif 63*f6dc9357SAndroid Build Coastguard Worker THREAD_FUNC_RET_TYPE; 64*f6dc9357SAndroid Build Coastguard Worker 65*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_RET_ZERO 0 66*f6dc9357SAndroid Build Coastguard Worker 67*f6dc9357SAndroid Build Coastguard Worker typedef DWORD_PTR CAffinityMask; 68*f6dc9357SAndroid Build Coastguard Worker typedef DWORD_PTR CCpuSet; 69*f6dc9357SAndroid Build Coastguard Worker 70*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Zero(p) *(p) = (0) 71*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu)) 72*f6dc9357SAndroid Build Coastguard Worker 73*f6dc9357SAndroid Build Coastguard Worker #else // _WIN32 74*f6dc9357SAndroid Build Coastguard Worker 75*f6dc9357SAndroid Build Coastguard Worker typedef struct 76*f6dc9357SAndroid Build Coastguard Worker { 77*f6dc9357SAndroid Build Coastguard Worker pthread_t _tid; 78*f6dc9357SAndroid Build Coastguard Worker int _created; 79*f6dc9357SAndroid Build Coastguard Worker } CThread; 80*f6dc9357SAndroid Build Coastguard Worker 81*f6dc9357SAndroid Build Coastguard Worker #define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; } 82*f6dc9357SAndroid Build Coastguard Worker #define Thread_WasCreated(p) ((p)->_created != 0) 83*f6dc9357SAndroid Build Coastguard Worker WRes Thread_Close(CThread *p); 84*f6dc9357SAndroid Build Coastguard Worker // #define Thread_Wait Thread_Wait_Close 85*f6dc9357SAndroid Build Coastguard Worker 86*f6dc9357SAndroid Build Coastguard Worker typedef void * THREAD_FUNC_RET_TYPE; 87*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_RET_ZERO NULL 88*f6dc9357SAndroid Build Coastguard Worker 89*f6dc9357SAndroid Build Coastguard Worker 90*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CAffinityMask; 91*f6dc9357SAndroid Build Coastguard Worker 92*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_AFFINITY_SUPPORTED 93*f6dc9357SAndroid Build Coastguard Worker 94*f6dc9357SAndroid Build Coastguard Worker typedef cpu_set_t CCpuSet; 95*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Zero(p) CPU_ZERO(p) 96*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Set(p, cpu) CPU_SET(cpu, p) 97*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) 98*f6dc9357SAndroid Build Coastguard Worker 99*f6dc9357SAndroid Build Coastguard Worker #else 100*f6dc9357SAndroid Build Coastguard Worker 101*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CCpuSet; 102*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Zero(p) *(p) = (0) 103*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu)) 104*f6dc9357SAndroid Build Coastguard Worker #define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) 105*f6dc9357SAndroid Build Coastguard Worker 106*f6dc9357SAndroid Build Coastguard Worker #endif 107*f6dc9357SAndroid Build Coastguard Worker 108*f6dc9357SAndroid Build Coastguard Worker 109*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32 110*f6dc9357SAndroid Build Coastguard Worker 111*f6dc9357SAndroid Build Coastguard Worker 112*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_CALL_TYPE Z7_STDCALL 113*f6dc9357SAndroid Build Coastguard Worker 114*f6dc9357SAndroid Build Coastguard Worker #if defined(_WIN32) && defined(__GNUC__) 115*f6dc9357SAndroid Build Coastguard Worker /* GCC compiler for x86 32-bit uses the rule: 116*f6dc9357SAndroid Build Coastguard Worker the stack is 16-byte aligned before CALL instruction for function calling. 117*f6dc9357SAndroid Build Coastguard Worker But only root function main() contains instructions that 118*f6dc9357SAndroid Build Coastguard Worker set 16-byte alignment for stack pointer. And another functions 119*f6dc9357SAndroid Build Coastguard Worker just keep alignment, if it was set in some parent function. 120*f6dc9357SAndroid Build Coastguard Worker 121*f6dc9357SAndroid Build Coastguard Worker The problem: 122*f6dc9357SAndroid Build Coastguard Worker if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(), 123*f6dc9357SAndroid Build Coastguard Worker the root function of thread doesn't set 16-byte alignment. 124*f6dc9357SAndroid Build Coastguard Worker And stack frames in all child functions also will be unaligned in that case. 125*f6dc9357SAndroid Build Coastguard Worker 126*f6dc9357SAndroid Build Coastguard Worker Here we set (force_align_arg_pointer) attribute for root function of new thread. 127*f6dc9357SAndroid Build Coastguard Worker Do we need (force_align_arg_pointer) also for another systems? */ 128*f6dc9357SAndroid Build Coastguard Worker 129*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer)) 130*f6dc9357SAndroid Build Coastguard Worker // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions 131*f6dc9357SAndroid Build Coastguard Worker #else 132*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_ATTRIB_ALIGN_ARG 133*f6dc9357SAndroid Build Coastguard Worker #endif 134*f6dc9357SAndroid Build Coastguard Worker 135*f6dc9357SAndroid Build Coastguard Worker #define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE 136*f6dc9357SAndroid Build Coastguard Worker 137*f6dc9357SAndroid Build Coastguard Worker typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); 138*f6dc9357SAndroid Build Coastguard Worker WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); 139*f6dc9357SAndroid Build Coastguard Worker WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity); 140*f6dc9357SAndroid Build Coastguard Worker WRes Thread_Wait_Close(CThread *p); 141*f6dc9357SAndroid Build Coastguard Worker 142*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32 143*f6dc9357SAndroid Build Coastguard Worker #define Thread_Create_With_CpuSet(p, func, param, cs) \ 144*f6dc9357SAndroid Build Coastguard Worker Thread_Create_With_Affinity(p, func, param, *cs) 145*f6dc9357SAndroid Build Coastguard Worker #else 146*f6dc9357SAndroid Build Coastguard Worker WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); 147*f6dc9357SAndroid Build Coastguard Worker #endif 148*f6dc9357SAndroid Build Coastguard Worker 149*f6dc9357SAndroid Build Coastguard Worker 150*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32 151*f6dc9357SAndroid Build Coastguard Worker 152*f6dc9357SAndroid Build Coastguard Worker typedef HANDLE CEvent; 153*f6dc9357SAndroid Build Coastguard Worker typedef CEvent CAutoResetEvent; 154*f6dc9357SAndroid Build Coastguard Worker typedef CEvent CManualResetEvent; 155*f6dc9357SAndroid Build Coastguard Worker #define Event_Construct(p) *(p) = NULL 156*f6dc9357SAndroid Build Coastguard Worker #define Event_IsCreated(p) (*(p) != NULL) 157*f6dc9357SAndroid Build Coastguard Worker #define Event_Close(p) HandlePtr_Close(p) 158*f6dc9357SAndroid Build Coastguard Worker #define Event_Wait(p) Handle_WaitObject(*(p)) 159*f6dc9357SAndroid Build Coastguard Worker WRes Event_Set(CEvent *p); 160*f6dc9357SAndroid Build Coastguard Worker WRes Event_Reset(CEvent *p); 161*f6dc9357SAndroid Build Coastguard Worker WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); 162*f6dc9357SAndroid Build Coastguard Worker WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); 163*f6dc9357SAndroid Build Coastguard Worker WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); 164*f6dc9357SAndroid Build Coastguard Worker WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); 165*f6dc9357SAndroid Build Coastguard Worker 166*f6dc9357SAndroid Build Coastguard Worker typedef HANDLE CSemaphore; 167*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_Construct(p) *(p) = NULL 168*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_IsCreated(p) (*(p) != NULL) 169*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_Close(p) HandlePtr_Close(p) 170*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_Wait(p) Handle_WaitObject(*(p)) 171*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 172*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 173*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); 174*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_Release1(CSemaphore *p); 175*f6dc9357SAndroid Build Coastguard Worker 176*f6dc9357SAndroid Build Coastguard Worker typedef CRITICAL_SECTION CCriticalSection; 177*f6dc9357SAndroid Build Coastguard Worker WRes CriticalSection_Init(CCriticalSection *p); 178*f6dc9357SAndroid Build Coastguard Worker #define CriticalSection_Delete(p) DeleteCriticalSection(p) 179*f6dc9357SAndroid Build Coastguard Worker #define CriticalSection_Enter(p) EnterCriticalSection(p) 180*f6dc9357SAndroid Build Coastguard Worker #define CriticalSection_Leave(p) LeaveCriticalSection(p) 181*f6dc9357SAndroid Build Coastguard Worker 182*f6dc9357SAndroid Build Coastguard Worker 183*f6dc9357SAndroid Build Coastguard Worker #else // _WIN32 184*f6dc9357SAndroid Build Coastguard Worker 185*f6dc9357SAndroid Build Coastguard Worker typedef struct 186*f6dc9357SAndroid Build Coastguard Worker { 187*f6dc9357SAndroid Build Coastguard Worker int _created; 188*f6dc9357SAndroid Build Coastguard Worker int _manual_reset; 189*f6dc9357SAndroid Build Coastguard Worker int _state; 190*f6dc9357SAndroid Build Coastguard Worker pthread_mutex_t _mutex; 191*f6dc9357SAndroid Build Coastguard Worker pthread_cond_t _cond; 192*f6dc9357SAndroid Build Coastguard Worker } CEvent; 193*f6dc9357SAndroid Build Coastguard Worker 194*f6dc9357SAndroid Build Coastguard Worker typedef CEvent CAutoResetEvent; 195*f6dc9357SAndroid Build Coastguard Worker typedef CEvent CManualResetEvent; 196*f6dc9357SAndroid Build Coastguard Worker 197*f6dc9357SAndroid Build Coastguard Worker #define Event_Construct(p) (p)->_created = 0 198*f6dc9357SAndroid Build Coastguard Worker #define Event_IsCreated(p) ((p)->_created) 199*f6dc9357SAndroid Build Coastguard Worker 200*f6dc9357SAndroid Build Coastguard Worker WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); 201*f6dc9357SAndroid Build Coastguard Worker WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); 202*f6dc9357SAndroid Build Coastguard Worker WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); 203*f6dc9357SAndroid Build Coastguard Worker WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); 204*f6dc9357SAndroid Build Coastguard Worker 205*f6dc9357SAndroid Build Coastguard Worker WRes Event_Set(CEvent *p); 206*f6dc9357SAndroid Build Coastguard Worker WRes Event_Reset(CEvent *p); 207*f6dc9357SAndroid Build Coastguard Worker WRes Event_Wait(CEvent *p); 208*f6dc9357SAndroid Build Coastguard Worker WRes Event_Close(CEvent *p); 209*f6dc9357SAndroid Build Coastguard Worker 210*f6dc9357SAndroid Build Coastguard Worker 211*f6dc9357SAndroid Build Coastguard Worker typedef struct 212*f6dc9357SAndroid Build Coastguard Worker { 213*f6dc9357SAndroid Build Coastguard Worker int _created; 214*f6dc9357SAndroid Build Coastguard Worker UInt32 _count; 215*f6dc9357SAndroid Build Coastguard Worker UInt32 _maxCount; 216*f6dc9357SAndroid Build Coastguard Worker pthread_mutex_t _mutex; 217*f6dc9357SAndroid Build Coastguard Worker pthread_cond_t _cond; 218*f6dc9357SAndroid Build Coastguard Worker } CSemaphore; 219*f6dc9357SAndroid Build Coastguard Worker 220*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_Construct(p) (p)->_created = 0 221*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_IsCreated(p) ((p)->_created) 222*f6dc9357SAndroid Build Coastguard Worker 223*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 224*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 225*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); 226*f6dc9357SAndroid Build Coastguard Worker #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) 227*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_Wait(CSemaphore *p); 228*f6dc9357SAndroid Build Coastguard Worker WRes Semaphore_Close(CSemaphore *p); 229*f6dc9357SAndroid Build Coastguard Worker 230*f6dc9357SAndroid Build Coastguard Worker 231*f6dc9357SAndroid Build Coastguard Worker typedef struct 232*f6dc9357SAndroid Build Coastguard Worker { 233*f6dc9357SAndroid Build Coastguard Worker pthread_mutex_t _mutex; 234*f6dc9357SAndroid Build Coastguard Worker } CCriticalSection; 235*f6dc9357SAndroid Build Coastguard Worker 236*f6dc9357SAndroid Build Coastguard Worker WRes CriticalSection_Init(CCriticalSection *p); 237*f6dc9357SAndroid Build Coastguard Worker void CriticalSection_Delete(CCriticalSection *cs); 238*f6dc9357SAndroid Build Coastguard Worker void CriticalSection_Enter(CCriticalSection *cs); 239*f6dc9357SAndroid Build Coastguard Worker void CriticalSection_Leave(CCriticalSection *cs); 240*f6dc9357SAndroid Build Coastguard Worker 241*f6dc9357SAndroid Build Coastguard Worker LONG InterlockedIncrement(LONG volatile *addend); 242*f6dc9357SAndroid Build Coastguard Worker LONG InterlockedDecrement(LONG volatile *addend); 243*f6dc9357SAndroid Build Coastguard Worker 244*f6dc9357SAndroid Build Coastguard Worker #endif // _WIN32 245*f6dc9357SAndroid Build Coastguard Worker 246*f6dc9357SAndroid Build Coastguard Worker WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p); 247*f6dc9357SAndroid Build Coastguard Worker 248*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END 249*f6dc9357SAndroid Build Coastguard Worker 250*f6dc9357SAndroid Build Coastguard Worker #endif 251