• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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