Coverage Report

Created: 2025-04-11 06:56

/src/unrar/threadmisc.cpp
Line
Count
Source (jump to first uncovered line)
1
static inline bool CriticalSectionCreate(CRITSECT_HANDLE *CritSection)
2
13.0k
{
3
#ifdef _WIN_ALL
4
  InitializeCriticalSection(CritSection);
5
  return true;
6
#elif defined(_UNIX)
7
  return pthread_mutex_init(CritSection,NULL)==0;
8
13.0k
#endif
9
13.0k
}
10
11
12
static inline void CriticalSectionDelete(CRITSECT_HANDLE *CritSection)
13
13.0k
{
14
#ifdef _WIN_ALL
15
  DeleteCriticalSection(CritSection);
16
#elif defined(_UNIX)
17
  pthread_mutex_destroy(CritSection);
18
13.0k
#endif
19
13.0k
}
20
21
22
static inline void CriticalSectionStart(CRITSECT_HANDLE *CritSection)
23
841k
{
24
#ifdef _WIN_ALL
25
  EnterCriticalSection(CritSection);
26
#elif defined(_UNIX)
27
  pthread_mutex_lock(CritSection);
28
841k
#endif
29
841k
}
30
31
32
static inline void CriticalSectionEnd(CRITSECT_HANDLE *CritSection)
33
846k
{
34
#ifdef _WIN_ALL
35
  LeaveCriticalSection(CritSection);
36
#elif defined(_UNIX)
37
  pthread_mutex_unlock(CritSection);
38
846k
#endif
39
846k
}
40
41
42
static THREAD_HANDLE ThreadCreate(NATIVE_THREAD_PTR Proc,void *Data)
43
7.74k
{
44
7.74k
#ifdef _UNIX
45
/*
46
  pthread_attr_t attr;
47
  pthread_attr_init(&attr);
48
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
49
*/
50
7.74k
  pthread_t pt;
51
7.74k
  int Code=pthread_create(&pt,NULL/*&attr*/,Proc,Data);
52
7.74k
  if (Code!=0)
53
0
  {
54
0
    wchar Msg[100];
55
0
    swprintf(Msg,ASIZE(Msg),L"\npthread_create failed, code %d\n",Code);
56
0
    ErrHandler.GeneralErrMsg(Msg);
57
0
    ErrHandler.SysErrMsg();
58
0
    ErrHandler.Exit(RARX_FATAL);
59
0
  }
60
7.74k
  return pt;
61
#else
62
  DWORD ThreadId;
63
  HANDLE hThread=CreateThread(NULL,0x10000,Proc,Data,0,&ThreadId);
64
  if (hThread==NULL)
65
  {
66
    ErrHandler.GeneralErrMsg(L"CreateThread failed");
67
    ErrHandler.SysErrMsg();
68
    ErrHandler.Exit(RARX_FATAL);
69
  }
70
  return hThread;
71
#endif
72
7.74k
}
73
74
75
static void ThreadClose(THREAD_HANDLE hThread)
76
7.74k
{
77
7.74k
#ifdef _UNIX
78
7.74k
  pthread_join(hThread,NULL);
79
#else
80
  CloseHandle(hThread);
81
#endif
82
7.74k
}
83
84
85
#ifdef _WIN_ALL
86
static void CWaitForSingleObject(HANDLE hHandle)
87
{
88
  DWORD rc=WaitForSingleObject(hHandle,INFINITE);
89
  if (rc==WAIT_FAILED)
90
  {
91
    ErrHandler.GeneralErrMsg(L"\nWaitForMultipleObjects error %d, GetLastError %d",rc,GetLastError());
92
    ErrHandler.Exit(RARX_FATAL);
93
  }
94
}
95
#endif
96
97
98
#ifdef _UNIX
99
static void cpthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
100
567k
{
101
567k
  int rc=pthread_cond_wait(cond,mutex);
102
567k
  if (rc!=0)
103
0
  {
104
0
    ErrHandler.GeneralErrMsg(L"\npthread_cond_wait error %d",rc);
105
0
    ErrHandler.Exit(RARX_FATAL);
106
0
  }
107
567k
}
108
#endif
109
110
111
uint GetNumberOfCPU()
112
23.9k
{
113
#ifndef RAR_SMP
114
  return 1;
115
#else
116
23.9k
#ifdef _UNIX
117
23.9k
#ifdef _SC_NPROCESSORS_ONLN
118
23.9k
  uint Count=(uint)sysconf(_SC_NPROCESSORS_ONLN);
119
23.9k
  return Count<1 ? 1:Count;
120
#elif defined(_APPLE)
121
  uint Count;
122
  size_t Size=sizeof(Count);
123
  return sysctlbyname("hw.ncpu",&Count,&Size,NULL,0)==0 ? Count:1;
124
#endif
125
#else // !_UNIX
126
127
#ifdef WIN32_CPU_GROUPS
128
  // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getprocessaffinitymask
129
  // "Starting with Windows 11 and Windows Server 2022, on a system with
130
  //  more than 64 processors, process and thread affinities span all
131
  //  processors in the system, across all processor groups, by default."
132
  // Supposing there are 80 CPUs in 2 processor groups 40 CPUs each.
133
  // Looks like, beginning from Windows 11 an app can use them all by default,
134
  // not resorting to processor groups API. But if we use GetProcessAffinityMask
135
  // to count CPUs, we would be limited to 40 CPUs only. So we call 
136
  // GetActiveProcessorCount() if it is available anf if there are multiple
137
  // processor groups. For a single group we prefer the affinity aware
138
  // GetProcessAffinityMask(). Out thread pool code handles the case
139
  // with restricted processor group affinity. So we avoid the complicated
140
  // code to calculate all processor groups affinity here, such as using
141
  // GetLogicalProcessorInformationEx, and resort to GetActiveProcessorCount().
142
  HMODULE hKernel=GetModuleHandle(L"kernel32.dll");
143
  if (hKernel!=nullptr)
144
  {
145
    typedef DWORD (WINAPI *GETACTIVEPROCESSORCOUNT)(WORD GroupNumber);
146
    GETACTIVEPROCESSORCOUNT pGetActiveProcessorCount=(GETACTIVEPROCESSORCOUNT)GetProcAddress(hKernel,"GetActiveProcessorCount");
147
    typedef WORD (WINAPI *GETACTIVEPROCESSORGROUPCOUNT)();
148
    GETACTIVEPROCESSORGROUPCOUNT pGetActiveProcessorGroupCount=(GETACTIVEPROCESSORGROUPCOUNT)GetProcAddress(hKernel,"GetActiveProcessorGroupCount");
149
    if (pGetActiveProcessorCount!=nullptr && pGetActiveProcessorGroupCount!=nullptr &&
150
        pGetActiveProcessorGroupCount()>1)
151
    {
152
      // Once the thread pool called SetThreadGroupAffinity(),
153
      // GetProcessAffinityMask() below will return 0. So we shall always
154
      // use GetActiveProcessorCount() here if there are multiple processor
155
      // groups, which makes SetThreadGroupAffinity() call possible.
156
      DWORD Count=pGetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
157
      return Count;
158
    }
159
  }
160
#endif
161
162
  DWORD_PTR ProcessMask;
163
  DWORD_PTR SystemMask;
164
165
  if (!GetProcessAffinityMask(GetCurrentProcess(),&ProcessMask,&SystemMask))
166
    return 1;
167
  uint Count=0;
168
  for (DWORD_PTR Mask=1;Mask!=0;Mask<<=1)
169
    if ((ProcessMask & Mask)!=0)
170
      Count++;
171
  return Count<1 ? 1:Count;
172
#endif
173
174
23.9k
#endif // RAR_SMP
175
23.9k
}
176
177
178
uint GetNumberOfThreads()
179
23.9k
{
180
23.9k
  uint NumCPU=GetNumberOfCPU();
181
23.9k
  if (NumCPU<1)
182
0
    return 1;
183
23.9k
  if (NumCPU>MaxPoolThreads)
184
0
    return MaxPoolThreads;
185
23.9k
  return NumCPU;
186
23.9k
}
187
188
189