52 #ifdef __cpp_lib_hardware_interference_size
53 l1_share_max = std::hardware_constructive_interference_size;
54 l1_apart_min = std::hardware_destructive_interference_size;
67 return (jlong) si.dwPageSize;
68 #elif defined(JAU_OS_TYPE_UNIX) && defined(_SC_PAGESIZE)
69 return sysconf(_SC_PAGESIZE);
75 return std::thread::hardware_concurrency();
81 GetSystemInfo(&sysinfo);
82 return static_cast<size_t>( sysinfo.dwNumberOfProcessors );
83 #elif defined(JAU_OS_TYPE_UNIX) && defined(_SC_NPROCESSORS_ONLN)
84 return static_cast<size_t>( sysconf(_SC_NPROCESSORS_ONLN) );
85 #elif defined(JAU_OS_TYPE_UNIX) && defined(HW_NCPU)
86 int mib[] { CTL_HW, HW_NCPU };
88 size_t len =
sizeof(numCPU);
89 if( sysctl(mib, 2, &numCPU, &len, NULL, 0) || 0 >= numCPU ) {
92 return static_cast<size_t>(numCPU);
102 GetSystemInfo(&sysinfo);
103 return static_cast<size_t>( sysinfo.dwNumberOfProcessors );
104 #elif defined(JAU_OS_TYPE_UNIX) && defined(_SC_NPROCESSORS_CONF)
105 return static_cast<size_t>( sysconf(_SC_NPROCESSORS_CONF) );
106 #elif defined(JAU_OS_TYPE_UNIX) && defined(HW_NCPU)
107 int mib[] { CTL_HW, HW_AVAILCPU };
109 size_t len =
sizeof(numCPU);
110 if( sysctl(mib, 2, &numCPU, &len, NULL, 0) || 0 >= numCPU ) {
113 return static_cast<size_t>(numCPU);
121static void append_bitstr(std::string& out, T mask, T bit,
const std::string& bitstr,
bool& comma) {
122 if( bit == ( mask & bit ) ) {
123 if( comma ) { out.append(
", "); }
124 out.append(bitstr); comma =
true;
127#define APPEND_BITSTR(U,V,M) append_bitstr(out, M, U::V, #V, comma);
129#define CASE_TO_STRING(U,V) case U::V: return #V;
131#define CPUFAMILY_ENUM(X) \
132 X(cpu_family_t,none) \
133 X(cpu_family_t,arm32) \
134 X(cpu_family_t,arm64) \
135 X(cpu_family_t,x86_32) \
136 X(cpu_family_t,x86_64) \
137 X(cpu_family_t,ia64) \
138 X(cpu_family_t,ppc32) \
139 X(cpu_family_t,ppc64) \
140 X(cpu_family_t,sparc32) \
141 X(cpu_family_t,sparc64) \
142 X(cpu_family_t,mips32) \
143 X(cpu_family_t,mips64) \
144 X(cpu_family_t,superh32) \
145 X(cpu_family_t,superh64) \
146 X(cpu_family_t,wasm32) \
147 X(cpu_family_t,wasm64)
158#define ARM32HWCAP1_ENUM(X,M) \
159 X(arm32_hwcap1_t,swp,M) \
160 X(arm32_hwcap1_t,half,M) \
161 X(arm32_hwcap1_t,thumb,M) \
162 X(arm32_hwcap1_t,bits26,M) \
163 X(arm32_hwcap1_t,fmult,M) \
164 X(arm32_hwcap1_t,fpa,M) \
165 X(arm32_hwcap1_t,vfp,M) \
166 X(arm32_hwcap1_t,edsp,M) \
167 X(arm32_hwcap1_t,java,M) \
168 X(arm32_hwcap1_t,iwmmxt,M) \
169 X(arm32_hwcap1_t,crunch,M) \
170 X(arm32_hwcap1_t,thumbee,M) \
171 X(arm32_hwcap1_t,neon,M) \
172 X(arm32_hwcap1_t,vfp_v3,M) \
173 X(arm32_hwcap1_t,vfp_v3_d16,M) \
174 X(arm32_hwcap1_t,tls,M) \
175 X(arm32_hwcap1_t,vfp_v4,M) \
176 X(arm32_hwcap1_t,idiva,M) \
177 X(arm32_hwcap1_t,idivt,M) \
178 X(arm32_hwcap1_t,vfp_d32,M) \
179 X(arm32_hwcap1_t,lpae,M) \
180 X(arm32_hwcap1_t,evtstrm,M)
189#define ARM32HWCAP2_ENUM(X,M) \
190 X(arm32_hwcap2_t,aes,M) \
191 X(arm32_hwcap2_t,pmull,M) \
192 X(arm32_hwcap2_t,sha1,M) \
193 X(arm32_hwcap2_t,sha2,M) \
194 X(arm32_hwcap2_t,crc32,M)
203#define ARM64HWCAP_ENUM(X,M) \
204 X(arm64_hwcap_t,fp,M) \
205 X(arm64_hwcap_t,asimd,M) \
206 X(arm64_hwcap_t,evtstrm,M) \
207 X(arm64_hwcap_t,aes,M) \
208 X(arm64_hwcap_t,pmull,M) \
209 X(arm64_hwcap_t,sha1,M) \
210 X(arm64_hwcap_t,sha2,M) \
211 X(arm64_hwcap_t,crc32,M) \
212 X(arm64_hwcap_t,atomics,M) \
213 X(arm64_hwcap_t,fphp,M) \
214 X(arm64_hwcap_t,asimdhp,M) \
215 X(arm64_hwcap_t,cpuid,M) \
216 X(arm64_hwcap_t,asimdrdm,M) \
217 X(arm64_hwcap_t,jscvt,M) \
218 X(arm64_hwcap_t,fcma,M) \
219 X(arm64_hwcap_t,lrcpc,M) \
220 X(arm64_hwcap_t,dcpop,M) \
221 X(arm64_hwcap_t,sha3,M) \
222 X(arm64_hwcap_t,sm3,M) \
223 X(arm64_hwcap_t,sm4,M) \
224 X(arm64_hwcap_t,asimddp,M) \
225 X(arm64_hwcap_t,sha512,M) \
226 X(arm64_hwcap_t,sve,M) \
227 X(arm64_hwcap_t,asimdfhm,M) \
228 X(arm64_hwcap_t,dit,M) \
229 X(arm64_hwcap_t,uscat,M) \
230 X(arm64_hwcap_t,ilrcpc,M) \
231 X(arm64_hwcap_t,flagm,M) \
232 X(arm64_hwcap_t,ssbs,M) \
233 X(arm64_hwcap_t,sb,M) \
234 X(arm64_hwcap_t,paca,M) \
235 X(arm64_hwcap_t,pacg,M)
246 #if defined(__EMSCRIPTEN__)
248 return cpu_family_t::wasm32;
250 return cpu_family_t::wasm64;
252 return cpu_family_t::wasm64;
254 #elif defined(__aarch64__)
256 return cpu_family_t::arm64;
257 #elif defined(__arm__)
259 return cpu_family_t::arm32;
260 #elif defined(__x86_64__)
262 return cpu_family_t::x86_64;
263 #elif defined(__ia64__)
265 return cpu_family_t::ia64;
266 #elif defined(__i386__)
268 return cpu_family_t::X86_32;
269 #elif defined(__powerpc__)
270 #if defined(__LP64__)
272 return cpu_family_t::ppc64;
275 return cpu_family_t::ppc32;
277 #elif defined(__sparc__)
278 #if defined(__LP64__)
280 return cpu_family_t::sparc64;
283 return cpu_family_t::sparc32;
285 #elif defined(__mips__)
286 #if defined(__LP64__)
288 return cpu_family_t::mips64;
291 return cpu_family_t::mips32;
293 #elif defined(__sh__)
294 #if defined(__LP64__)
296 return cpu_family_t::superh64;
299 return cpu_family_t::superh32;
302 return cpu_family_t::UNDEF;
307#if defined(__i386__) || defined(__x86_64__)
311#elif defined(__INTEL__)
312 #include <ia32intrin.h>
313#elif defined(__GNUC__) || defined(__clang__)
317static void invoke_cpuid(uint32_t type, uint32_t out[4]) {
318#if defined(_MSC_VER) || defined(__INTEL__)
319 __cpuid((
int*)out, type);
320#elif defined(__GNUC__) || defined(__clang__)
321 __get_cpuid(type, out, out+1, out+2, out+3);
323 #warning "No x86 cpuid supported for this compiler"
324 ::bzero(out,
sizeof(uint32_t)*4);
328static void invoke_cpuid_sublevel(uint32_t type, uint32_t level, uint32_t out[4]) {
330 __cpuidex((
int*)out, type, level);
331#elif defined(__GNUC__) || defined(__clang__)
332 __cpuid_count(type, level, out[0], out[1], out[2], out[3]);
334 #warning "No x86 cpuid sublevel supported for this compiler"
335 ::bzero(out,
sizeof(uint32_t)*4);
346 if( arm32_hwcap1_t::neon == ( hwcap1 & arm32_hwcap1_t::neon ) ) {
349 hwcap2 = arm32_hwcap2_t::none;
353 hwcap1 = arm32_hwcap1_t::none;
354 hwcap2 = arm32_hwcap2_t::none;
358 hwcap1 = arm32_hwcap1_t::none;
359 hwcap2 = arm32_hwcap2_t::none;
370 hwcap = arm64_hwcap_t::none;
374 hwcap = arm64_hwcap_t::none;
379jau::cpu::CpuInfo::CpuInfo() noexcept
382 has_l1_minmax(false), l1_share_max(0), l1_apart_min(0),
394 if( !details_only ) {
398 to_string(byte_order).c_str(), pointer_bits, online_core_count(), page_size) );
399 if( has_l1_minmax ) {
400 sb.append(
jau::format_string(
", l1[shared-max %zu, apart-min %zu]", l1_share_max, l1_apart_min) );
402 if( has_arm32_hwcap ) {
409 }
else if( has_arm64_hwcap ) {
414 if( !details_only ) {
std::string toString() const noexcept
size_t l1_apart_min
Minimum offset between two objects to avoid false sharing if has_l1_minmax, or zero.
bool has_l1_minmax
True if successfully queried l1_share_max and l1_apart_min.
size_t l1_share_max
Maximum size of contiguous memory to promote true sharing if has_l1_minmax, or zero.
static bool get_arm32_hwcap(arm32_hwcap1_t &hwcap1, arm32_hwcap2_t &hwcap2) noexcept
static size_t get_concurrent_thread_count() noexcept
static void append_bitstr(std::string &out, T mask, T bit, const std::string &bitstr, bool &comma)
#define ARM32HWCAP2_ENUM(X, M)
static size_t get_sys_online_core_count() noexcept
#define ARM32HWCAP1_ENUM(X, M)
#define ARM64HWCAP_ENUM(X, M)
static size_t get_sys_max_core_count() noexcept
static size_t get_page_size() noexcept
#define CASE_TO_STRING(U, V)
#define CPUFAMILY_ENUM(X)
static cpu_family_t get_cpu_family() noexcept
Returns cpu_family derived from Architectures predefined compiler macros.
static bool get_arm64_hwcap(arm64_hwcap_t &hwcap) noexcept
static bool get_cache_line_size(size_t &l1_share_max, size_t &l1_apart_min) noexcept
#define APPEND_BITSTR(U, V, M)
endian_t
Endian identifier, indicating endianess of all scalar types.
constexpr uint32_t number(const iostate rhs) noexcept
std::string format_string(const char *format,...) noexcept
Returns a string according to printf() formatting rules and variable number of arguments following th...
std::string to_string(const cpu_family_t v) noexcept
constexpr size_t pointer_bit_size() noexcept
Returns the compile time pointer architecture size in bits.
constexpr uint16_t number(const cpu_family_t rhs) noexcept
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.