16 #if defined(_WIN32) && BT_THREADSAFE
26 struct btProcessorInfo
28 int numLogicalProcessors;
34 int numPhysicalPackages;
35 static const int maxNumTeamMasks = 32;
37 UINT64 processorTeamMasks[maxNumTeamMasks];
40 UINT64 getProcessorTeamMask(
const btProcessorInfo& procInfo,
int procId)
42 UINT64 procMask = UINT64(1) << procId;
43 for (
int i = 0; i < procInfo.numTeamMasks; ++i)
45 if (procMask & procInfo.processorTeamMasks[i])
47 return procInfo.processorTeamMasks[i];
53 int getProcessorTeamIndex(
const btProcessorInfo& procInfo,
int procId)
55 UINT64 procMask = UINT64(1) << procId;
56 for (
int i = 0; i < procInfo.numTeamMasks; ++i)
58 if (procMask & procInfo.processorTeamMasks[i])
66 int countSetBits(ULONG64 bits)
80 typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
82 void getProcessorInformation(btProcessorInfo* procInfo)
84 memset(procInfo, 0,
sizeof(*procInfo));
85 Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
86 (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT(
"kernel32")),
"GetLogicalProcessorInformation");
87 if (getLogicalProcInfo ==
NULL)
92 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf =
NULL;
96 if (getLogicalProcInfo(buf, &bufSize))
102 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
108 buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
113 int len = bufSize /
sizeof(*buf);
114 for (
int i = 0; i <
len; ++i)
116 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
117 switch (info->Relationship)
119 case RelationNumaNode:
120 procInfo->numNumaNodes++;
123 case RelationProcessorCore:
124 procInfo->numCores++;
125 procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
129 if (info->Cache.Level == 1)
131 procInfo->numL1Cache++;
133 else if (info->Cache.Level == 2)
135 procInfo->numL2Cache++;
137 else if (info->Cache.Level == 3)
139 procInfo->numL3Cache++;
149 if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
151 procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
152 procInfo->numTeamMasks++;
157 case RelationProcessorPackage:
158 procInfo->numPhysicalPackages++;
169 struct btThreadStatus
175 ThreadFunc m_userThreadFunc;
178 void* m_threadHandle;
180 void* m_eventStartHandle;
181 char m_eventStartHandleName[32];
183 void* m_eventCompleteHandle;
184 char m_eventCompleteHandleName[32];
191 DWORD_PTR m_startedThreadMask;
192 btProcessorInfo m_processorInfo;
194 void startThreads(
const ConstructionInfo& threadInfo);
196 int waitForResponse();
199 btThreadSupportWin32(
const ConstructionInfo& threadConstructionInfo);
200 virtual ~btThreadSupportWin32();
213 btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
215 startThreads(threadConstructionInfo);
218 btThreadSupportWin32::~btThreadSupportWin32()
223 DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
225 btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
229 WaitForSingleObject(status->m_eventStartHandle, INFINITE);
230 void* userPtr = status->m_userPtr;
235 status->m_userThreadFunc(userPtr);
236 status->m_status = 2;
237 SetEvent(status->m_eventCompleteHandle);
242 status->m_status = 3;
243 printf(
"Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
244 SetEvent(status->m_eventCompleteHandle);
248 printf(
"Thread TERMINATED\n");
252 void btThreadSupportWin32::runTask(
int threadIndex,
void* userData)
254 btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
256 btAssert(
int(threadIndex) < m_activeThreadStatus.
size());
258 threadStatus.m_commandId = 1;
259 threadStatus.m_status = 1;
260 threadStatus.m_userPtr = userData;
261 m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
264 SetEvent(threadStatus.m_eventStartHandle);
267 int btThreadSupportWin32::waitForResponse()
272 DWORD res = WaitForMultipleObjects(m_completeHandles.
size(), &m_completeHandles[0],
FALSE, INFINITE);
274 last = res - WAIT_OBJECT_0;
276 btThreadStatus& threadStatus = m_activeThreadStatus[last];
277 btAssert(threadStatus.m_threadHandle);
278 btAssert(threadStatus.m_eventCompleteHandle);
281 btAssert(threadStatus.m_status > 1);
282 threadStatus.m_status = 0;
286 m_startedThreadMask &= ~(DWORD_PTR(1) << last);
291 void btThreadSupportWin32::waitForAllTasks()
293 while (m_startedThreadMask)
299 void btThreadSupportWin32::startThreads(
const ConstructionInfo& threadConstructionInfo)
303 btProcessorInfo& procInfo = m_processorInfo;
304 getProcessorInformation(&procInfo);
305 DWORD_PTR dwProcessAffinityMask = 0;
306 DWORD_PTR dwSystemAffinityMask = 0;
307 if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
309 dwProcessAffinityMask = 0;
314 m_activeThreadStatus.
resize(m_numThreads);
315 m_completeHandles.
resize(m_numThreads);
316 m_startedThreadMask = 0;
319 if (DWORD_PTR
mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
321 SetThreadAffinityMask(GetCurrentThread(),
mask);
322 SetThreadIdealProcessor(GetCurrentThread(), 0);
325 for (
int i = 0; i < m_numThreads; i++)
327 printf(
"starting thread %d\n", i);
329 btThreadStatus& threadStatus = m_activeThreadStatus[i];
331 LPSECURITY_ATTRIBUTES lpThreadAttributes =
NULL;
332 SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
333 LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
334 LPVOID lpParameter = &threadStatus;
335 DWORD dwCreationFlags = 0;
336 LPDWORD lpThreadId = 0;
338 threadStatus.m_userPtr = 0;
340 sprintf(threadStatus.m_eventStartHandleName,
"es%.8s%d%d", threadConstructionInfo.m_uniqueName,
uniqueId, i);
341 threadStatus.m_eventStartHandle = CreateEventA(0,
false,
false, threadStatus.m_eventStartHandleName);
343 sprintf(threadStatus.m_eventCompleteHandleName,
"ec%.8s%d%d", threadConstructionInfo.m_uniqueName,
uniqueId, i);
344 threadStatus.m_eventCompleteHandle = CreateEventA(0,
false,
false, threadStatus.m_eventCompleteHandleName);
346 m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
348 HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
356 int processorId = i + 1;
357 DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
364 DWORD_PTR
mask = teamMask & dwProcessAffinityMask;
367 SetThreadAffinityMask(handle,
mask);
370 SetThreadIdealProcessor(handle, processorId);
373 threadStatus.m_taskId = i;
374 threadStatus.m_commandId = 0;
375 threadStatus.m_status = 0;
376 threadStatus.m_threadHandle = handle;
377 threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
379 printf(
"started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
384 void btThreadSupportWin32::stopThreads()
386 for (
int i = 0; i < m_activeThreadStatus.
size(); i++)
388 btThreadStatus& threadStatus = m_activeThreadStatus[i];
389 if (threadStatus.m_status > 0)
391 WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
394 threadStatus.m_userPtr =
NULL;
395 SetEvent(threadStatus.m_eventStartHandle);
396 WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
398 CloseHandle(threadStatus.m_eventCompleteHandle);
399 CloseHandle(threadStatus.m_eventStartHandle);
400 CloseHandle(threadStatus.m_threadHandle);
403 m_activeThreadStatus.
clear();
404 m_completeHandles.
clear();
410 CRITICAL_SECTION mCriticalSection;
413 btWin32CriticalSection()
415 InitializeCriticalSection(&mCriticalSection);
418 ~btWin32CriticalSection()
420 DeleteCriticalSection(&mCriticalSection);
425 EnterCriticalSection(&mCriticalSection);
430 LeaveCriticalSection(&mCriticalSection);
436 unsigned char* mem = (
unsigned char*)
btAlignedAlloc(
sizeof(btWin32CriticalSection), 16);
437 btWin32CriticalSection* cs =
new (mem) btWin32CriticalSection();
441 void btThreadSupportWin32::deleteCriticalSection(
btCriticalSection* criticalSection)
449 return new btThreadSupportWin32(info);
void BLI_kdtree_nd_() free(KDTree *tree)
#define btAlignedFree(ptr)
#define btAlignedAlloc(size, alignment)
SIMD_FORCE_INLINE const T & btMin(const T &a, const T &b)
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint int const btContactSolverInfo btIDebugDraw *debugDrawer BT_OVERRIDE
const unsigned int BT_MAX_THREAD_COUNT
SIMD_FORCE_INLINE void clear()
clear the array, deallocated memory. Generally it is better to use array.resize(0),...
SIMD_FORCE_INLINE int size() const
return the number of elements in the array
SIMD_FORCE_INLINE void resize(int newsize, const T &fillData=T())
virtual ~btCriticalSection()
virtual int getCacheFriendlyNumThreads() const =0
virtual int getLogicalToPhysicalCoreRatio() const =0
virtual void waitForAllTasks()=0
virtual void runTask(int threadIndex, void *userData)=0
virtual int getNumWorkerThreads() const =0
static btThreadSupportInterface * create(const ConstructionInfo &info)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)