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