uint32_t WindowsEnvironment::GetCoreCount()

in src/environment/environment_windows.cc [99:153]


uint32_t WindowsEnvironment::GetCoreCount() {
  LPFN_GLPI glpi;
  BOOL done = FALSE;
  PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
  PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
  DWORD returnLength = 0;
  DWORD byteOffset = 0;

  glpi = (LPFN_GLPI)::GetProcAddress(GetModuleHandle(TEXT("kernel32")),
      "GetLogicalProcessorInformation");
  if(!glpi) {
    return 0;
  }

  while(!done) {
    DWORD rc = glpi(buffer, &returnLength);
    if(FALSE == rc) {
      if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        if(buffer) {
          free(buffer);
        }

        buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(
                   returnLength);
        if(NULL == buffer) {
          return 0;
        }
      } else {
        return 0;
      }
    } else {
      done = TRUE;
    }
  }

  uint32_t count = 0;
  ptr = buffer;
  while(byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)
        <= returnLength) {
    switch(ptr->Relationship) {
    case RelationProcessorCore:
      // A hyperthreaded core supplies more than one logical processor.
      count += CountSetBits(ptr->ProcessorMask);
      break;

    default:
      break;
    }
    byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
    ptr++;
  }

  free(buffer);
  return count;
}