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