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