mkp224o/cpucount.c
2019-03-31 19:26:53 +00:00

150 lines
2.6 KiB
C

#include "cpucount.h"
#ifndef BSD
# ifndef __linux__
// FreeBSD
# ifdef __FreeBSD__
# undef BSD
# define BSD
# endif
// OpenBSD
# ifdef __OpenBSD__
# undef BSD
# define BSD
# endif
// NetBSD
# ifdef __NetBSD__
# undef BSD
# define BSD
# endif
// DragonFly
# ifdef __DragonFly__
# undef BSD
# define BSD
# endif
# endif // __linux__
// sys/param.h may have its own define
# ifdef BSD
# undef BSD
# include <sys/param.h>
# define SYS_PARAM_INCLUDED
# ifndef BSD
# define BSD
# endif
# endif
#endif // BSD
#ifdef BSD
# ifndef SYS_PARAM_INCLUDED
# include <sys/param.h>
# endif
# include <sys/sysctl.h>
#endif
#include <string.h>
#ifndef _WIN32
#include <unistd.h>
#else
#define UNICODE 1
#include <windows.h>
#endif
#ifdef __linux__
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
static int parsecpuinfo(void)
{
unsigned char cpubitmap[128];
memset(cpubitmap,0,sizeof(cpubitmap));
FILE *f = fopen("/proc/cpuinfo","r");
if (!f)
return -1;
char buf[8192];
while (fgets(buf,sizeof(buf),f)) {
// we don't like newlines
for (char *p = buf;*p;++p) {
if (*p == '\n') {
*p = 0;
break;
}
}
// split ':'
char *v = 0;
for (char *p = buf;*p;++p) {
if (*p == ':') {
*p = 0;
v = p + 1;
break;
}
}
// key padding
size_t kl = strlen(buf);
while (kl > 0 && (buf[kl - 1] == '\t' || buf[kl - 1] == ' ')) {
--kl;
buf[kl] = 0;
}
// space before value
if (v) {
while (*v && (*v == ' ' || *v == '\t'))
++v;
}
// check what we need
if (strcasecmp(buf,"processor") == 0 && v) {
char *endp = 0;
long n = strtol(v,&endp,10);
if (endp && endp > v && n >= 0 && (size_t)n < sizeof(cpubitmap) * 8)
cpubitmap[n / 8] |= 1 << (n % 8);
}
}
fclose(f);
// count bits in bitmap
int ncpu = 0;
for (size_t n = 0;n < sizeof(cpubitmap) * 8;++n)
if (cpubitmap[n / 8] & (1 << (n % 8)))
++ncpu;
return ncpu;
}
#endif
int cpucount(void)
{
int ncpu;
#ifdef _SC_NPROCESSORS_ONLN
ncpu = (int)sysconf(_SC_NPROCESSORS_ONLN);
if (ncpu > 0)
return ncpu;
#endif
#ifdef __linux__
// try parsing /proc/cpuinfo
// NOTE seems cygwin can provide this too, idk if need tho
ncpu = parsecpuinfo();
if (ncpu > 0)
return ncpu;
#endif
#ifdef BSD
const int ctlname[2] = {CTL_HW,HW_NCPU};
size_t ctllen = sizeof(ncpu);
if (sysctl(ctlname,2,&ncpu,&ctllen,0,0) < 0)
ncpu = -1;
if (ncpu > 0)
return ncpu;
#endif
#ifdef _WIN32
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
ncpu = (int)sysinfo.dwNumberOfProcessors;
if (ncpu > 0)
return ncpu;
#endif
(void) ncpu;
return -1;
}