1370b324cSopenharmony_ci/* Threads.h -- multithreading library 2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci#ifndef ZIP7_INC_THREADS_H 5370b324cSopenharmony_ci#define ZIP7_INC_THREADS_H 6370b324cSopenharmony_ci 7370b324cSopenharmony_ci#ifdef _WIN32 8370b324cSopenharmony_ci#include "7zWindows.h" 9370b324cSopenharmony_ci 10370b324cSopenharmony_ci#else 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#if defined(__linux__) 13370b324cSopenharmony_ci#if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__) 14370b324cSopenharmony_ci#ifndef Z7_AFFINITY_DISABLE 15370b324cSopenharmony_ci#define Z7_AFFINITY_SUPPORTED 16370b324cSopenharmony_ci// #pragma message(" ==== Z7_AFFINITY_SUPPORTED") 17370b324cSopenharmony_ci// #define _GNU_SOURCE 18370b324cSopenharmony_ci#endif 19370b324cSopenharmony_ci#endif 20370b324cSopenharmony_ci#endif 21370b324cSopenharmony_ci 22370b324cSopenharmony_ci#include <pthread.h> 23370b324cSopenharmony_ci 24370b324cSopenharmony_ci#endif 25370b324cSopenharmony_ci 26370b324cSopenharmony_ci#include "7zTypes.h" 27370b324cSopenharmony_ci 28370b324cSopenharmony_ciEXTERN_C_BEGIN 29370b324cSopenharmony_ci 30370b324cSopenharmony_ci#ifdef _WIN32 31370b324cSopenharmony_ci 32370b324cSopenharmony_ciWRes HandlePtr_Close(HANDLE *h); 33370b324cSopenharmony_ciWRes Handle_WaitObject(HANDLE h); 34370b324cSopenharmony_ci 35370b324cSopenharmony_citypedef HANDLE CThread; 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci#define Thread_CONSTRUCT(p) { *(p) = NULL; } 38370b324cSopenharmony_ci#define Thread_WasCreated(p) (*(p) != NULL) 39370b324cSopenharmony_ci#define Thread_Close(p) HandlePtr_Close(p) 40370b324cSopenharmony_ci// #define Thread_Wait(p) Handle_WaitObject(*(p)) 41370b324cSopenharmony_ci 42370b324cSopenharmony_ci#ifdef UNDER_CE 43370b324cSopenharmony_ci // if (USE_THREADS_CreateThread is defined), we use _beginthreadex() 44370b324cSopenharmony_ci // if (USE_THREADS_CreateThread is not definned), we use CreateThread() 45370b324cSopenharmony_ci #define USE_THREADS_CreateThread 46370b324cSopenharmony_ci#endif 47370b324cSopenharmony_ci 48370b324cSopenharmony_citypedef 49370b324cSopenharmony_ci #ifdef USE_THREADS_CreateThread 50370b324cSopenharmony_ci DWORD 51370b324cSopenharmony_ci #else 52370b324cSopenharmony_ci unsigned 53370b324cSopenharmony_ci #endif 54370b324cSopenharmony_ci THREAD_FUNC_RET_TYPE; 55370b324cSopenharmony_ci 56370b324cSopenharmony_ci#define THREAD_FUNC_RET_ZERO 0 57370b324cSopenharmony_ci 58370b324cSopenharmony_citypedef DWORD_PTR CAffinityMask; 59370b324cSopenharmony_citypedef DWORD_PTR CCpuSet; 60370b324cSopenharmony_ci 61370b324cSopenharmony_ci#define CpuSet_Zero(p) *(p) = (0) 62370b324cSopenharmony_ci#define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu)) 63370b324cSopenharmony_ci 64370b324cSopenharmony_ci#else // _WIN32 65370b324cSopenharmony_ci 66370b324cSopenharmony_citypedef struct 67370b324cSopenharmony_ci{ 68370b324cSopenharmony_ci pthread_t _tid; 69370b324cSopenharmony_ci int _created; 70370b324cSopenharmony_ci} CThread; 71370b324cSopenharmony_ci 72370b324cSopenharmony_ci#define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; } 73370b324cSopenharmony_ci#define Thread_WasCreated(p) ((p)->_created != 0) 74370b324cSopenharmony_ciWRes Thread_Close(CThread *p); 75370b324cSopenharmony_ci// #define Thread_Wait Thread_Wait_Close 76370b324cSopenharmony_ci 77370b324cSopenharmony_citypedef void * THREAD_FUNC_RET_TYPE; 78370b324cSopenharmony_ci#define THREAD_FUNC_RET_ZERO NULL 79370b324cSopenharmony_ci 80370b324cSopenharmony_ci 81370b324cSopenharmony_citypedef UInt64 CAffinityMask; 82370b324cSopenharmony_ci 83370b324cSopenharmony_ci#ifdef Z7_AFFINITY_SUPPORTED 84370b324cSopenharmony_ci 85370b324cSopenharmony_citypedef cpu_set_t CCpuSet; 86370b324cSopenharmony_ci#define CpuSet_Zero(p) CPU_ZERO(p) 87370b324cSopenharmony_ci#define CpuSet_Set(p, cpu) CPU_SET(cpu, p) 88370b324cSopenharmony_ci#define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p) 89370b324cSopenharmony_ci 90370b324cSopenharmony_ci#else 91370b324cSopenharmony_ci 92370b324cSopenharmony_citypedef UInt64 CCpuSet; 93370b324cSopenharmony_ci#define CpuSet_Zero(p) *(p) = (0) 94370b324cSopenharmony_ci#define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu)) 95370b324cSopenharmony_ci#define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0) 96370b324cSopenharmony_ci 97370b324cSopenharmony_ci#endif 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci 100370b324cSopenharmony_ci#endif // _WIN32 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci 103370b324cSopenharmony_ci#define THREAD_FUNC_CALL_TYPE Z7_STDCALL 104370b324cSopenharmony_ci 105370b324cSopenharmony_ci#if defined(_WIN32) && defined(__GNUC__) 106370b324cSopenharmony_ci/* GCC compiler for x86 32-bit uses the rule: 107370b324cSopenharmony_ci the stack is 16-byte aligned before CALL instruction for function calling. 108370b324cSopenharmony_ci But only root function main() contains instructions that 109370b324cSopenharmony_ci set 16-byte alignment for stack pointer. And another functions 110370b324cSopenharmony_ci just keep alignment, if it was set in some parent function. 111370b324cSopenharmony_ci 112370b324cSopenharmony_ci The problem: 113370b324cSopenharmony_ci if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(), 114370b324cSopenharmony_ci the root function of thread doesn't set 16-byte alignment. 115370b324cSopenharmony_ci And stack frames in all child functions also will be unaligned in that case. 116370b324cSopenharmony_ci 117370b324cSopenharmony_ci Here we set (force_align_arg_pointer) attribute for root function of new thread. 118370b324cSopenharmony_ci Do we need (force_align_arg_pointer) also for another systems? */ 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer)) 121370b324cSopenharmony_ci // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions 122370b324cSopenharmony_ci#else 123370b324cSopenharmony_ci #define THREAD_FUNC_ATTRIB_ALIGN_ARG 124370b324cSopenharmony_ci#endif 125370b324cSopenharmony_ci 126370b324cSopenharmony_ci#define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE 127370b324cSopenharmony_ci 128370b324cSopenharmony_citypedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); 129370b324cSopenharmony_ciWRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); 130370b324cSopenharmony_ciWRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity); 131370b324cSopenharmony_ciWRes Thread_Wait_Close(CThread *p); 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci#ifdef _WIN32 134370b324cSopenharmony_ci#define Thread_Create_With_CpuSet(p, func, param, cs) \ 135370b324cSopenharmony_ci Thread_Create_With_Affinity(p, func, param, *cs) 136370b324cSopenharmony_ci#else 137370b324cSopenharmony_ciWRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet); 138370b324cSopenharmony_ci#endif 139370b324cSopenharmony_ci 140370b324cSopenharmony_ci 141370b324cSopenharmony_ci#ifdef _WIN32 142370b324cSopenharmony_ci 143370b324cSopenharmony_citypedef HANDLE CEvent; 144370b324cSopenharmony_citypedef CEvent CAutoResetEvent; 145370b324cSopenharmony_citypedef CEvent CManualResetEvent; 146370b324cSopenharmony_ci#define Event_Construct(p) *(p) = NULL 147370b324cSopenharmony_ci#define Event_IsCreated(p) (*(p) != NULL) 148370b324cSopenharmony_ci#define Event_Close(p) HandlePtr_Close(p) 149370b324cSopenharmony_ci#define Event_Wait(p) Handle_WaitObject(*(p)) 150370b324cSopenharmony_ciWRes Event_Set(CEvent *p); 151370b324cSopenharmony_ciWRes Event_Reset(CEvent *p); 152370b324cSopenharmony_ciWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); 153370b324cSopenharmony_ciWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); 154370b324cSopenharmony_ciWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); 155370b324cSopenharmony_ciWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); 156370b324cSopenharmony_ci 157370b324cSopenharmony_citypedef HANDLE CSemaphore; 158370b324cSopenharmony_ci#define Semaphore_Construct(p) *(p) = NULL 159370b324cSopenharmony_ci#define Semaphore_IsCreated(p) (*(p) != NULL) 160370b324cSopenharmony_ci#define Semaphore_Close(p) HandlePtr_Close(p) 161370b324cSopenharmony_ci#define Semaphore_Wait(p) Handle_WaitObject(*(p)) 162370b324cSopenharmony_ciWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 163370b324cSopenharmony_ciWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 164370b324cSopenharmony_ciWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); 165370b324cSopenharmony_ciWRes Semaphore_Release1(CSemaphore *p); 166370b324cSopenharmony_ci 167370b324cSopenharmony_citypedef CRITICAL_SECTION CCriticalSection; 168370b324cSopenharmony_ciWRes CriticalSection_Init(CCriticalSection *p); 169370b324cSopenharmony_ci#define CriticalSection_Delete(p) DeleteCriticalSection(p) 170370b324cSopenharmony_ci#define CriticalSection_Enter(p) EnterCriticalSection(p) 171370b324cSopenharmony_ci#define CriticalSection_Leave(p) LeaveCriticalSection(p) 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci 174370b324cSopenharmony_ci#else // _WIN32 175370b324cSopenharmony_ci 176370b324cSopenharmony_citypedef struct _CEvent 177370b324cSopenharmony_ci{ 178370b324cSopenharmony_ci int _created; 179370b324cSopenharmony_ci int _manual_reset; 180370b324cSopenharmony_ci int _state; 181370b324cSopenharmony_ci pthread_mutex_t _mutex; 182370b324cSopenharmony_ci pthread_cond_t _cond; 183370b324cSopenharmony_ci} CEvent; 184370b324cSopenharmony_ci 185370b324cSopenharmony_citypedef CEvent CAutoResetEvent; 186370b324cSopenharmony_citypedef CEvent CManualResetEvent; 187370b324cSopenharmony_ci 188370b324cSopenharmony_ci#define Event_Construct(p) (p)->_created = 0 189370b324cSopenharmony_ci#define Event_IsCreated(p) ((p)->_created) 190370b324cSopenharmony_ci 191370b324cSopenharmony_ciWRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); 192370b324cSopenharmony_ciWRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); 193370b324cSopenharmony_ciWRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); 194370b324cSopenharmony_ciWRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); 195370b324cSopenharmony_ci 196370b324cSopenharmony_ciWRes Event_Set(CEvent *p); 197370b324cSopenharmony_ciWRes Event_Reset(CEvent *p); 198370b324cSopenharmony_ciWRes Event_Wait(CEvent *p); 199370b324cSopenharmony_ciWRes Event_Close(CEvent *p); 200370b324cSopenharmony_ci 201370b324cSopenharmony_ci 202370b324cSopenharmony_citypedef struct _CSemaphore 203370b324cSopenharmony_ci{ 204370b324cSopenharmony_ci int _created; 205370b324cSopenharmony_ci UInt32 _count; 206370b324cSopenharmony_ci UInt32 _maxCount; 207370b324cSopenharmony_ci pthread_mutex_t _mutex; 208370b324cSopenharmony_ci pthread_cond_t _cond; 209370b324cSopenharmony_ci} CSemaphore; 210370b324cSopenharmony_ci 211370b324cSopenharmony_ci#define Semaphore_Construct(p) (p)->_created = 0 212370b324cSopenharmony_ci#define Semaphore_IsCreated(p) ((p)->_created) 213370b324cSopenharmony_ci 214370b324cSopenharmony_ciWRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 215370b324cSopenharmony_ciWRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount); 216370b324cSopenharmony_ciWRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); 217370b324cSopenharmony_ci#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1) 218370b324cSopenharmony_ciWRes Semaphore_Wait(CSemaphore *p); 219370b324cSopenharmony_ciWRes Semaphore_Close(CSemaphore *p); 220370b324cSopenharmony_ci 221370b324cSopenharmony_ci 222370b324cSopenharmony_citypedef struct _CCriticalSection 223370b324cSopenharmony_ci{ 224370b324cSopenharmony_ci pthread_mutex_t _mutex; 225370b324cSopenharmony_ci} CCriticalSection; 226370b324cSopenharmony_ci 227370b324cSopenharmony_ciWRes CriticalSection_Init(CCriticalSection *p); 228370b324cSopenharmony_civoid CriticalSection_Delete(CCriticalSection *cs); 229370b324cSopenharmony_civoid CriticalSection_Enter(CCriticalSection *cs); 230370b324cSopenharmony_civoid CriticalSection_Leave(CCriticalSection *cs); 231370b324cSopenharmony_ci 232370b324cSopenharmony_ciLONG InterlockedIncrement(LONG volatile *addend); 233370b324cSopenharmony_ci 234370b324cSopenharmony_ci#endif // _WIN32 235370b324cSopenharmony_ci 236370b324cSopenharmony_ciWRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p); 237370b324cSopenharmony_ci 238370b324cSopenharmony_ciEXTERN_C_END 239370b324cSopenharmony_ci 240370b324cSopenharmony_ci#endif 241