0030959: OSD_Parallel_TBB: number of execution threads is strictly limited by the...
[occt.git] / src / OSD / OSD_Parallel.cxx
CommitLineData
c7b59798 1// Created on: 2014-08-19
2// Created by: Alexander Zaikin
3// Copyright (c) 1996-1999 Matra Datavision
4// Copyright (c) 2013-2014 OPEN CASCADE SAS
5//
6// This file is part of Open CASCADE Technology software library.
7//
8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
13//
14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
16
17#include <OSD_Parallel.hxx>
18
19#ifdef _WIN32
4897e58d 20 #include <windows.h>
21 #include <process.h>
c7b59798 22#else
4897e58d 23 #include <sys/types.h>
00af0ebb 24 #include <unistd.h>
4897e58d 25
26 #ifdef __sun
27 #include <sys/processor.h>
28 #include <sys/procset.h>
29 #else
30 #include <sched.h>
31 #endif
c7b59798 32#endif
33
c7b59798 34namespace {
4897e58d 35
36#if defined(_WIN32) && !defined(OCCT_UWP)
37 //! For a 64-bit app running under 64-bit Windows, this is FALSE.
c7b59798 38 static bool isWow64()
39 {
40 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE , PBOOL);
41 BOOL bIsWow64 = FALSE;
742cc8b0 42
c7b59798 43 HMODULE aKern32Module = GetModuleHandleW(L"kernel32");
44 LPFN_ISWOW64PROCESS aFunIsWow64 = (aKern32Module == NULL) ? (LPFN_ISWOW64PROCESS )NULL
45 : (LPFN_ISWOW64PROCESS)GetProcAddress(aKern32Module, "IsWow64Process");
46
47 return aFunIsWow64 != NULL &&
48 aFunIsWow64(GetCurrentProcess(), &bIsWow64) &&
49 bIsWow64 != FALSE;
50 }
4897e58d 51
52#elif defined(__ANDROID__)
53
54 //! Simple number parser.
55 static const char* parseNumber (int& theResult,
56 const char* theInput,
57 const char* theLimit,
58 const int theBase = 10)
59 {
60 const char* aCharIter = theInput;
61 int aValue = 0;
62 while (aCharIter < theLimit)
63 {
64 int aDigit = (*aCharIter - '0');
65 if ((unsigned int )aDigit >= 10U)
66 {
67 aDigit = (*aCharIter - 'a');
68 if ((unsigned int )aDigit >= 6U)
69 {
70 aDigit = (*aCharIter - 'A');
71 }
72 if ((unsigned int )aDigit >= 6U)
73 {
74 break;
75 }
76 aDigit += 10;
77 }
78 if (aDigit >= theBase)
79 {
80 break;
81 }
82 aValue = aValue * theBase + aDigit;
83 ++aCharIter;
84 }
85 if (aCharIter == theInput)
86 {
87 return NULL;
88 }
89
90 theResult = aValue;
91 return aCharIter;
92 }
93
94 //! Read CPUs mask from sysfs.
95 static uint32_t readCpuMask (const char* thePath)
96 {
97 FILE* aFileHandle = fopen (thePath, "rb");
98 if (aFileHandle == NULL)
99 {
100 return 0;
101 }
102
103 fseek (aFileHandle, 0, SEEK_END);
104 long aFileLen = ftell (aFileHandle);
105 if (aFileLen <= 0L)
106 {
107 fclose (aFileHandle);
108 return 0;
109 }
110
111 char* aBuffer = (char* )Standard::Allocate (aFileLen);
112 if (aBuffer == NULL)
113 {
114 return 0;
115 }
116
117 fseek (aFileHandle, 0, SEEK_SET);
118 size_t aCountRead = fread (aBuffer, 1, aFileLen, aFileHandle);
119 (void )aCountRead;
120 fclose (aFileHandle);
121
122 uint32_t aCpuMask = 0;
123 const char* anEnd = aBuffer + aFileLen;
124 for (const char* aCharIter = aBuffer; aCharIter < anEnd && *aCharIter != '\n';)
125 {
126 const char* aChunkEnd = (const char* )::memchr (aCharIter, ',', anEnd - aCharIter);
127 if (aChunkEnd == NULL)
128 {
129 aChunkEnd = anEnd;
130 }
131
132 // get first value
133 int anIndexLower = 0;
134 aCharIter = parseNumber (anIndexLower, aCharIter, aChunkEnd);
135 if (aCharIter == NULL)
136 {
137 Standard::Free (aBuffer);
138 return aCpuMask;
139 }
140
141 // if we're not at the end of the item, expect a dash and and integer; extract end value.
142 int anIndexUpper = anIndexLower;
143 if (aCharIter < aChunkEnd && *aCharIter == '-')
144 {
145 aCharIter = parseNumber (anIndexUpper, aCharIter + 1, aChunkEnd);
146 if (aCharIter == NULL)
147 {
148 Standard::Free (aBuffer);
149 return aCpuMask;
150 }
151 }
152
153 // set bits CPU list
154 for (int aCpuIndex = anIndexLower; aCpuIndex <= anIndexUpper; ++aCpuIndex)
155 {
156 if ((unsigned int )aCpuIndex < 32)
157 {
158 aCpuMask |= (uint32_t )(1U << aCpuIndex);
159 }
160 }
161
162 aCharIter = aChunkEnd;
163 if (aCharIter < anEnd)
164 {
165 ++aCharIter;
166 }
167 }
168
169 Standard::Free (aBuffer);
170 return aCpuMask;
171 }
c7b59798 172#endif
173
fc867b96 174 static Standard_Boolean OSD_Parallel_ToUseOcctThreads =
175 #ifdef HAVE_TBB
176 Standard_False;
177 #else
178 Standard_True;
179 #endif
180}
181
182//=======================================================================
183//function : ToUseOcctThreads
184//purpose :
185//=======================================================================
186Standard_Boolean OSD_Parallel::ToUseOcctThreads()
187{
188 return OSD_Parallel_ToUseOcctThreads;
189}
190
191//=======================================================================
192//function : SetUseOcctThreads
193//purpose :
194//=======================================================================
195void OSD_Parallel::SetUseOcctThreads (Standard_Boolean theToUseOcct)
196{
197#ifdef HAVE_TBB
198 OSD_Parallel_ToUseOcctThreads = theToUseOcct;
199#else
200 (void )theToUseOcct;
201#endif
4897e58d 202}
203
c7b59798 204//=======================================================================
205//function : NbLogicalProcessors
206//purpose : Returns number of logical proccessors.
207//=======================================================================
208Standard_Integer OSD_Parallel::NbLogicalProcessors()
209{
210 static Standard_Integer aNumLogicalProcessors = 0;
211 if ( aNumLogicalProcessors != 0 )
212 {
213 return aNumLogicalProcessors;
214 }
215#ifdef _WIN32
216 // GetSystemInfo() will return the number of processors in a data field in a SYSTEM_INFO structure.
217 SYSTEM_INFO aSysInfo;
742cc8b0 218#ifndef OCCT_UWP
c7b59798 219 if ( isWow64() )
220 {
221 typedef BOOL (WINAPI *LPFN_GSI)(LPSYSTEM_INFO );
742cc8b0 222
c7b59798 223 HMODULE aKern32 = GetModuleHandleW(L"kernel32");
224 LPFN_GSI aFuncSysInfo = (LPFN_GSI )GetProcAddress(aKern32, "GetNativeSystemInfo");
742cc8b0 225
c7b59798 226 // So, they suggest 32-bit apps should call this instead of the other in WOW64
227 if ( aFuncSysInfo != NULL )
228 {
229 aFuncSysInfo(&aSysInfo);
230 }
231 else
232 {
233 GetSystemInfo(&aSysInfo);
234 }
235 }
236 else
237 {
238 GetSystemInfo(&aSysInfo);
239 }
742cc8b0 240#else
241 GetNativeSystemInfo(&aSysInfo);
242#endif
c7b59798 243 aNumLogicalProcessors = aSysInfo.dwNumberOfProcessors;
244#else
4897e58d 245
246#if defined(__ANDROID__)
247 uint32_t aCpuMaskPresent = readCpuMask ("/sys/devices/system/cpu/present");
248 uint32_t aCpuMaskPossible = readCpuMask ("/sys/devices/system/cpu/possible");
249 aCpuMaskPresent &= aCpuMaskPossible;
250 aNumLogicalProcessors = __builtin_popcount (aCpuMaskPresent);
251 if (aNumLogicalProcessors >= 1)
252 {
253 return aNumLogicalProcessors;
254 }
255#endif
256
c7b59798 257 // These are the choices. We'll check number of processors online.
258 // _SC_NPROCESSORS_CONF Number of processors configured
259 // _SC_NPROCESSORS_MAX Max number of processors supported by platform
260 // _SC_NPROCESSORS_ONLN Number of processors online
261 aNumLogicalProcessors = (Standard_Integer)sysconf(_SC_NPROCESSORS_ONLN);
262#endif
263 return aNumLogicalProcessors;
264}