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);
 
  452 #endif  //defined(_WIN32) && BT_THREADSAFE