// Copyright (c) 2019 Giorgos Vougioukas
//
// The license can be found in the LICENSE file.

#include "euterpe/concurrency.h"

#if defined(_WIN32)
#include <windows.h>
#elif defined(__linux__)
#include <unistd.h>
#endif

int GetCPUCores()
{
#if defined(_WIN32)
  SYSTEM_INFO sysinfo;
  GetSystemInfo(&sysinfo);
  int num_cpu = sysinfo.dwNumberOfProcessors;

  if (!num_cpu) num_cpu = 1;
  if (num_cpu > RSE_MAX_THREADS) num_cpu = RSE_MAX_THREADS;

  return num_cpu;
#elif defined(__APPLE__)
  int mib[4];
  int num_cpu;
  unsigned int len = sizeof(num_cpu); 

  /* set the mib for hw.ncpu */
  mib[0] = CTL_HW;
  mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;

  /* get the number of CPUs from the system */
  sysctl(mib, 2, &num_cpu, &len, NULL, 0);

  if (num_cpu < 1) 
  {
    mib[1] = HW_NCPU;
    sysctl(mib, 2, &num_cpu, &len, NULL, 0);
    if (num_cpu < 1) num_cpu = 1;
  }

  if (!num_cpu) num_cpu = 1;
  if (num_cpu > RSE_MAX_THREADS) num_cpu = RSE_MAX_THREADS;

  return num_cpu;
#elif defined(__linux__)
  int num_cpu = sysconf(_SC_NPROCESSORS_ONLN);

  if (!num_cpu) num_cpu = 1;
  if (num_cpu > RSE_MAX_THREADS) num_cpu = RSE_MAX_THREADS;

  return num_cpu;
#else
  #error "euterpe CPU cores not right"
#endif
}
