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