Threads.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /* Threads.h -- multithreading library
  2. : Igor Pavlov : Public domain */
  3. #ifndef ZIP7_INC_THREADS_H
  4. #define ZIP7_INC_THREADS_H
  5. #ifdef _WIN32
  6. #include "7zWindows.h"
  7. #else
  8. #include "Compiler.h"
  9. // #define Z7_AFFINITY_DISABLE
  10. #if defined(__linux__)
  11. #if !defined(__APPLE__) && !defined(_AIX) && !defined(__ANDROID__)
  12. #ifndef Z7_AFFINITY_DISABLE
  13. #define Z7_AFFINITY_SUPPORTED
  14. // #pragma message(" ==== Z7_AFFINITY_SUPPORTED")
  15. #if !defined(_GNU_SOURCE)
  16. // #pragma message(" ==== _GNU_SOURCE set")
  17. // we need _GNU_SOURCE for cpu_set_t, if we compile for MUSL
  18. Z7_DIAGNOSTIC_IGNORE_BEGIN_RESERVED_MACRO_IDENTIFIER
  19. #define _GNU_SOURCE
  20. Z7_DIAGNOSTIC_IGNORE_END_RESERVED_MACRO_IDENTIFIER
  21. #endif
  22. #endif
  23. #endif
  24. #endif
  25. #include <pthread.h>
  26. #endif
  27. #include "7zTypes.h"
  28. EXTERN_C_BEGIN
  29. #ifdef _WIN32
  30. WRes HandlePtr_Close(HANDLE *h);
  31. WRes Handle_WaitObject(HANDLE h);
  32. typedef HANDLE CThread;
  33. #define Thread_CONSTRUCT(p) { *(p) = NULL; }
  34. #define Thread_WasCreated(p) (*(p) != NULL)
  35. #define Thread_Close(p) HandlePtr_Close(p)
  36. // #define Thread_Wait(p) Handle_WaitObject(*(p))
  37. #ifdef UNDER_CE
  38. // if (USE_THREADS_CreateThread is defined), we use _beginthreadex()
  39. // if (USE_THREADS_CreateThread is not definned), we use CreateThread()
  40. #define USE_THREADS_CreateThread
  41. #endif
  42. typedef
  43. #ifdef USE_THREADS_CreateThread
  44. DWORD
  45. #else
  46. unsigned
  47. #endif
  48. THREAD_FUNC_RET_TYPE;
  49. #define THREAD_FUNC_RET_ZERO 0
  50. typedef DWORD_PTR CAffinityMask;
  51. typedef DWORD_PTR CCpuSet;
  52. #define CpuSet_Zero(p) *(p) = (0)
  53. #define CpuSet_Set(p, cpu) *(p) |= ((DWORD_PTR)1 << (cpu))
  54. #else // _WIN32
  55. typedef struct
  56. {
  57. pthread_t _tid;
  58. int _created;
  59. } CThread;
  60. #define Thread_CONSTRUCT(p) { (p)->_tid = 0; (p)->_created = 0; }
  61. #define Thread_WasCreated(p) ((p)->_created != 0)
  62. WRes Thread_Close(CThread *p);
  63. // #define Thread_Wait Thread_Wait_Close
  64. typedef void * THREAD_FUNC_RET_TYPE;
  65. #define THREAD_FUNC_RET_ZERO NULL
  66. typedef UInt64 CAffinityMask;
  67. #ifdef Z7_AFFINITY_SUPPORTED
  68. typedef cpu_set_t CCpuSet;
  69. #define CpuSet_Zero(p) CPU_ZERO(p)
  70. #define CpuSet_Set(p, cpu) CPU_SET(cpu, p)
  71. #define CpuSet_IsSet(p, cpu) CPU_ISSET(cpu, p)
  72. #else
  73. typedef UInt64 CCpuSet;
  74. #define CpuSet_Zero(p) *(p) = (0)
  75. #define CpuSet_Set(p, cpu) *(p) |= ((UInt64)1 << (cpu))
  76. #define CpuSet_IsSet(p, cpu) ((*(p) & ((UInt64)1 << (cpu))) != 0)
  77. #endif
  78. #endif // _WIN32
  79. #define THREAD_FUNC_CALL_TYPE Z7_STDCALL
  80. #if defined(_WIN32) && defined(__GNUC__)
  81. /* GCC compiler for x86 32-bit uses the rule:
  82. the stack is 16-byte aligned before CALL instruction for function calling.
  83. But only root function main() contains instructions that
  84. set 16-byte alignment for stack pointer. And another functions
  85. just keep alignment, if it was set in some parent function.
  86. The problem:
  87. if we create new thread in MinGW (GCC) 32-bit x86 via _beginthreadex() or CreateThread(),
  88. the root function of thread doesn't set 16-byte alignment.
  89. And stack frames in all child functions also will be unaligned in that case.
  90. Here we set (force_align_arg_pointer) attribute for root function of new thread.
  91. Do we need (force_align_arg_pointer) also for another systems? */
  92. #define THREAD_FUNC_ATTRIB_ALIGN_ARG __attribute__((force_align_arg_pointer))
  93. // #define THREAD_FUNC_ATTRIB_ALIGN_ARG // for debug : bad alignment in SSE functions
  94. #else
  95. #define THREAD_FUNC_ATTRIB_ALIGN_ARG
  96. #endif
  97. #define THREAD_FUNC_DECL THREAD_FUNC_ATTRIB_ALIGN_ARG THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
  98. typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
  99. WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
  100. WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, CAffinityMask affinity);
  101. WRes Thread_Wait_Close(CThread *p);
  102. #ifdef _WIN32
  103. WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, unsigned group, CAffinityMask affinityMask);
  104. #define Thread_Create_With_CpuSet(p, func, param, cs) \
  105. Thread_Create_With_Affinity(p, func, param, *cs)
  106. #else
  107. WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
  108. #endif
  109. typedef struct
  110. {
  111. unsigned NumGroups;
  112. unsigned NextGroup;
  113. } CThreadNextGroup;
  114. void ThreadNextGroup_Init(CThreadNextGroup *p, unsigned numGroups, unsigned startGroup);
  115. unsigned ThreadNextGroup_GetNext(CThreadNextGroup *p);
  116. #ifdef _WIN32
  117. typedef HANDLE CEvent;
  118. typedef CEvent CAutoResetEvent;
  119. typedef CEvent CManualResetEvent;
  120. #define Event_Construct(p) *(p) = NULL
  121. #define Event_IsCreated(p) (*(p) != NULL)
  122. #define Event_Close(p) HandlePtr_Close(p)
  123. #define Event_Wait(p) Handle_WaitObject(*(p))
  124. WRes Event_Set(CEvent *p);
  125. WRes Event_Reset(CEvent *p);
  126. WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
  127. WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
  128. WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
  129. WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
  130. typedef HANDLE CSemaphore;
  131. #define Semaphore_Construct(p) *(p) = NULL
  132. #define Semaphore_IsCreated(p) (*(p) != NULL)
  133. #define Semaphore_Close(p) HandlePtr_Close(p)
  134. #define Semaphore_Wait(p) Handle_WaitObject(*(p))
  135. WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  136. WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  137. WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
  138. WRes Semaphore_Release1(CSemaphore *p);
  139. typedef CRITICAL_SECTION CCriticalSection;
  140. WRes CriticalSection_Init(CCriticalSection *p);
  141. #define CriticalSection_Delete(p) DeleteCriticalSection(p)
  142. #define CriticalSection_Enter(p) EnterCriticalSection(p)
  143. #define CriticalSection_Leave(p) LeaveCriticalSection(p)
  144. #else // _WIN32
  145. typedef struct
  146. {
  147. int _created;
  148. int _manual_reset;
  149. int _state;
  150. pthread_mutex_t _mutex;
  151. pthread_cond_t _cond;
  152. } CEvent;
  153. typedef CEvent CAutoResetEvent;
  154. typedef CEvent CManualResetEvent;
  155. #define Event_Construct(p) (p)->_created = 0
  156. #define Event_IsCreated(p) ((p)->_created)
  157. WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
  158. WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
  159. WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
  160. WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
  161. WRes Event_Set(CEvent *p);
  162. WRes Event_Reset(CEvent *p);
  163. WRes Event_Wait(CEvent *p);
  164. WRes Event_Close(CEvent *p);
  165. typedef struct
  166. {
  167. int _created;
  168. UInt32 _count;
  169. UInt32 _maxCount;
  170. pthread_mutex_t _mutex;
  171. pthread_cond_t _cond;
  172. } CSemaphore;
  173. #define Semaphore_Construct(p) (p)->_created = 0
  174. #define Semaphore_IsCreated(p) ((p)->_created)
  175. WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  176. WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  177. WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
  178. #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
  179. WRes Semaphore_Wait(CSemaphore *p);
  180. WRes Semaphore_Close(CSemaphore *p);
  181. typedef struct
  182. {
  183. pthread_mutex_t _mutex;
  184. } CCriticalSection;
  185. WRes CriticalSection_Init(CCriticalSection *p);
  186. void CriticalSection_Delete(CCriticalSection *cs);
  187. void CriticalSection_Enter(CCriticalSection *cs);
  188. void CriticalSection_Leave(CCriticalSection *cs);
  189. LONG InterlockedIncrement(LONG volatile *addend);
  190. LONG InterlockedDecrement(LONG volatile *addend);
  191. #endif // _WIN32
  192. WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p);
  193. EXTERN_C_END
  194. #endif