1 /* Threads.h -- multithreading library
\r
2 2021-12-21 : Igor Pavlov : Public domain */
\r
4 #ifndef __7Z_THREADS_H
\r
5 #define __7Z_THREADS_H
\r
11 #if defined(__linux__)
\r
12 #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
\r
13 #ifndef _7ZIP_AFFINITY_DISABLE
\r
14 #define _7ZIP_AFFINITY_SUPPORTED
\r
15 // #pragma message(" ==== _7ZIP_AFFINITY_SUPPORTED")
\r
16 // #define _GNU_SOURCE
\r
21 #include <pthread.h>
\r
25 #include "7zTypes.h"
\r
31 WRes HandlePtr_Close(HANDLE *h);
\r
32 WRes Handle_WaitObject(HANDLE h);
\r
34 typedef HANDLE CThread;
\r
36 #define Thread_Construct(p) { *(p) = NULL; }
\r
37 #define Thread_WasCreated(p) (*(p) != NULL)
\r
38 #define Thread_Close(p) HandlePtr_Close(p)
\r
39 // #define Thread_Wait(p) Handle_WaitObject(*(p))
\r
42 // if (USE_THREADS_CreateThread is defined), we use _beginthreadex()
\r
43 // if (USE_THREADS_CreateThread is not definned), we use CreateThread()
\r
44 #define USE_THREADS_CreateThread
\r
48 #ifdef USE_THREADS_CreateThread
\r
53 THREAD_FUNC_RET_TYPE;
\r
55 typedef DWORD_PTR CAffinityMask;
\r
56 typedef DWORD_PTR CCpuSet;
\r
58 #define CpuSet_Zero(p) { *(p) = 0; }
\r
59 #define CpuSet_Set(p, cpu) { *(p) |= ((DWORD_PTR)1 << (cpu)); }
\r
63 typedef struct _CThread
\r
69 #define Thread_Construct(p) { (p)->_tid = 0; (p)->_created = 0; }
\r
70 #define Thread_WasCreated(p) ((p)->_created != 0)
\r
71 WRes Thread_Close(CThread *p);
\r
72 // #define Thread_Wait Thread_Wait_Close
\r
74 typedef void * THREAD_FUNC_RET_TYPE;
\r
76 typedef UInt64 CAffinityMask;
\r
78 #ifdef _7ZIP_AFFINITY_SUPPORTED
\r
80 typedef cpu_set_t CCpuSet;
\r
81 #define CpuSet_Zero(p) CPU_ZERO(p)
\r
82 #define CpuSet_Set(p, cpu) CPU_SET(cpu, p)
\r
83 #define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p)
\r
87 typedef UInt64 CCpuSet;
\r
88 #define CpuSet_Zero(p) { *(p) = 0; }
\r
89 #define CpuSet_Set(p, cpu) { *(p) |= ((UInt64)1 << (cpu)); }
\r
90 #define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0)
\r
98 #define THREAD_FUNC_CALL_TYPE MY_STD_CALL
\r
100 #if defined(_WIN32) && defined(__GNUC__)
\r
101 /* GCC compiler for x86 32-bit uses the rule:
\r
102 the stack is 16-byte aligned before CALL instruction for function calling.
\r
103 But only root function main() contains instructions that
\r
104 set 16-byte alignment for stack pointer. And another functions
\r
105 just keep alignment, if it was set in some parent function.
\r
108 if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),
\r
109 the root function of thread doesn't set 16-byte alignment.
\r
110 And stack frames in all child functions also will be unaligned in that case.
\r
112 Here we set (force_align_arg_pointer) attribute for root function of new thread.
\r
113 Do we need (force_align_arg_pointer) also for another systems? */
\r
115 #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))
\r
116 // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions
\r
118 #define THREAD_FUNC_ATTRIB_ALIGN_ARG
\r
121 #define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
\r
123 typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
\r
124 WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
\r
125 WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
\r
126 WRes Thread_Wait_Close(CThread *p);
\r
129 #define Thread_Create_With_CpuSet(p, func, param, cs) \
\r
130 Thread_Create_With_Affinity(p, func, param, *cs)
\r
132 WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
\r
138 typedef HANDLE CEvent;
\r
139 typedef CEvent CAutoResetEvent;
\r
140 typedef CEvent CManualResetEvent;
\r
141 #define Event_Construct(p) *(p) = NULL
\r
142 #define Event_IsCreated(p) (*(p) != NULL)
\r
143 #define Event_Close(p) HandlePtr_Close(p)
\r
144 #define Event_Wait(p) Handle_WaitObject(*(p))
\r
145 WRes Event_Set(CEvent *p);
\r
146 WRes Event_Reset(CEvent *p);
\r
147 WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
\r
148 WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
\r
149 WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
\r
150 WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
\r
152 typedef HANDLE CSemaphore;
\r
153 #define Semaphore_Construct(p) *(p) = NULL
\r
154 #define Semaphore_IsCreated(p) (*(p) != NULL)
\r
155 #define Semaphore_Close(p) HandlePtr_Close(p)
\r
156 #define Semaphore_Wait(p) Handle_WaitObject(*(p))
\r
157 WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
\r
158 WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
\r
159 WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
\r
160 WRes Semaphore_Release1(CSemaphore *p);
\r
162 typedef CRITICAL_SECTION CCriticalSection;
\r
163 WRes CriticalSection_Init(CCriticalSection *p);
\r
164 #define CriticalSection_Delete(p) DeleteCriticalSection(p)
\r
165 #define CriticalSection_Enter(p) EnterCriticalSection(p)
\r
166 #define CriticalSection_Leave(p) LeaveCriticalSection(p)
\r
171 typedef struct _CEvent
\r
176 pthread_mutex_t _mutex;
\r
177 pthread_cond_t _cond;
\r
180 typedef CEvent CAutoResetEvent;
\r
181 typedef CEvent CManualResetEvent;
\r
183 #define Event_Construct(p) (p)->_created = 0
\r
184 #define Event_IsCreated(p) ((p)->_created)
\r
186 WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
\r
187 WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
\r
188 WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
\r
189 WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
\r
190 WRes Event_Set(CEvent *p);
\r
191 WRes Event_Reset(CEvent *p);
\r
192 WRes Event_Wait(CEvent *p);
\r
193 WRes Event_Close(CEvent *p);
\r
196 typedef struct _CSemaphore
\r
201 pthread_mutex_t _mutex;
\r
202 pthread_cond_t _cond;
\r
205 #define Semaphore_Construct(p) (p)->_created = 0
\r
206 #define Semaphore_IsCreated(p) ((p)->_created)
\r
208 WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
\r
209 WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
\r
210 WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
\r
211 #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
\r
212 WRes Semaphore_Wait(CSemaphore *p);
\r
213 WRes Semaphore_Close(CSemaphore *p);
\r
216 typedef struct _CCriticalSection
\r
218 pthread_mutex_t _mutex;
\r
219 } CCriticalSection;
\r
221 WRes CriticalSection_Init(CCriticalSection *p);
\r
222 void CriticalSection_Delete(CCriticalSection *cs);
\r
223 void CriticalSection_Enter(CCriticalSection *cs);
\r
224 void CriticalSection_Leave(CCriticalSection *cs);
\r
226 LONG InterlockedIncrement(LONG volatile *addend);
\r