xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/getcpu/getcpu01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright © International Business Machines  Corp., 2007, 2008
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  * Test Description:
6*49cdfc7eSAndroid Build Coastguard Worker  *  The test process is affined to a CPU. It then calls getcpu and
7*49cdfc7eSAndroid Build Coastguard Worker  *  checks that the CPU and node (if supported) match the expected
8*49cdfc7eSAndroid Build Coastguard Worker  *  values.
9*49cdfc7eSAndroid Build Coastguard Worker  */
10*49cdfc7eSAndroid Build Coastguard Worker 
11*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
12*49cdfc7eSAndroid Build Coastguard Worker #include <dirent.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
17*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/cpuset.h"
19*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/sched.h"
20*49cdfc7eSAndroid Build Coastguard Worker 
max_cpuid(size_t size,cpu_set_t * set)21*49cdfc7eSAndroid Build Coastguard Worker static unsigned int max_cpuid(size_t size, cpu_set_t * set)
22*49cdfc7eSAndroid Build Coastguard Worker {
23*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int index, max = 0;
24*49cdfc7eSAndroid Build Coastguard Worker 	for (index = 0; index < size * 8; index++)
25*49cdfc7eSAndroid Build Coastguard Worker 		if (CPU_ISSET_S(index, size, set))
26*49cdfc7eSAndroid Build Coastguard Worker 			max = index;
27*49cdfc7eSAndroid Build Coastguard Worker 	return max;
28*49cdfc7eSAndroid Build Coastguard Worker }
29*49cdfc7eSAndroid Build Coastguard Worker 
30*49cdfc7eSAndroid Build Coastguard Worker /*
31*49cdfc7eSAndroid Build Coastguard Worker  * This will set the affinity to max cpu on which process can run
32*49cdfc7eSAndroid Build Coastguard Worker  * and return that cpu id to the calling process
33*49cdfc7eSAndroid Build Coastguard Worker  */
set_cpu_affinity(void)34*49cdfc7eSAndroid Build Coastguard Worker static unsigned int set_cpu_affinity(void)
35*49cdfc7eSAndroid Build Coastguard Worker {
36*49cdfc7eSAndroid Build Coastguard Worker 	unsigned cpu_max;
37*49cdfc7eSAndroid Build Coastguard Worker 	cpu_set_t *set;
38*49cdfc7eSAndroid Build Coastguard Worker 	size_t size;
39*49cdfc7eSAndroid Build Coastguard Worker 	int nrcpus = 1024;
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker realloc:
42*49cdfc7eSAndroid Build Coastguard Worker 	set = CPU_ALLOC(nrcpus);
43*49cdfc7eSAndroid Build Coastguard Worker 	if (!set)
44*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "CPU_ALLOC()");
45*49cdfc7eSAndroid Build Coastguard Worker 
46*49cdfc7eSAndroid Build Coastguard Worker 	size = CPU_ALLOC_SIZE(nrcpus);
47*49cdfc7eSAndroid Build Coastguard Worker 	CPU_ZERO_S(size, set);
48*49cdfc7eSAndroid Build Coastguard Worker 	if (sched_getaffinity(0, size, set) < 0) {
49*49cdfc7eSAndroid Build Coastguard Worker 		CPU_FREE(set);
50*49cdfc7eSAndroid Build Coastguard Worker 		if (errno == EINVAL && nrcpus < (1024 << 8)) {
51*49cdfc7eSAndroid Build Coastguard Worker 			nrcpus = nrcpus << 2;
52*49cdfc7eSAndroid Build Coastguard Worker 			goto realloc;
53*49cdfc7eSAndroid Build Coastguard Worker 		}
54*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "sched_getaffinity()");
55*49cdfc7eSAndroid Build Coastguard Worker 	}
56*49cdfc7eSAndroid Build Coastguard Worker 	cpu_max = max_cpuid(size, set);
57*49cdfc7eSAndroid Build Coastguard Worker 	CPU_ZERO_S(size, set);
58*49cdfc7eSAndroid Build Coastguard Worker 	CPU_SET_S(cpu_max, size, set);
59*49cdfc7eSAndroid Build Coastguard Worker 	if (sched_setaffinity(0, size, set) < 0) {
60*49cdfc7eSAndroid Build Coastguard Worker 		CPU_FREE(set);
61*49cdfc7eSAndroid Build Coastguard Worker 		tst_brk(TBROK | TERRNO, "sched_setaffinity()");
62*49cdfc7eSAndroid Build Coastguard Worker 	}
63*49cdfc7eSAndroid Build Coastguard Worker 	CPU_FREE(set);
64*49cdfc7eSAndroid Build Coastguard Worker 	return cpu_max;
65*49cdfc7eSAndroid Build Coastguard Worker }
66*49cdfc7eSAndroid Build Coastguard Worker 
get_nodeid(unsigned int cpu_id)67*49cdfc7eSAndroid Build Coastguard Worker static unsigned int get_nodeid(unsigned int cpu_id)
68*49cdfc7eSAndroid Build Coastguard Worker {
69*49cdfc7eSAndroid Build Coastguard Worker 	DIR *directory_parent, *directory_node;
70*49cdfc7eSAndroid Build Coastguard Worker 	struct dirent *de, *dn;
71*49cdfc7eSAndroid Build Coastguard Worker 	char directory_path[PATH_MAX];
72*49cdfc7eSAndroid Build Coastguard Worker 	char *invalid_number;
73*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int cpu;
74*49cdfc7eSAndroid Build Coastguard Worker 	int node_id = 0;
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker 	directory_parent = opendir("/sys/devices/system/node");
77*49cdfc7eSAndroid Build Coastguard Worker 	if (!directory_parent) {
78*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO,
79*49cdfc7eSAndroid Build Coastguard Worker 			"/sys not mounted or not a numa system. "
80*49cdfc7eSAndroid Build Coastguard Worker 			"Assuming one node");
81*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TINFO, "Error opening: /sys/devices/system/node :%s",
82*49cdfc7eSAndroid Build Coastguard Worker 			strerror(errno));
83*49cdfc7eSAndroid Build Coastguard Worker 		/* Assume CPU belongs to the only node, node zero. */
84*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
85*49cdfc7eSAndroid Build Coastguard Worker 	} else {
86*49cdfc7eSAndroid Build Coastguard Worker 		while ((de = readdir(directory_parent)) != NULL) {
87*49cdfc7eSAndroid Build Coastguard Worker 			if (strncmp(de->d_name, "node", 4))
88*49cdfc7eSAndroid Build Coastguard Worker 				continue;
89*49cdfc7eSAndroid Build Coastguard Worker 			sprintf(directory_path, "/sys/devices/system/node/%s",
90*49cdfc7eSAndroid Build Coastguard Worker 				de->d_name);
91*49cdfc7eSAndroid Build Coastguard Worker 			directory_node = opendir(directory_path);
92*49cdfc7eSAndroid Build Coastguard Worker 			while ((dn = readdir(directory_node)) != NULL) {
93*49cdfc7eSAndroid Build Coastguard Worker 				if (strncmp(dn->d_name, "cpu", 3))
94*49cdfc7eSAndroid Build Coastguard Worker 					continue;
95*49cdfc7eSAndroid Build Coastguard Worker 				cpu = strtoul(dn->d_name + 3, &invalid_number, 0);
96*49cdfc7eSAndroid Build Coastguard Worker 				if (strcmp(invalid_number, "\0"))
97*49cdfc7eSAndroid Build Coastguard Worker 					continue;
98*49cdfc7eSAndroid Build Coastguard Worker 				if (cpu == cpu_id) {
99*49cdfc7eSAndroid Build Coastguard Worker 					node_id =
100*49cdfc7eSAndroid Build Coastguard Worker 					    strtoul(de->d_name + 4, NULL, 0);
101*49cdfc7eSAndroid Build Coastguard Worker 					break;
102*49cdfc7eSAndroid Build Coastguard Worker 				}
103*49cdfc7eSAndroid Build Coastguard Worker 			}
104*49cdfc7eSAndroid Build Coastguard Worker 			closedir(directory_node);
105*49cdfc7eSAndroid Build Coastguard Worker 		}
106*49cdfc7eSAndroid Build Coastguard Worker 		closedir(directory_parent);
107*49cdfc7eSAndroid Build Coastguard Worker 	}
108*49cdfc7eSAndroid Build Coastguard Worker 	return node_id;
109*49cdfc7eSAndroid Build Coastguard Worker }
110*49cdfc7eSAndroid Build Coastguard Worker 
run(void)111*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
112*49cdfc7eSAndroid Build Coastguard Worker {
113*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int cpu_id, node_id = 0;
114*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int cpu_set;
115*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int node_set;
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	cpu_set = set_cpu_affinity();
118*49cdfc7eSAndroid Build Coastguard Worker 	node_set = get_nodeid(cpu_set);
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	TEST(getcpu(&cpu_id, &node_id));
121*49cdfc7eSAndroid Build Coastguard Worker 	if (TST_RET == 0) {
122*49cdfc7eSAndroid Build Coastguard Worker 		if (cpu_id != cpu_set)
123*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "getcpu() returned wrong value"
124*49cdfc7eSAndroid Build Coastguard Worker 				" expected cpuid:%d, returned value cpuid: %d",
125*49cdfc7eSAndroid Build Coastguard Worker 				cpu_set, cpu_id);
126*49cdfc7eSAndroid Build Coastguard Worker 		else if (node_id != node_set)
127*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TFAIL, "getcpu() returned wrong value"
128*49cdfc7eSAndroid Build Coastguard Worker 				" expected  node id:%d returned  node id:%d",
129*49cdfc7eSAndroid Build Coastguard Worker 				node_set, node_id);
130*49cdfc7eSAndroid Build Coastguard Worker 		else
131*49cdfc7eSAndroid Build Coastguard Worker 			tst_res(TPASS, "getcpu() returned proper"
132*49cdfc7eSAndroid Build Coastguard Worker 				" cpuid:%d, node id:%d", cpu_id,
133*49cdfc7eSAndroid Build Coastguard Worker 				node_id);
134*49cdfc7eSAndroid Build Coastguard Worker 	} else {
135*49cdfc7eSAndroid Build Coastguard Worker 		tst_res(TFAIL, "getcpu() Failed, errno=%d:%s",
136*49cdfc7eSAndroid Build Coastguard Worker 			TST_ERR, strerror(TST_ERR));
137*49cdfc7eSAndroid Build Coastguard Worker 	}
138*49cdfc7eSAndroid Build Coastguard Worker }
139*49cdfc7eSAndroid Build Coastguard Worker 
140*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
141*49cdfc7eSAndroid Build Coastguard Worker 	.test_all = run,
142*49cdfc7eSAndroid Build Coastguard Worker };
143