aboutsummaryrefslogtreecommitdiff
path: root/C/Threads.h
diff options
context:
space:
mode:
Diffstat (limited to 'C/Threads.h')
-rw-r--r--C/Threads.h232
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
22021-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
27EXTERN_C_BEGIN
28
29#ifdef _WIN32
30
31WRes HandlePtr_Close(HANDLE *h);
32WRes Handle_WaitObject(HANDLE h);
33
34typedef 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
47typedef
48 #ifdef USE_THREADS_CreateThread
49 DWORD
50 #else
51 unsigned
52 #endif
53 THREAD_FUNC_RET_TYPE;
54
55typedef DWORD_PTR CAffinityMask;
56typedef 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
63typedef 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)
71WRes Thread_Close(CThread *p);
72// #define Thread_Wait Thread_Wait_Close
73
74typedef void * THREAD_FUNC_RET_TYPE;
75
76typedef UInt64 CAffinityMask;
77
78#ifdef _7ZIP_AFFINITY_SUPPORTED
79
80typedef 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
87typedef 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
123typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
124WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
125WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
126WRes 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
132WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
133#endif
134
135
136#ifdef _WIN32
137
138typedef HANDLE CEvent;
139typedef CEvent CAutoResetEvent;
140typedef 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))
145WRes Event_Set(CEvent *p);
146WRes Event_Reset(CEvent *p);
147WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
148WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
149WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
150WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
151
152typedef 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))
157WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
158WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
159WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
160WRes Semaphore_Release1(CSemaphore *p);
161
162typedef CRITICAL_SECTION CCriticalSection;
163WRes 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
171typedef 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
180typedef CEvent CAutoResetEvent;
181typedef CEvent CManualResetEvent;
182
183#define Event_Construct(p) (p)->_created = 0
184#define Event_IsCreated(p) ((p)->_created)
185
186WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
187WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
188WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
189WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
190WRes Event_Set(CEvent *p);
191WRes Event_Reset(CEvent *p);
192WRes Event_Wait(CEvent *p);
193WRes Event_Close(CEvent *p);
194
195
196typedef 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
208WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
209WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
210WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
211#define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
212WRes Semaphore_Wait(CSemaphore *p);
213WRes Semaphore_Close(CSemaphore *p);
214
215
216typedef struct _CCriticalSection
217{
218 pthread_mutex_t _mutex;
219} CCriticalSection;
220
221WRes CriticalSection_Init(CCriticalSection *p);
222void CriticalSection_Delete(CCriticalSection *cs);
223void CriticalSection_Enter(CCriticalSection *cs);
224void CriticalSection_Leave(CCriticalSection *cs);
225
226LONG InterlockedIncrement(LONG volatile *addend);
227
228#endif // _WIN32
229
230EXTERN_C_END
231
232#endif