diff options
author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2021-12-27 00:00:00 +0000 |
---|---|---|
committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-03-18 15:35:13 +0500 |
commit | f19f813537c7aea1c20749c914e756b54a9c3cf5 (patch) | |
tree | 816ba62ca7c0fa19f2eb46d9e9d6f7dd7c3a744d /C/Threads.h | |
parent | 98e06a519b63b81986abe76d28887f6984a7732b (diff) | |
download | 7zip-21.07.tar.gz 7zip-21.07.tar.bz2 7zip-21.07.zip |
'21.07'21.07
Diffstat (limited to 'C/Threads.h')
-rw-r--r-- | C/Threads.h | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/C/Threads.h b/C/Threads.h new file mode 100644 index 0000000..89ecb92 --- /dev/null +++ b/C/Threads.h | |||
@@ -0,0 +1,232 @@ | |||
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 | ||