123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- /* Threads.h -- multithreading library
- : Igor Pavlov : Public domain */
- #ifndef ZIP7_INC_THREADS_H
- #define ZIP7_INC_THREADS_H
- #ifdef _WIN32
- #include "7zWindows.h"
- #else
- #include "Compiler.h"
- // #define Z7_AFFINITY_DISABLE
- #if defined(__linux__)
- #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
- #ifndef Z7_AFFINITY_DISABLE
- #define Z7_AFFINITY_SUPPORTED
- // #pragma message(" ==== Z7_AFFINITY_SUPPORTED")
- #if !defined(_GNU_SOURCE)
- // #pragma message(" ==== _GNU_SOURCE set")
- // we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL
- Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
- #define _GNU_SOURCE
- Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
- #endif
- #endif
- #endif
- #endif
- #include <pthread.h>
- #endif
- #include "7zTypes.h"
- EXTERN_C_BEGIN
- #ifdef _WIN32
- WRes HandlePtr_Close(HANDLE *h);
- WRes Handle_WaitObject(HANDLE h);
- typedef HANDLE CThread;
- #define Thread_CONSTRUCT(p) { *(p) = NULL; }
- #define Thread_WasCreated(p) (*(p) != NULL)
- #define Thread_Close(p) HandlePtr_Close(p)
- // #define Thread_Wait(p) Handle_WaitObject(*(p))
- #ifdef UNDER_CE
- // if (USE_THREADS_CreateThread is defined), we use _beginthreadex()
- // if (USE_THREADS_CreateThread is not definned), we use CreateThread()
- #define USE_THREADS_CreateThread
- #endif
- typedef
- #ifdef USE_THREADS_CreateThread
- DWORD
- #else
- unsigned
- #endif
- THREAD_FUNC_RET_TYPE;
- #define THREAD_FUNC_RET_ZERO 0
- typedef DWORD_PTR CAffinityMask;
- typedef DWORD_PTR CCpuSet;
- #define CpuSet_Zero(p) *(p) = (0)
- #define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu))
- #else // _WIN32
- typedef struct
- {
- pthread_t _tid;
- int _created;
- } CThread;
- #define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; }
- #define Thread_WasCreated(p) ((p)->_created != 0)
- WRes Thread_Close(CThread *p);
- // #define Thread_Wait Thread_Wait_Close
- typedef void * THREAD_FUNC_RET_TYPE;
- #define THREAD_FUNC_RET_ZERO NULL
- typedef UInt64 CAffinityMask;
- #ifdef Z7_AFFINITY_SUPPORTED
- typedef cpu_set_t CCpuSet;
- #define CpuSet_Zero(p) CPU_ZERO(p)
- #define CpuSet_Set(p, cpu) CPU_SET(cpu, p)
- #define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p)
- #else
- typedef UInt64 CCpuSet;
- #define CpuSet_Zero(p) *(p) = (0)
- #define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu))
- #define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0)
- #endif
- #endif // _WIN32
- #define THREAD_FUNC_CALL_TYPE Z7_STDCALL
- #if defined(_WIN32) && defined(__GNUC__)
- /* GCC compiler for x86 32-bit uses the rule:
- the stack is 16-byte aligned before CALL instruction for function calling.
- But only root function main() contains instructions that
- set 16-byte alignment for stack pointer. And another functions
- just keep alignment, if it was set in some parent function.
-
- The problem:
- if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),
- the root function of thread doesn't set 16-byte alignment.
- And stack frames in all child functions also will be unaligned in that case.
-
- Here we set (force_align_arg_pointer) attribute for root function of new thread.
- Do we need (force_align_arg_pointer) also for another systems? */
-
- #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))
- // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions
- #else
- #define THREAD_FUNC_ATTRIB_ALIGN_ARG
- #endif
- #define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
- typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
- WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
- WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
- WRes Thread_Wait_Close(CThread *p);
- #ifdef _WIN32
- WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask);
- #define Thread_Create_With_CpuSet(p, func, param, cs) \
- Thread_Create_With_Affinity(p, func, param, *cs)
- #else
- WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
- #endif
- typedef struct
- {
- unsigned NumGroups;
- unsigned NextGroup;
- } CThreadNextGroup;
- void ThreadNextGroup_Init(CThreadNextGroup *p, unsigned numGroups, unsigned startGroup);
- unsigned ThreadNextGroup_GetNext(CThreadNextGroup *p);
- #ifdef _WIN32
- typedef HANDLE CEvent;
- typedef CEvent CAutoResetEvent;
- typedef CEvent CManualResetEvent;
- #define Event_Construct(p) *(p) = NULL
- #define Event_IsCreated(p) (*(p) != NULL)
- #define Event_Close(p) HandlePtr_Close(p)
- #define Event_Wait(p) Handle_WaitObject(*(p))
- WRes Event_Set(CEvent *p);
- WRes Event_Reset(CEvent *p);
- WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
- WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
- WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
- WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
- typedef HANDLE CSemaphore;
- #define Semaphore_Construct(p) *(p) = NULL
- #define Semaphore_IsCreated(p) (*(p) != NULL)
- #define Semaphore_Close(p) HandlePtr_Close(p)
- #define Semaphore_Wait(p) Handle_WaitObject(*(p))
- WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
- WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
- WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
- WRes Semaphore_Release1(CSemaphore *p);
- typedef CRITICAL_SECTION CCriticalSection;
- WRes CriticalSection_Init(CCriticalSection *p);
- #define CriticalSection_Delete(p) DeleteCriticalSection(p)
- #define CriticalSection_Enter(p) EnterCriticalSection(p)
- #define CriticalSection_Leave(p) LeaveCriticalSection(p)
- #else // _WIN32
- typedef struct
- {
- int _created;
- int _manual_reset;
- int _state;
- pthread_mutex_t _mutex;
- pthread_cond_t _cond;
- } CEvent;
- typedef CEvent CAutoResetEvent;
- typedef CEvent CManualResetEvent;
- #define Event_Construct(p) (p)->_created = 0
- #define Event_IsCreated(p) ((p)->_created)
- WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
- WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
- WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
- WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
- WRes Event_Set(CEvent *p);
- WRes Event_Reset(CEvent *p);
- WRes Event_Wait(CEvent *p);
- WRes Event_Close(CEvent *p);
- typedef struct
- {
- int _created;
- UInt32 _count;
- UInt32 _maxCount;
- pthread_mutex_t _mutex;
- pthread_cond_t _cond;
- } CSemaphore;
- #define Semaphore_Construct(p) (p)->_created = 0
- #define Semaphore_IsCreated(p) ((p)->_created)
- WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
- WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
- WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
- #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
- WRes Semaphore_Wait(CSemaphore *p);
- WRes Semaphore_Close(CSemaphore *p);
- typedef struct
- {
- pthread_mutex_t _mutex;
- } CCriticalSection;
- WRes CriticalSection_Init(CCriticalSection *p);
- void CriticalSection_Delete(CCriticalSection *cs);
- void CriticalSection_Enter(CCriticalSection *cs);
- void CriticalSection_Leave(CCriticalSection *cs);
- LONG InterlockedIncrement(LONG volatile *addend);
- LONG InterlockedDecrement(LONG volatile *addend);
- #endif // _WIN32
- WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p);
- EXTERN_C_END
- #endif
|