forked from travisdowns/avx-turbo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cpu.c
165 lines (142 loc) · 4.38 KB
/
cpu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/* CPU Information (v1)
* Portable Snippets - https://gitub.com/nemequ/portable-snippets
* Created by Evan Nemerson <[email protected]>
*
* To the extent possible under law, the authors have waived all
* copyright and related or neighboring rights to this code. For
* details, see the Creative Commons Zero 1.0 Universal license at
* https://creativecommons.org/publicdomain/zero/1.0/
*/
#include "cpu.h"
#include "once.h"
#include <assert.h>
#if defined(_WIN32)
# include <Windows.h>
# define PSNIP_CPU__IMPL_WIN32
#elif defined(unix) || defined(__unix__) || defined(__unix)
# include <unistd.h>
# if defined(_SC_NPROCESSORS_ONLN) || defined(_SC_NPROC_ONLN)
# define PSNIP_CPU__IMPL_SYSCONF
# else
# include <sys/sysctl.h>
# endif
#endif
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
# if defined(_MSC_VER)
static void psnip_cpu_getid(int func, int* data) {
__cpuid(data, func);
}
# else
static void psnip_cpu_getid(int func, int* data) {
__asm__ ("cpuid"
: "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3])
: "0" (func), "2" (0));
}
# endif
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM64)
# if (defined(__GNUC__) && ((__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 16)))
# define PSNIP_CPU__IMPL_GETAUXVAL
# include <sys/auxv.h>
# endif
#endif
static psnip_once psnip_cpu_once = PSNIP_ONCE_INIT;
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
static unsigned int psnip_cpuinfo[8 * 4] = { 0, };
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
static unsigned long psnip_cpuinfo[2] = { 0, };
#endif
static void psnip_cpu_init(void) {
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
int i;
for (i = 0 ; i < 8 ; i++) {
psnip_cpu_getid(i, (int*) &(psnip_cpuinfo[i * 4]));
}
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
psnip_cpuinfo[0] = getauxval (AT_HWCAP);
psnip_cpuinfo[1] = getauxval (AT_HWCAP2);
#endif
}
int
psnip_cpu_feature_check (enum PSnipCPUFeature feature) {
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
unsigned int i, r, b;
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
unsigned long b, i;
#endif
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
if ((feature & PSNIP_CPU_FEATURE_CPU_MASK) != PSNIP_CPU_FEATURE_X86)
return 0;
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
if ((feature & PSNIP_CPU_FEATURE_CPU_MASK) != PSNIP_CPU_FEATURE_ARM)
return 0;
#else
return 0;
#endif
feature &= (enum PSnipCPUFeature) ~PSNIP_CPU_FEATURE_CPU_MASK;
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4152)
#endif
psnip_once_call (&psnip_cpu_once, psnip_cpu_init);
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if defined(PSNIP_CPU_ARCH_X86) || defined(PSNIP_CPU_ARCH_X86_64)
i = (feature >> 16) & 0xff;
r = (feature >> 8) & 0xff;
b = (feature ) & 0xff;
if (i > 7 || r > 3 || b > 31)
return 0;
return (psnip_cpuinfo[(i * 4) + r] >> b) & 1;
#elif defined(PSNIP_CPU_ARCH_ARM) || defined(PSNIP_CPU_ARCH_ARM_64)
b = 1 << ((feature & 0xff) - 1);
i = psnip_cpuinfo[(feature >> 0x08) & 0xff];
return (psnip_cpuinfo[(feature >> 0x08) & 0xff] & b) == b;
#endif
}
int
psnip_cpu_feature_check_many (enum PSnipCPUFeature* feature) {
int n;
for (n = 0 ; feature[n] != PSNIP_CPU_FEATURE_NONE ; n++)
if (!psnip_cpu_feature_check(feature[n]))
return 0;
return 1;
}
int
psnip_cpu_count (void) {
static int count = 0;
int c;
#if defined(_WIN32)
DWORD_PTR lpProcessAffinityMask;
DWORD_PTR lpSystemAffinityMask;
int i;
#elif defined(PSNIP_CPU__IMPL_SYSCONF) && defined(HW_NCPU)
int mib[2];
size_t len;
#endif
if (count != 0)
return count;
#if defined(_WIN32)
if (!GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) {
c = -1;
} else {
c = 0;
for (i = 0 ; lpProcessAffinityMask != 0 ; lpProcessAffinityMask >>= 1)
c += lpProcessAffinityMask & 1;
}
#elif defined(_SC_NPROCESSORS_ONLN)
c = sysconf (_SC_NPROCESSORS_ONLN);
#elif defined(_SC_NPROC_ONLN)
c = sysconf (_SC_NPROC_ONLN);
#elif defined(_hpux)
c = mpctl(MPC_GETNUMSPUS, NULL, NULL);
#elif defined(HW_NCPU)
c = 0;
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
len = sizeof(c);
sysctl (mib, 2, &c, &len, NULL, 0);
#endif
count = (c > 0) ? c : -1;
return count;
}