Threads.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /* Threads.h -- multithreading library
  2. 2024-03-28 : 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. #define Thread_Create_With_CpuSet(p, func, param, cs) \
  104. Thread_Create_With_Affinity(p, func, param, *cs)
  105. #else
  106. WRes Thread_Create_With_CpuSet(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, const CCpuSet *cpuSet);
  107. #endif
  108. #ifdef _WIN32
  109. typedef HANDLE CEvent;
  110. typedef CEvent CAutoResetEvent;
  111. typedef CEvent CManualResetEvent;
  112. #define Event_Construct(p) *(p) = NULL
  113. #define Event_IsCreated(p) (*(p) != NULL)
  114. #define Event_Close(p) HandlePtr_Close(p)
  115. #define Event_Wait(p) Handle_WaitObject(*(p))
  116. WRes Event_Set(CEvent *p);
  117. WRes Event_Reset(CEvent *p);
  118. WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
  119. WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
  120. WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
  121. WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
  122. typedef HANDLE CSemaphore;
  123. #define Semaphore_Construct(p) *(p) = NULL
  124. #define Semaphore_IsCreated(p) (*(p) != NULL)
  125. #define Semaphore_Close(p) HandlePtr_Close(p)
  126. #define Semaphore_Wait(p) Handle_WaitObject(*(p))
  127. WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  128. WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  129. WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
  130. WRes Semaphore_Release1(CSemaphore *p);
  131. typedef CRITICAL_SECTION CCriticalSection;
  132. WRes CriticalSection_Init(CCriticalSection *p);
  133. #define CriticalSection_Delete(p) DeleteCriticalSection(p)
  134. #define CriticalSection_Enter(p) EnterCriticalSection(p)
  135. #define CriticalSection_Leave(p) LeaveCriticalSection(p)
  136. #else // _WIN32
  137. typedef struct
  138. {
  139. int _created;
  140. int _manual_reset;
  141. int _state;
  142. pthread_mutex_t _mutex;
  143. pthread_cond_t _cond;
  144. } CEvent;
  145. typedef CEvent CAutoResetEvent;
  146. typedef CEvent CManualResetEvent;
  147. #define Event_Construct(p) (p)->_created = 0
  148. #define Event_IsCreated(p) ((p)->_created)
  149. WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
  150. WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
  151. WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
  152. WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
  153. WRes Event_Set(CEvent *p);
  154. WRes Event_Reset(CEvent *p);
  155. WRes Event_Wait(CEvent *p);
  156. WRes Event_Close(CEvent *p);
  157. typedef struct
  158. {
  159. int _created;
  160. UInt32 _count;
  161. UInt32 _maxCount;
  162. pthread_mutex_t _mutex;
  163. pthread_cond_t _cond;
  164. } CSemaphore;
  165. #define Semaphore_Construct(p) (p)->_created = 0
  166. #define Semaphore_IsCreated(p) ((p)->_created)
  167. WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  168. WRes Semaphore_OptCreateInit(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
  169. WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
  170. #define Semaphore_Release1(p) Semaphore_ReleaseN(p, 1)
  171. WRes Semaphore_Wait(CSemaphore *p);
  172. WRes Semaphore_Close(CSemaphore *p);
  173. typedef struct
  174. {
  175. pthread_mutex_t _mutex;
  176. } CCriticalSection;
  177. WRes CriticalSection_Init(CCriticalSection *p);
  178. void CriticalSection_Delete(CCriticalSection *cs);
  179. void CriticalSection_Enter(CCriticalSection *cs);
  180. void CriticalSection_Leave(CCriticalSection *cs);
  181. LONG InterlockedIncrement(LONG volatile *addend);
  182. LONG InterlockedDecrement(LONG volatile *addend);
  183. #endif // _WIN32
  184. WRes AutoResetEvent_OptCreate_And_Reset(CAutoResetEvent *p);
  185. EXTERN_C_END
  186. #endif