summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp')
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp700
1 files changed, 340 insertions, 360 deletions
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
index 00edac650b..922e449cce 100644
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
@@ -13,7 +13,7 @@ subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution.
*/
-#if defined( _WIN32 ) && BT_THREADSAFE
+#if defined(_WIN32) && BT_THREADSAFE
#include "LinearMath/btScalar.h"
#include "LinearMath/btMinMax.h"
@@ -23,450 +23,430 @@ subject to the following restrictions:
#include <windows.h>
#include <stdio.h>
-
struct btProcessorInfo
{
- int numLogicalProcessors;
- int numCores;
- int numNumaNodes;
- int numL1Cache;
- int numL2Cache;
- int numL3Cache;
- int numPhysicalPackages;
- static const int maxNumTeamMasks = 32;
- int numTeamMasks;
- UINT64 processorTeamMasks[ maxNumTeamMasks ];
+ int numLogicalProcessors;
+ int numCores;
+ int numNumaNodes;
+ int numL1Cache;
+ int numL2Cache;
+ int numL3Cache;
+ int numPhysicalPackages;
+ static const int maxNumTeamMasks = 32;
+ int numTeamMasks;
+ UINT64 processorTeamMasks[maxNumTeamMasks];
};
-UINT64 getProcessorTeamMask( const btProcessorInfo& procInfo, int procId )
+UINT64 getProcessorTeamMask(const btProcessorInfo& procInfo, int procId)
{
- UINT64 procMask = UINT64( 1 ) << procId;
- for ( int i = 0; i < procInfo.numTeamMasks; ++i )
- {
- if ( procMask & procInfo.processorTeamMasks[ i ] )
- {
- return procInfo.processorTeamMasks[ i ];
- }
- }
- return 0;
+ UINT64 procMask = UINT64(1) << procId;
+ for (int i = 0; i < procInfo.numTeamMasks; ++i)
+ {
+ if (procMask & procInfo.processorTeamMasks[i])
+ {
+ return procInfo.processorTeamMasks[i];
+ }
+ }
+ return 0;
}
-int getProcessorTeamIndex( const btProcessorInfo& procInfo, int procId )
+int getProcessorTeamIndex(const btProcessorInfo& procInfo, int procId)
{
- UINT64 procMask = UINT64( 1 ) << procId;
- for ( int i = 0; i < procInfo.numTeamMasks; ++i )
- {
- if ( procMask & procInfo.processorTeamMasks[ i ] )
- {
- return i;
- }
- }
- return -1;
+ UINT64 procMask = UINT64(1) << procId;
+ for (int i = 0; i < procInfo.numTeamMasks; ++i)
+ {
+ if (procMask & procInfo.processorTeamMasks[i])
+ {
+ return i;
+ }
+ }
+ return -1;
}
-int countSetBits( ULONG64 bits )
+int countSetBits(ULONG64 bits)
{
- int count = 0;
- while ( bits )
- {
- if ( bits & 1 )
- {
- count++;
- }
- bits >>= 1;
- }
- return count;
+ int count = 0;
+ while (bits)
+ {
+ if (bits & 1)
+ {
+ count++;
+ }
+ bits >>= 1;
+ }
+ return count;
}
+typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
-typedef BOOL( WINAPI *Pfn_GetLogicalProcessorInformation )( PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD );
-
-
-void getProcessorInformation( btProcessorInfo* procInfo )
+void getProcessorInformation(btProcessorInfo* procInfo)
{
- memset( procInfo, 0, sizeof( *procInfo ) );
- Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
- (Pfn_GetLogicalProcessorInformation) GetProcAddress( GetModuleHandle( TEXT( "kernel32" ) ), "GetLogicalProcessorInformation" );
- if ( getLogicalProcInfo == NULL )
- {
- // no info
- return;
- }
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
- DWORD bufSize = 0;
- while ( true )
- {
- if ( getLogicalProcInfo( buf, &bufSize ) )
- {
- break;
- }
- else
- {
- if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
- {
- if ( buf )
- {
- free( buf );
- }
- buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION) malloc( bufSize );
- }
- }
- }
-
- int len = bufSize / sizeof( *buf );
- for ( int i = 0; i < len; ++i )
- {
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
- switch ( info->Relationship )
- {
- case RelationNumaNode:
- procInfo->numNumaNodes++;
- break;
-
- case RelationProcessorCore:
- procInfo->numCores++;
- procInfo->numLogicalProcessors += countSetBits( info->ProcessorMask );
- break;
-
- case RelationCache:
- if ( info->Cache.Level == 1 )
- {
- procInfo->numL1Cache++;
- }
- else if ( info->Cache.Level == 2 )
- {
- procInfo->numL2Cache++;
- }
- else if ( info->Cache.Level == 3 )
- {
- procInfo->numL3Cache++;
- // processors that share L3 cache are considered to be on the same team
- // because they can more easily work together on the same data.
- // Large performance penalties will occur if 2 or more threads from different
- // teams attempt to frequently read and modify the same cache lines.
- //
- // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
- // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
- // CCXs are operating on the same data, many cycles will be spent keeping the
- // two caches coherent.
- if ( procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks )
- {
- procInfo->processorTeamMasks[ procInfo->numTeamMasks ] = info->ProcessorMask;
- procInfo->numTeamMasks++;
- }
- }
- break;
-
- case RelationProcessorPackage:
- procInfo->numPhysicalPackages++;
- break;
- }
- }
- free( buf );
+ memset(procInfo, 0, sizeof(*procInfo));
+ Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
+ (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
+ if (getLogicalProcInfo == NULL)
+ {
+ // no info
+ return;
+ }
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
+ DWORD bufSize = 0;
+ while (true)
+ {
+ if (getLogicalProcInfo(buf, &bufSize))
+ {
+ break;
+ }
+ else
+ {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if (buf)
+ {
+ free(buf);
+ }
+ buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
+ }
+ }
+ }
+
+ int len = bufSize / sizeof(*buf);
+ for (int i = 0; i < len; ++i)
+ {
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
+ switch (info->Relationship)
+ {
+ case RelationNumaNode:
+ procInfo->numNumaNodes++;
+ break;
+
+ case RelationProcessorCore:
+ procInfo->numCores++;
+ procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
+ break;
+
+ case RelationCache:
+ if (info->Cache.Level == 1)
+ {
+ procInfo->numL1Cache++;
+ }
+ else if (info->Cache.Level == 2)
+ {
+ procInfo->numL2Cache++;
+ }
+ else if (info->Cache.Level == 3)
+ {
+ procInfo->numL3Cache++;
+ // processors that share L3 cache are considered to be on the same team
+ // because they can more easily work together on the same data.
+ // Large performance penalties will occur if 2 or more threads from different
+ // teams attempt to frequently read and modify the same cache lines.
+ //
+ // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
+ // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
+ // CCXs are operating on the same data, many cycles will be spent keeping the
+ // two caches coherent.
+ if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
+ {
+ procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
+ procInfo->numTeamMasks++;
+ }
+ }
+ break;
+
+ case RelationProcessorPackage:
+ procInfo->numPhysicalPackages++;
+ break;
+ }
+ }
+ free(buf);
}
-
-
///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
class btThreadSupportWin32 : public btThreadSupportInterface
{
public:
- struct btThreadStatus
- {
- int m_taskId;
- int m_commandId;
- int m_status;
+ struct btThreadStatus
+ {
+ int m_taskId;
+ int m_commandId;
+ int m_status;
- ThreadFunc m_userThreadFunc;
- void* m_userPtr; //for taskDesc etc
+ ThreadFunc m_userThreadFunc;
+ void* m_userPtr; //for taskDesc etc
- void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
+ void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
- void* m_eventStartHandle;
- char m_eventStartHandleName[ 32 ];
+ void* m_eventStartHandle;
+ char m_eventStartHandleName[32];
- void* m_eventCompleteHandle;
- char m_eventCompleteHandleName[ 32 ];
- };
+ void* m_eventCompleteHandle;
+ char m_eventCompleteHandleName[32];
+ };
private:
- btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
- btAlignedObjectArray<void*> m_completeHandles;
- int m_numThreads;
- DWORD_PTR m_startedThreadMask;
- btProcessorInfo m_processorInfo;
+ btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
+ btAlignedObjectArray<void*> m_completeHandles;
+ int m_numThreads;
+ DWORD_PTR m_startedThreadMask;
+ btProcessorInfo m_processorInfo;
- void startThreads( const ConstructionInfo& threadInfo );
- void stopThreads();
- int waitForResponse();
+ void startThreads(const ConstructionInfo& threadInfo);
+ void stopThreads();
+ int waitForResponse();
public:
+ btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo);
+ virtual ~btThreadSupportWin32();
- btThreadSupportWin32( const ConstructionInfo& threadConstructionInfo );
- virtual ~btThreadSupportWin32();
+ virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
+ virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
+ virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
- virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
- virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
- virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
+ virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
+ virtual void waitForAllTasks() BT_OVERRIDE;
- virtual void runTask( int threadIndex, void* userData ) BT_OVERRIDE;
- virtual void waitForAllTasks() BT_OVERRIDE;
-
- virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
- virtual void deleteCriticalSection( btCriticalSection* criticalSection ) BT_OVERRIDE;
+ virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
+ virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
};
-
-btThreadSupportWin32::btThreadSupportWin32( const ConstructionInfo & threadConstructionInfo )
+btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
{
- startThreads( threadConstructionInfo );
+ startThreads(threadConstructionInfo);
}
-
btThreadSupportWin32::~btThreadSupportWin32()
{
- stopThreads();
+ stopThreads();
}
-
-DWORD WINAPI win32threadStartFunc( LPVOID lpParam )
+DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
{
- btThreadSupportWin32::btThreadStatus* status = ( btThreadSupportWin32::btThreadStatus* )lpParam;
-
- while ( 1 )
- {
- WaitForSingleObject( status->m_eventStartHandle, INFINITE );
- void* userPtr = status->m_userPtr;
-
- if ( userPtr )
- {
- btAssert( status->m_status );
- status->m_userThreadFunc( userPtr );
- status->m_status = 2;
- SetEvent( status->m_eventCompleteHandle );
- }
- else
- {
- //exit Thread
- status->m_status = 3;
- printf( "Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle );
- SetEvent( status->m_eventCompleteHandle );
- break;
- }
- }
- printf( "Thread TERMINATED\n" );
- return 0;
+ btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
+
+ while (1)
+ {
+ WaitForSingleObject(status->m_eventStartHandle, INFINITE);
+ void* userPtr = status->m_userPtr;
+
+ if (userPtr)
+ {
+ btAssert(status->m_status);
+ status->m_userThreadFunc(userPtr);
+ status->m_status = 2;
+ SetEvent(status->m_eventCompleteHandle);
+ }
+ else
+ {
+ //exit Thread
+ status->m_status = 3;
+ printf("Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
+ SetEvent(status->m_eventCompleteHandle);
+ break;
+ }
+ }
+ printf("Thread TERMINATED\n");
+ return 0;
}
-
-void btThreadSupportWin32::runTask( int threadIndex, void* userData )
+void btThreadSupportWin32::runTask(int threadIndex, void* userData)
{
- btThreadStatus& threadStatus = m_activeThreadStatus[ threadIndex ];
- btAssert( threadIndex >= 0 );
- btAssert( int( threadIndex ) < m_activeThreadStatus.size() );
+ btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
+ btAssert(threadIndex >= 0);
+ btAssert(int(threadIndex) < m_activeThreadStatus.size());
- threadStatus.m_commandId = 1;
- threadStatus.m_status = 1;
- threadStatus.m_userPtr = userData;
- m_startedThreadMask |= DWORD_PTR( 1 ) << threadIndex;
+ threadStatus.m_commandId = 1;
+ threadStatus.m_status = 1;
+ threadStatus.m_userPtr = userData;
+ m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
- ///fire event to start new task
- SetEvent( threadStatus.m_eventStartHandle );
+ ///fire event to start new task
+ SetEvent(threadStatus.m_eventStartHandle);
}
-
int btThreadSupportWin32::waitForResponse()
{
- btAssert( m_activeThreadStatus.size() );
+ btAssert(m_activeThreadStatus.size());
- int last = -1;
- DWORD res = WaitForMultipleObjects( m_completeHandles.size(), &m_completeHandles[ 0 ], FALSE, INFINITE );
- btAssert( res != WAIT_FAILED );
- last = res - WAIT_OBJECT_0;
+ int last = -1;
+ DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
+ btAssert(res != WAIT_FAILED);
+ last = res - WAIT_OBJECT_0;
- btThreadStatus& threadStatus = m_activeThreadStatus[ last ];
- btAssert( threadStatus.m_threadHandle );
- btAssert( threadStatus.m_eventCompleteHandle );
+ btThreadStatus& threadStatus = m_activeThreadStatus[last];
+ btAssert(threadStatus.m_threadHandle);
+ btAssert(threadStatus.m_eventCompleteHandle);
- //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
- btAssert( threadStatus.m_status > 1 );
- threadStatus.m_status = 0;
+ //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+ btAssert(threadStatus.m_status > 1);
+ threadStatus.m_status = 0;
- ///need to find an active spu
- btAssert( last >= 0 );
- m_startedThreadMask &= ~( DWORD_PTR( 1 ) << last );
+ ///need to find an active spu
+ btAssert(last >= 0);
+ m_startedThreadMask &= ~(DWORD_PTR(1) << last);
- return last;
+ return last;
}
-
void btThreadSupportWin32::waitForAllTasks()
{
- while ( m_startedThreadMask )
- {
- waitForResponse();
- }
+ while (m_startedThreadMask)
+ {
+ waitForResponse();
+ }
}
-
-void btThreadSupportWin32::startThreads( const ConstructionInfo& threadConstructionInfo )
+void btThreadSupportWin32::startThreads(const ConstructionInfo& threadConstructionInfo)
{
- static int uniqueId = 0;
- uniqueId++;
- btProcessorInfo& procInfo = m_processorInfo;
- getProcessorInformation( &procInfo );
- DWORD_PTR dwProcessAffinityMask = 0;
- DWORD_PTR dwSystemAffinityMask = 0;
- if ( !GetProcessAffinityMask( GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask ) )
- {
- dwProcessAffinityMask = 0;
- }
- ///The number of threads should be equal to the number of available cores - 1
- m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
-
- m_activeThreadStatus.resize( m_numThreads );
- m_completeHandles.resize( m_numThreads );
- m_startedThreadMask = 0;
-
- // set main thread affinity
- if ( DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask( procInfo, 0 ))
- {
- SetThreadAffinityMask( GetCurrentThread(), mask );
- SetThreadIdealProcessor( GetCurrentThread(), 0 );
- }
-
- for ( int i = 0; i < m_numThreads; i++ )
- {
- printf( "starting thread %d\n", i );
-
- btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
-
- LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
- SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
- LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
- LPVOID lpParameter = &threadStatus;
- DWORD dwCreationFlags = 0;
- LPDWORD lpThreadId = 0;
-
- threadStatus.m_userPtr = 0;
-
- sprintf( threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i );
- threadStatus.m_eventStartHandle = CreateEventA( 0, false, false, threadStatus.m_eventStartHandleName );
-
- sprintf( threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i );
- threadStatus.m_eventCompleteHandle = CreateEventA( 0, false, false, threadStatus.m_eventCompleteHandleName );
-
- m_completeHandles[ i ] = threadStatus.m_eventCompleteHandle;
-
- HANDLE handle = CreateThread( lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId );
- //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
- // highest priority -- can cause erratic performance when numThreads > numCores
- // we don't want worker threads to be higher priority than the main thread or the main thread could get
- // totally shut out and unable to tell the workers to stop
- //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
-
- {
- int processorId = i + 1; // leave processor 0 for main thread
- DWORD_PTR teamMask = getProcessorTeamMask( procInfo, processorId );
- if ( teamMask )
- {
- // bind each thread to only execute on processors of it's assigned team
- // - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
- // - for multi-socket Intel this will keep threads from migrating from one socket to another
- // - for AMD Ryzen this will keep threads from migrating from one CCX to another
- DWORD_PTR mask = teamMask & dwProcessAffinityMask;
- if ( mask )
- {
- SetThreadAffinityMask( handle, mask );
- }
- }
- SetThreadIdealProcessor( handle, processorId );
- }
-
- threadStatus.m_taskId = i;
- threadStatus.m_commandId = 0;
- threadStatus.m_status = 0;
- threadStatus.m_threadHandle = handle;
- threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
-
- printf( "started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle );
- }
+ static int uniqueId = 0;
+ uniqueId++;
+ btProcessorInfo& procInfo = m_processorInfo;
+ getProcessorInformation(&procInfo);
+ DWORD_PTR dwProcessAffinityMask = 0;
+ DWORD_PTR dwSystemAffinityMask = 0;
+ if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
+ {
+ dwProcessAffinityMask = 0;
+ }
+ ///The number of threads should be equal to the number of available cores - 1
+ m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
+
+ m_activeThreadStatus.resize(m_numThreads);
+ m_completeHandles.resize(m_numThreads);
+ m_startedThreadMask = 0;
+
+ // set main thread affinity
+ if (DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
+ {
+ SetThreadAffinityMask(GetCurrentThread(), mask);
+ SetThreadIdealProcessor(GetCurrentThread(), 0);
+ }
+
+ for (int i = 0; i < m_numThreads; i++)
+ {
+ printf("starting thread %d\n", i);
+
+ btThreadStatus& threadStatus = m_activeThreadStatus[i];
+
+ LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
+ SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
+ LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
+ LPVOID lpParameter = &threadStatus;
+ DWORD dwCreationFlags = 0;
+ LPDWORD lpThreadId = 0;
+
+ threadStatus.m_userPtr = 0;
+
+ sprintf(threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+ threadStatus.m_eventStartHandle = CreateEventA(0, false, false, threadStatus.m_eventStartHandleName);
+
+ sprintf(threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
+ threadStatus.m_eventCompleteHandle = CreateEventA(0, false, false, threadStatus.m_eventCompleteHandleName);
+
+ m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
+
+ HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
+ //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
+ // highest priority -- can cause erratic performance when numThreads > numCores
+ // we don't want worker threads to be higher priority than the main thread or the main thread could get
+ // totally shut out and unable to tell the workers to stop
+ //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
+
+ {
+ int processorId = i + 1; // leave processor 0 for main thread
+ DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
+ if (teamMask)
+ {
+ // bind each thread to only execute on processors of it's assigned team
+ // - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
+ // - for multi-socket Intel this will keep threads from migrating from one socket to another
+ // - for AMD Ryzen this will keep threads from migrating from one CCX to another
+ DWORD_PTR mask = teamMask & dwProcessAffinityMask;
+ if (mask)
+ {
+ SetThreadAffinityMask(handle, mask);
+ }
+ }
+ SetThreadIdealProcessor(handle, processorId);
+ }
+
+ threadStatus.m_taskId = i;
+ threadStatus.m_commandId = 0;
+ threadStatus.m_status = 0;
+ threadStatus.m_threadHandle = handle;
+ threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+
+ printf("started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
+ }
}
///tell the task scheduler we are done with the SPU tasks
void btThreadSupportWin32::stopThreads()
{
- for ( int i = 0; i < m_activeThreadStatus.size(); i++ )
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[ i ];
- if ( threadStatus.m_status > 0 )
- {
- WaitForSingleObject( threadStatus.m_eventCompleteHandle, INFINITE );
- }
-
- threadStatus.m_userPtr = NULL;
- SetEvent( threadStatus.m_eventStartHandle );
- WaitForSingleObject( threadStatus.m_eventCompleteHandle, INFINITE );
-
- CloseHandle( threadStatus.m_eventCompleteHandle );
- CloseHandle( threadStatus.m_eventStartHandle );
- CloseHandle( threadStatus.m_threadHandle );
-
- }
-
- m_activeThreadStatus.clear();
- m_completeHandles.clear();
+ for (int i = 0; i < m_activeThreadStatus.size(); i++)
+ {
+ btThreadStatus& threadStatus = m_activeThreadStatus[i];
+ if (threadStatus.m_status > 0)
+ {
+ WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+ }
+
+ threadStatus.m_userPtr = NULL;
+ SetEvent(threadStatus.m_eventStartHandle);
+ WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
+
+ CloseHandle(threadStatus.m_eventCompleteHandle);
+ CloseHandle(threadStatus.m_eventStartHandle);
+ CloseHandle(threadStatus.m_threadHandle);
+ }
+
+ m_activeThreadStatus.clear();
+ m_completeHandles.clear();
}
-
class btWin32CriticalSection : public btCriticalSection
{
private:
- CRITICAL_SECTION mCriticalSection;
+ CRITICAL_SECTION mCriticalSection;
public:
- btWin32CriticalSection()
- {
- InitializeCriticalSection( &mCriticalSection );
- }
-
- ~btWin32CriticalSection()
- {
- DeleteCriticalSection( &mCriticalSection );
- }
-
- void lock()
- {
- EnterCriticalSection( &mCriticalSection );
- }
-
- void unlock()
- {
- LeaveCriticalSection( &mCriticalSection );
- }
+ btWin32CriticalSection()
+ {
+ InitializeCriticalSection(&mCriticalSection);
+ }
+
+ ~btWin32CriticalSection()
+ {
+ DeleteCriticalSection(&mCriticalSection);
+ }
+
+ void lock()
+ {
+ EnterCriticalSection(&mCriticalSection);
+ }
+
+ void unlock()
+ {
+ LeaveCriticalSection(&mCriticalSection);
+ }
};
-
btCriticalSection* btThreadSupportWin32::createCriticalSection()
{
- unsigned char* mem = (unsigned char*) btAlignedAlloc( sizeof( btWin32CriticalSection ), 16 );
- btWin32CriticalSection* cs = new( mem ) btWin32CriticalSection();
- return cs;
+ unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32CriticalSection), 16);
+ btWin32CriticalSection* cs = new (mem) btWin32CriticalSection();
+ return cs;
}
-void btThreadSupportWin32::deleteCriticalSection( btCriticalSection* criticalSection )
+void btThreadSupportWin32::deleteCriticalSection(btCriticalSection* criticalSection)
{
- criticalSection->~btCriticalSection();
- btAlignedFree( criticalSection );
+ criticalSection->~btCriticalSection();
+ btAlignedFree(criticalSection);
}
-
-btThreadSupportInterface* btThreadSupportInterface::create( const ConstructionInfo& info )
+btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
{
- return new btThreadSupportWin32( info );
+ return new btThreadSupportWin32(info);
}
-
-
-#endif //defined(_WIN32) && BT_THREADSAFE
-
+#endif //defined(_WIN32) && BT_THREADSAFE