xref: /aosp_15_r20/external/cpuinfo/src/emscripten/init.c (revision 2b54f0db79fd8303838913b20ff3780cddaa909f)
1*2b54f0dbSXin Li #include <stdbool.h>
2*2b54f0dbSXin Li #include <stdint.h>
3*2b54f0dbSXin Li #include <stdlib.h>
4*2b54f0dbSXin Li #include <string.h>
5*2b54f0dbSXin Li #include <math.h>
6*2b54f0dbSXin Li 
7*2b54f0dbSXin Li #include <emscripten/threading.h>
8*2b54f0dbSXin Li 
9*2b54f0dbSXin Li #include <cpuinfo.h>
10*2b54f0dbSXin Li #include <cpuinfo/internal-api.h>
11*2b54f0dbSXin Li #include <cpuinfo/log.h>
12*2b54f0dbSXin Li 
13*2b54f0dbSXin Li 
14*2b54f0dbSXin Li static const volatile float infinity = INFINITY;
15*2b54f0dbSXin Li 
16*2b54f0dbSXin Li static struct cpuinfo_package static_package = { };
17*2b54f0dbSXin Li 
18*2b54f0dbSXin Li static struct cpuinfo_cache static_x86_l3 = {
19*2b54f0dbSXin Li 	.size = 2 * 1024 * 1024,
20*2b54f0dbSXin Li 	.associativity = 16,
21*2b54f0dbSXin Li 	.sets = 2048,
22*2b54f0dbSXin Li 	.partitions = 1,
23*2b54f0dbSXin Li 	.line_size = 64,
24*2b54f0dbSXin Li };
25*2b54f0dbSXin Li 
cpuinfo_emscripten_init(void)26*2b54f0dbSXin Li void cpuinfo_emscripten_init(void) {
27*2b54f0dbSXin Li 	struct cpuinfo_processor* processors = NULL;
28*2b54f0dbSXin Li 	struct cpuinfo_core* cores = NULL;
29*2b54f0dbSXin Li 	struct cpuinfo_cluster* clusters = NULL;
30*2b54f0dbSXin Li 	struct cpuinfo_cache* l1i = NULL;
31*2b54f0dbSXin Li 	struct cpuinfo_cache* l1d = NULL;
32*2b54f0dbSXin Li 	struct cpuinfo_cache* l2 = NULL;
33*2b54f0dbSXin Li 
34*2b54f0dbSXin Li 	const bool is_x86 = signbit(infinity - infinity);
35*2b54f0dbSXin Li 
36*2b54f0dbSXin Li 	int logical_cores_count = emscripten_num_logical_cores();
37*2b54f0dbSXin Li 	if (logical_cores_count <= 0) {
38*2b54f0dbSXin Li 		logical_cores_count = 1;
39*2b54f0dbSXin Li 	}
40*2b54f0dbSXin Li 	uint32_t processor_count = (uint32_t) logical_cores_count;
41*2b54f0dbSXin Li 	uint32_t core_count = processor_count;
42*2b54f0dbSXin Li 	uint32_t cluster_count = 1;
43*2b54f0dbSXin Li 	uint32_t big_cluster_core_count = core_count;
44*2b54f0dbSXin Li 	uint32_t processors_per_core = 1;
45*2b54f0dbSXin Li 	if (is_x86) {
46*2b54f0dbSXin Li 		if (processor_count % 2 == 0) {
47*2b54f0dbSXin Li 			processors_per_core = 2;
48*2b54f0dbSXin Li 			core_count = processor_count / 2;
49*2b54f0dbSXin Li 			big_cluster_core_count = core_count;
50*2b54f0dbSXin Li 		}
51*2b54f0dbSXin Li 	} else {
52*2b54f0dbSXin Li 		/* Assume ARM/ARM64 */
53*2b54f0dbSXin Li 		if (processor_count > 4) {
54*2b54f0dbSXin Li 			/* Assume big.LITTLE architecture */
55*2b54f0dbSXin Li 			cluster_count = 2;
56*2b54f0dbSXin Li 			big_cluster_core_count = processor_count >= 8 ? 4 : 2;
57*2b54f0dbSXin Li 		}
58*2b54f0dbSXin Li 	}
59*2b54f0dbSXin Li 	uint32_t l2_count = is_x86 ? core_count : cluster_count;
60*2b54f0dbSXin Li 
61*2b54f0dbSXin Li 	processors = calloc(processor_count, sizeof(struct cpuinfo_processor));
62*2b54f0dbSXin Li 	if (processors == NULL) {
63*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" logical processors",
64*2b54f0dbSXin Li 			processor_count * sizeof(struct cpuinfo_processor), processor_count);
65*2b54f0dbSXin Li 		goto cleanup;
66*2b54f0dbSXin Li 	}
67*2b54f0dbSXin Li 	cores = calloc(processor_count, sizeof(struct cpuinfo_core));
68*2b54f0dbSXin Li 	if (cores == NULL) {
69*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores",
70*2b54f0dbSXin Li 			processor_count * sizeof(struct cpuinfo_core), processor_count);
71*2b54f0dbSXin Li 		goto cleanup;
72*2b54f0dbSXin Li 	}
73*2b54f0dbSXin Li 	clusters = calloc(cluster_count, sizeof(struct cpuinfo_cluster));
74*2b54f0dbSXin Li 	if (clusters == NULL) {
75*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" clusters",
76*2b54f0dbSXin Li 			cluster_count * sizeof(struct cpuinfo_cluster), cluster_count);
77*2b54f0dbSXin Li 		goto cleanup;
78*2b54f0dbSXin Li 	}
79*2b54f0dbSXin Li 
80*2b54f0dbSXin Li 	l1i = calloc(core_count, sizeof(struct cpuinfo_cache));
81*2b54f0dbSXin Li 	if (l1i == NULL) {
82*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1I caches",
83*2b54f0dbSXin Li 			core_count * sizeof(struct cpuinfo_cache), core_count);
84*2b54f0dbSXin Li 		goto cleanup;
85*2b54f0dbSXin Li 	}
86*2b54f0dbSXin Li 
87*2b54f0dbSXin Li 	l1d = calloc(core_count, sizeof(struct cpuinfo_cache));
88*2b54f0dbSXin Li 	if (l1d == NULL) {
89*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1D caches",
90*2b54f0dbSXin Li 			core_count * sizeof(struct cpuinfo_cache), core_count);
91*2b54f0dbSXin Li 		goto cleanup;
92*2b54f0dbSXin Li 	}
93*2b54f0dbSXin Li 
94*2b54f0dbSXin Li 	l2 = calloc(l2_count, sizeof(struct cpuinfo_cache));
95*2b54f0dbSXin Li 	if (l2 == NULL) {
96*2b54f0dbSXin Li 		cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L2 caches",
97*2b54f0dbSXin Li 			l2_count * sizeof(struct cpuinfo_cache), l2_count);
98*2b54f0dbSXin Li 		goto cleanup;
99*2b54f0dbSXin Li 	}
100*2b54f0dbSXin Li 
101*2b54f0dbSXin Li 	static_package.processor_count = processor_count;
102*2b54f0dbSXin Li 	static_package.core_count = core_count;
103*2b54f0dbSXin Li 	static_package.cluster_count = cluster_count;
104*2b54f0dbSXin Li 	if (is_x86) {
105*2b54f0dbSXin Li 		strncpy(static_package.name, "x86 vCPU", CPUINFO_PACKAGE_NAME_MAX);
106*2b54f0dbSXin Li 	} else {
107*2b54f0dbSXin Li 		strncpy(static_package.name, "ARM vCPU", CPUINFO_PACKAGE_NAME_MAX);
108*2b54f0dbSXin Li 	}
109*2b54f0dbSXin Li 
110*2b54f0dbSXin Li 	for (uint32_t i = 0; i < core_count; i++) {
111*2b54f0dbSXin Li 		for (uint32_t j = 0; j < processors_per_core; j++) {
112*2b54f0dbSXin Li 			processors[i * processors_per_core + j] = (struct cpuinfo_processor) {
113*2b54f0dbSXin Li 				.smt_id = j,
114*2b54f0dbSXin Li 				.core = cores + i,
115*2b54f0dbSXin Li 				.cluster = clusters + (uint32_t) (i >= big_cluster_core_count),
116*2b54f0dbSXin Li 				.package = &static_package,
117*2b54f0dbSXin Li 				.cache.l1i = l1i + i,
118*2b54f0dbSXin Li 				.cache.l1d = l1d + i,
119*2b54f0dbSXin Li 				.cache.l2 = is_x86 ? l2 + i : l2 + (uint32_t) (i >= big_cluster_core_count),
120*2b54f0dbSXin Li 				.cache.l3 = is_x86 ? &static_x86_l3 : NULL,
121*2b54f0dbSXin Li 			};
122*2b54f0dbSXin Li 		}
123*2b54f0dbSXin Li 
124*2b54f0dbSXin Li 		cores[i] = (struct cpuinfo_core) {
125*2b54f0dbSXin Li 			.processor_start = i * processors_per_core,
126*2b54f0dbSXin Li 			.processor_count = processors_per_core,
127*2b54f0dbSXin Li 			.core_id = i,
128*2b54f0dbSXin Li 			.cluster = clusters + (uint32_t) (i >= big_cluster_core_count),
129*2b54f0dbSXin Li 			.package = &static_package,
130*2b54f0dbSXin Li 			.vendor = cpuinfo_vendor_unknown,
131*2b54f0dbSXin Li 			.uarch = cpuinfo_uarch_unknown,
132*2b54f0dbSXin Li 			.frequency = 0,
133*2b54f0dbSXin Li 		};
134*2b54f0dbSXin Li 
135*2b54f0dbSXin Li 		l1i[i] = (struct cpuinfo_cache) {
136*2b54f0dbSXin Li 			.size = 32 * 1024,
137*2b54f0dbSXin Li 			.associativity = 4,
138*2b54f0dbSXin Li 			.sets = 128,
139*2b54f0dbSXin Li 			.partitions = 1,
140*2b54f0dbSXin Li 			.line_size = 64,
141*2b54f0dbSXin Li 			.processor_start = i * processors_per_core,
142*2b54f0dbSXin Li 			.processor_count = processors_per_core,
143*2b54f0dbSXin Li 		};
144*2b54f0dbSXin Li 
145*2b54f0dbSXin Li 		l1d[i] = (struct cpuinfo_cache) {
146*2b54f0dbSXin Li 			.size = 32 * 1024,
147*2b54f0dbSXin Li 			.associativity = 4,
148*2b54f0dbSXin Li 			.sets = 128,
149*2b54f0dbSXin Li 			.partitions = 1,
150*2b54f0dbSXin Li 			.line_size = 64,
151*2b54f0dbSXin Li 			.processor_start = i * processors_per_core,
152*2b54f0dbSXin Li 			.processor_count = processors_per_core,
153*2b54f0dbSXin Li 		};
154*2b54f0dbSXin Li 
155*2b54f0dbSXin Li 		if (is_x86) {
156*2b54f0dbSXin Li 			l2[i] = (struct cpuinfo_cache) {
157*2b54f0dbSXin Li 				.size = 256 * 1024,
158*2b54f0dbSXin Li 				.associativity = 8,
159*2b54f0dbSXin Li 				.sets = 512,
160*2b54f0dbSXin Li 				.partitions = 1,
161*2b54f0dbSXin Li 				.line_size = 64,
162*2b54f0dbSXin Li 				.processor_start = i * processors_per_core,
163*2b54f0dbSXin Li 				.processor_count = processors_per_core,
164*2b54f0dbSXin Li 			};
165*2b54f0dbSXin Li 		}
166*2b54f0dbSXin Li 	}
167*2b54f0dbSXin Li 
168*2b54f0dbSXin Li 	if (is_x86) {
169*2b54f0dbSXin Li 		clusters[0] = (struct cpuinfo_cluster) {
170*2b54f0dbSXin Li 			.processor_start = 0,
171*2b54f0dbSXin Li 			.processor_count = processor_count,
172*2b54f0dbSXin Li 			.core_start = 0,
173*2b54f0dbSXin Li 			.core_count = core_count,
174*2b54f0dbSXin Li 			.cluster_id = 0,
175*2b54f0dbSXin Li 			.package = &static_package,
176*2b54f0dbSXin Li 			.vendor = cpuinfo_vendor_unknown,
177*2b54f0dbSXin Li 			.uarch = cpuinfo_uarch_unknown,
178*2b54f0dbSXin Li 			.frequency = 0,
179*2b54f0dbSXin Li 		};
180*2b54f0dbSXin Li 
181*2b54f0dbSXin Li 		static_x86_l3.processor_count = processor_count;
182*2b54f0dbSXin Li 	} else {
183*2b54f0dbSXin Li 		clusters[0] = (struct cpuinfo_cluster) {
184*2b54f0dbSXin Li 			.processor_start = 0,
185*2b54f0dbSXin Li 			.processor_count = big_cluster_core_count,
186*2b54f0dbSXin Li 			.core_start = 0,
187*2b54f0dbSXin Li 			.core_count = big_cluster_core_count,
188*2b54f0dbSXin Li 			.cluster_id = 0,
189*2b54f0dbSXin Li 			.package = &static_package,
190*2b54f0dbSXin Li 			.vendor = cpuinfo_vendor_unknown,
191*2b54f0dbSXin Li 			.uarch = cpuinfo_uarch_unknown,
192*2b54f0dbSXin Li 			.frequency = 0,
193*2b54f0dbSXin Li 		};
194*2b54f0dbSXin Li 
195*2b54f0dbSXin Li 		l2[0] = (struct cpuinfo_cache) {
196*2b54f0dbSXin Li 			.size = 1024 * 1024,
197*2b54f0dbSXin Li 			.associativity = 8,
198*2b54f0dbSXin Li 			.sets = 2048,
199*2b54f0dbSXin Li 			.partitions = 1,
200*2b54f0dbSXin Li 			.line_size = 64,
201*2b54f0dbSXin Li 			.processor_start = 0,
202*2b54f0dbSXin Li 			.processor_count = big_cluster_core_count,
203*2b54f0dbSXin Li 		};
204*2b54f0dbSXin Li 
205*2b54f0dbSXin Li 		if (cluster_count > 1) {
206*2b54f0dbSXin Li 			l2[1] = (struct cpuinfo_cache) {
207*2b54f0dbSXin Li 				.size = 256 * 1024,
208*2b54f0dbSXin Li 				.associativity = 8,
209*2b54f0dbSXin Li 				.sets = 512,
210*2b54f0dbSXin Li 				.partitions = 1,
211*2b54f0dbSXin Li 				.line_size = 64,
212*2b54f0dbSXin Li 				.processor_start = big_cluster_core_count,
213*2b54f0dbSXin Li 				.processor_count = processor_count - big_cluster_core_count,
214*2b54f0dbSXin Li 			};
215*2b54f0dbSXin Li 
216*2b54f0dbSXin Li 			clusters[1] = (struct cpuinfo_cluster) {
217*2b54f0dbSXin Li 				.processor_start = big_cluster_core_count,
218*2b54f0dbSXin Li 				.processor_count = processor_count - big_cluster_core_count,
219*2b54f0dbSXin Li 				.core_start = big_cluster_core_count,
220*2b54f0dbSXin Li 				.core_count = processor_count - big_cluster_core_count,
221*2b54f0dbSXin Li 				.cluster_id = 1,
222*2b54f0dbSXin Li 				.package = &static_package,
223*2b54f0dbSXin Li 				.vendor = cpuinfo_vendor_unknown,
224*2b54f0dbSXin Li 				.uarch = cpuinfo_uarch_unknown,
225*2b54f0dbSXin Li 				.frequency = 0,
226*2b54f0dbSXin Li 			};
227*2b54f0dbSXin Li 		}
228*2b54f0dbSXin Li 	}
229*2b54f0dbSXin Li 
230*2b54f0dbSXin Li 	/* Commit changes */
231*2b54f0dbSXin Li 	cpuinfo_cache[cpuinfo_cache_level_1i] = l1i;
232*2b54f0dbSXin Li 	cpuinfo_cache[cpuinfo_cache_level_1d] = l1d;
233*2b54f0dbSXin Li 	cpuinfo_cache[cpuinfo_cache_level_2]  = l2;
234*2b54f0dbSXin Li 	if (is_x86) {
235*2b54f0dbSXin Li 		cpuinfo_cache[cpuinfo_cache_level_3]  = &static_x86_l3;
236*2b54f0dbSXin Li 	}
237*2b54f0dbSXin Li 
238*2b54f0dbSXin Li 	cpuinfo_processors = processors;
239*2b54f0dbSXin Li 	cpuinfo_cores = cores;
240*2b54f0dbSXin Li 	cpuinfo_clusters = clusters;
241*2b54f0dbSXin Li 	cpuinfo_packages = &static_package;
242*2b54f0dbSXin Li 
243*2b54f0dbSXin Li 	cpuinfo_cache_count[cpuinfo_cache_level_1i] = processor_count;
244*2b54f0dbSXin Li 	cpuinfo_cache_count[cpuinfo_cache_level_1d] = processor_count;
245*2b54f0dbSXin Li 	cpuinfo_cache_count[cpuinfo_cache_level_2]  = l2_count;
246*2b54f0dbSXin Li 	if (is_x86) {
247*2b54f0dbSXin Li 		cpuinfo_cache_count[cpuinfo_cache_level_3]  = 1;
248*2b54f0dbSXin Li 	}
249*2b54f0dbSXin Li 
250*2b54f0dbSXin Li 	cpuinfo_global_uarch = (struct cpuinfo_uarch_info) {
251*2b54f0dbSXin Li 		.uarch = cpuinfo_uarch_unknown,
252*2b54f0dbSXin Li 		.processor_count = processor_count,
253*2b54f0dbSXin Li 		.core_count = core_count,
254*2b54f0dbSXin Li 	};
255*2b54f0dbSXin Li 
256*2b54f0dbSXin Li 	cpuinfo_processors_count = processor_count;
257*2b54f0dbSXin Li 	cpuinfo_cores_count = processor_count;
258*2b54f0dbSXin Li 	cpuinfo_clusters_count = cluster_count;
259*2b54f0dbSXin Li 	cpuinfo_packages_count = 1;
260*2b54f0dbSXin Li 
261*2b54f0dbSXin Li 	cpuinfo_max_cache_size = is_x86 ? 128 * 1024 * 1024 : 8 * 1024 * 1024;
262*2b54f0dbSXin Li 
263*2b54f0dbSXin Li 	cpuinfo_is_initialized = true;
264*2b54f0dbSXin Li 
265*2b54f0dbSXin Li 	processors = NULL;
266*2b54f0dbSXin Li 	cores = NULL;
267*2b54f0dbSXin Li 	clusters = NULL;
268*2b54f0dbSXin Li 	l1i = l1d = l2 = NULL;
269*2b54f0dbSXin Li 
270*2b54f0dbSXin Li cleanup:
271*2b54f0dbSXin Li 	free(processors);
272*2b54f0dbSXin Li 	free(cores);
273*2b54f0dbSXin Li 	free(clusters);
274*2b54f0dbSXin Li 	free(l1i);
275*2b54f0dbSXin Li 	free(l1d);
276*2b54f0dbSXin Li 	free(l2);
277*2b54f0dbSXin Li }
278