make requirements section of readme more retard-proof
[mkp224o.git] / cpucount.c
blob74ed7823f6e31dba1b6afabdea5bbd754b06a155
1 #include "cpucount.h"
3 #ifndef BSD
4 # ifndef __linux__
5 // FreeBSD
6 # ifdef __FreeBSD__
7 # undef BSD
8 # define BSD
9 # endif
10 // OpenBSD
11 # ifdef __OpenBSD__
12 # undef BSD
13 # define BSD
14 # endif
15 // NetBSD
16 # ifdef __NetBSD__
17 # undef BSD
18 # define BSD
19 # endif
20 // DragonFly
21 # ifdef __DragonFly__
22 # undef BSD
23 # define BSD
24 # endif
25 # endif // __linux__
26 // sys/param.h may have its own define
27 # ifdef BSD
28 # undef BSD
29 # include <sys/param.h>
30 # define SYS_PARAM_INCLUDED
31 # ifndef BSD
32 # define BSD
33 # endif
34 # endif
35 #endif // BSD
37 #ifdef BSD
38 # ifndef SYS_PARAM_INCLUDED
39 # include <sys/param.h>
40 # endif
41 # include <sys/sysctl.h>
42 #endif
44 #include <string.h>
46 #ifndef _WIN32
47 #include <unistd.h>
48 #else
49 #define UNICODE 1
50 #include <windows.h>
51 #endif
53 #ifdef __linux__
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <strings.h>
57 static int parsecpuinfo(void)
59 unsigned char cpubitmap[128];
61 memset(cpubitmap,0,sizeof(cpubitmap));
63 FILE *f = fopen("/proc/cpuinfo","r");
64 if (!f)
65 return -1;
67 char buf[8192];
68 while (fgets(buf,sizeof(buf),f)) {
69 // we don't like newlines
70 for (char *p = buf;*p;++p) {
71 if (*p == '\n') {
72 *p = 0;
73 break;
76 // split ':'
77 char *v = 0;
78 for (char *p = buf;*p;++p) {
79 if (*p == ':') {
80 *p = 0;
81 v = p + 1;
82 break;
85 // key padding
86 size_t kl = strlen(buf);
87 while (kl > 0 && (buf[kl - 1] == '\t' || buf[kl - 1] == ' ')) {
88 --kl;
89 buf[kl] = 0;
91 // space before value
92 if (v) {
93 while (*v && (*v == ' ' || *v == '\t'))
94 ++v;
96 // check what we need
97 if (strcasecmp(buf,"processor") == 0 && v) {
98 char *endp = 0;
99 long n = strtol(v,&endp,10);
100 if (endp && endp > v && n >= 0 && (size_t)n < sizeof(cpubitmap) * 8)
101 cpubitmap[n / 8] |= 1 << (n % 8);
105 fclose(f);
107 // count bits in bitmap
108 int ncpu = 0;
109 for (size_t n = 0;n < sizeof(cpubitmap) * 8;++n)
110 if (cpubitmap[n / 8] & (1 << (n % 8)))
111 ++ncpu;
113 return ncpu;
115 #endif
117 int cpucount(void)
119 int ncpu;
120 #ifdef _SC_NPROCESSORS_ONLN
121 ncpu = (int)sysconf(_SC_NPROCESSORS_ONLN);
122 if (ncpu > 0)
123 return ncpu;
124 #endif
125 #ifdef __linux__
126 // try parsing /proc/cpuinfo
127 // NOTE seems cygwin can provide this too, idk if need tho
128 ncpu = parsecpuinfo();
129 if (ncpu > 0)
130 return ncpu;
131 #endif
132 #ifdef BSD
133 const int ctlname[2] = {CTL_HW,HW_NCPU};
134 size_t ctllen = sizeof(ncpu);
135 if (sysctl(ctlname,2,&ncpu,&ctllen,0,0) < 0)
136 ncpu = -1;
137 if (ncpu > 0)
138 return ncpu;
139 #endif
140 #ifdef _WIN32
141 SYSTEM_INFO sysinfo;
142 GetSystemInfo(&sysinfo);
143 ncpu = (int)sysinfo.dwNumberOfProcessors;
144 if (ncpu > 0)
145 return ncpu;
146 #endif
147 (void) ncpu;
148 return -1;