blob: 599d9b1f8e7abcbfe9d0ffded7ae111c75844a0c [file] [log] [blame]
subrata_modak5a4cf272008-08-22 21:09:58 +00001/*
2 *
3 * Copyright © International Business Machines Corp., 2007, 2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
18 */
19
20/*
21 * NAME
22 * getcpu1.c
23 *
24 * DESCRIPTION
25 * getcpu01 - call getcpu() and make sure it succeeds
26 *
27 * ALGORITHM
subrata_modak4bb656a2009-02-26 12:02:09 +000028 * set cpu affinity of the process
subrata_modak5a4cf272008-08-22 21:09:58 +000029 * If setaffinity() fails exit from the test suite
30 * Store the node ID of the cpu which has been set in previous step
31 * Make a call to getcpu() system call
32 * Verify the returned valued with the set value
subrata_modak4bb656a2009-02-26 12:02:09 +000033 * if they match
subrata_modak5a4cf272008-08-22 21:09:58 +000034 * test is considered PASS
35 * else
36 * test is considered FAIL
37 *
38 * USAGE: <for command-line>
39 * getcpu [-c n] [-f] [-i n] [-I x] [-P x] [-t]
40 * where, -c n : Run n copies concurrently.
41 * -f : Turn off functionality Testing.
42 * -i n : Execute test n times.
43 * -I x : Execute test for x seconds.
44 * -P x : Pause for x seconds between iterations.
45 * -t : Turn on syscall timing.
46 *
47 * HISTORY
48 * 06/2008 written by Sharyathi Nagesh <sharyathi@in.ibm.com>
49 *
subrata_modak5c8eb0c2009-05-30 18:30:15 +000050 * 05/2009 Suzuki K P <suzuki@in.ibm.com>
51 * Use TCONF instead of TWARN for non-NUMA machines
52 *
subrata_modak5a4cf272008-08-22 21:09:58 +000053 * RESTRICTIONS
54 * none
55 */
56
subrata_modak5a4cf272008-08-22 21:09:58 +000057#define _GNU_SOURCE
58#include <sched.h>
59#include <errno.h>
60#include "test.h"
subrata_modak5a4cf272008-08-22 21:09:58 +000061#include <sys/types.h>
62#include <dirent.h>
63
64#if defined(__i386__) || defined(__x86_64__)
subrata_modak56207ce2009-03-23 13:35:39 +000065#if __GLIBC_PREREQ(2,6)
66#if defined(__x86_64__)
67#include <utmpx.h>
68#endif
69int sys_support = 1;
70#elif defined(__i386__)
71int sys_support = 1;
72#else
73int sys_support = 0;
74#endif
subrata_modak5a4cf272008-08-22 21:09:58 +000075#else
76int sys_support = 0;
77#endif
subrata_modakbdbaec52009-02-26 12:14:51 +000078
subrata_modak08216ea2010-01-07 11:03:10 +000079#if !(__GLIBC_PREREQ(2, 7))
80#define CPU_FREE(ptr) free(ptr)
81#endif
82
subrata_modak5a4cf272008-08-22 21:09:58 +000083void cleanup(void);
84void setup(void);
85static inline int getcpu(unsigned int *, unsigned int *, void *);
Mike Frysingerc57fba52014-04-09 18:56:30 -040086unsigned int set_cpu_affinity(void);
subrata_modak5a4cf272008-08-22 21:09:58 +000087unsigned int get_nodeid(unsigned int);
subrata_modak08216ea2010-01-07 11:03:10 +000088unsigned int max_cpuid(size_t, cpu_set_t *);
subrata_modak4bb656a2009-02-26 12:02:09 +000089
subrata_modak56207ce2009-03-23 13:35:39 +000090char *TCID = "getcpu01";
subrata_modak5a4cf272008-08-22 21:09:58 +000091int TST_TOTAL = 1;
subrata_modak5a4cf272008-08-22 21:09:58 +000092
subrata_modak5a4cf272008-08-22 21:09:58 +000093int main(int ac, char **av)
94{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020095 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020096 const char *msg;
subrata_modak56207ce2009-03-23 13:35:39 +000097 unsigned int cpu_id, node_id = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +000098 unsigned int cpu_set;
subrata_modak56207ce2009-03-23 13:35:39 +000099#ifdef __i386__
subrata_modak5a4cf272008-08-22 21:09:58 +0000100 unsigned int node_set;
subrata_modak56207ce2009-03-23 13:35:39 +0000101#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000102
103 /* Check For Kernel Version */
subrata_modak56207ce2009-03-23 13:35:39 +0000104 if (((tst_kvercmp(2, 6, 20)) < 0) || !(sys_support)) {
105 tst_resm(TCONF, "This test can only run on kernels that are ");
106 tst_resm(TCONF,
107 "2.6.20 and higher and glibc version 2.6 and above");
108 tst_resm(TCONF, "Currently the test case has been");
109 tst_resm(TCONF, "developed only for i386 and x86_64");
110 exit(0);
111 }
subrata_modak5a4cf272008-08-22 21:09:58 +0000112
Garrett Cooper45e285d2010-11-22 12:19:25 -0800113 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800114 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modakbdbaec52009-02-26 12:14:51 +0000115
subrata_modak56207ce2009-03-23 13:35:39 +0000116 setup(); /* global setup */
subrata_modak5a4cf272008-08-22 21:09:58 +0000117
118 /* The following loop checks looping state if -i option given */
119
120 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800121 /* reset tst_count in case we are looping */
122 tst_count = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +0000123
124 /* call the system call with the TEST() macro */
125 cpu_set = set_cpu_affinity();
subrata_modak56207ce2009-03-23 13:35:39 +0000126#ifdef __i386__
127 node_set = get_nodeid(cpu_set);
128#endif
129 TEST(getcpu(&cpu_id, &node_id, NULL));
130 if (TEST_RETURN == 0) {
131 if (cpu_id != cpu_set) {
132 tst_resm(TFAIL, "getcpu() returned wrong value"
133 " expected cpuid:%d, returned value cpuid: %d",
134 cpu_set, cpu_id);
Garrett Cooper2c282152010-12-16 00:55:50 -0800135
subrata_modak4bb656a2009-02-26 12:02:09 +0000136 }
subrata_modak56207ce2009-03-23 13:35:39 +0000137#ifdef __i386__
138 else if (node_id != node_set) {
139 tst_resm(TFAIL, "getcpu() returned wrong value"
140 " expected node id:%d returned node id:%d",
141 node_set, node_id);
Garrett Cooper2c282152010-12-16 00:55:50 -0800142
subrata_modak56207ce2009-03-23 13:35:39 +0000143 }
144#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000145 else
subrata_modak56207ce2009-03-23 13:35:39 +0000146 tst_resm(TPASS, "getcpu() returned proper"
147 " cpuid:%d, node id:%d", cpu_id,
148 node_id);
subrata_modak5a4cf272008-08-22 21:09:58 +0000149 } else {
subrata_modak4bb656a2009-02-26 12:02:09 +0000150 tst_resm(TFAIL, "getcpu() Failed, errno=%d:%s",
subrata_modak56207ce2009-03-23 13:35:39 +0000151 TEST_ERRNO, strerror(TEST_ERRNO));
Garrett Cooper2c282152010-12-16 00:55:50 -0800152
subrata_modak5a4cf272008-08-22 21:09:58 +0000153 }
154 }
155
156 cleanup();
157
Garrett Cooper7d0a4a52010-12-16 10:05:08 -0800158 tst_exit();
subrata_modak5a4cf272008-08-22 21:09:58 +0000159}
160
subrata_modak4bb656a2009-02-26 12:02:09 +0000161/*
subrata_modak5a4cf272008-08-22 21:09:58 +0000162 * getcpu() - calls the system call
163 */
subrata_modak56207ce2009-03-23 13:35:39 +0000164static inline int getcpu(unsigned *cpu_id, unsigned *node_id,
165 void *cache_struct)
subrata_modak5a4cf272008-08-22 21:09:58 +0000166{
subrata_modak56207ce2009-03-23 13:35:39 +0000167#if defined(__i386__)
168 return syscall(318, cpu_id, node_id, cache_struct);
169#elif __GLIBC_PREREQ(2,6)
170 *cpu_id = sched_getcpu();
171#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000172 return 0;
173}
174
subrata_modak5a4cf272008-08-22 21:09:58 +0000175/*
176 * setup() - performs all the ONE TIME setup for this test.
177 */
subrata_modak56207ce2009-03-23 13:35:39 +0000178void setup(void)
subrata_modak5a4cf272008-08-22 21:09:58 +0000179{
Garrett Cooper2c282152010-12-16 00:55:50 -0800180
subrata_modakbdbaec52009-02-26 12:14:51 +0000181 /* ?? */
Garrett Cooper2c282152010-12-16 00:55:50 -0800182
subrata_modak5a4cf272008-08-22 21:09:58 +0000183 TEST_PAUSE;
184}
185
186/*
187 * This will set the affinity to max cpu on which process can run
188 * and return that cpu id to the calling process
189 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400190unsigned int set_cpu_affinity(void)
subrata_modak5a4cf272008-08-22 21:09:58 +0000191{
192 unsigned cpu_max;
subrata_modak08216ea2010-01-07 11:03:10 +0000193 cpu_set_t *set;
194 size_t size;
195 int nrcpus = 1024;
196#if __GLIBC_PREREQ(2, 7)
197realloc:
198 set = CPU_ALLOC(nrcpus);
199#else
200 set = malloc(sizeof(cpu_set_t));
201#endif
202 if (set == NULL) {
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100203 tst_brkm(TFAIL, NULL, "CPU_ALLOC:errno:%d", errno);
subrata_modak5a4cf272008-08-22 21:09:58 +0000204 }
subrata_modak08216ea2010-01-07 11:03:10 +0000205#if __GLIBC_PREREQ(2, 7)
206 size = CPU_ALLOC_SIZE(nrcpus);
207 CPU_ZERO_S(size, set);
208#else
209 size = sizeof(cpu_set_t);
210 CPU_ZERO(set);
211#endif
212 if (sched_getaffinity(0, size, set) < 0) {
213 CPU_FREE(set);
214#if __GLIBC_PREREQ(2, 7)
215 if (errno == EINVAL && nrcpus < (1024 << 8)) {
216 nrcpus = nrcpus << 2;
217 goto realloc;
218 }
219#else
220 if (errno == EINVAL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800221 tst_resm(TFAIL,
222 "NR_CPUS of the kernel is more than 1024, so we'd better use a newer glibc(>= 2.7)");
subrata_modak08216ea2010-01-07 11:03:10 +0000223 else
224#endif
225 tst_resm(TFAIL, "sched_getaffinity:errno:%d", errno);
226 tst_exit();
227 }
228 cpu_max = max_cpuid(size, set);
229#if __GLIBC_PREREQ(2, 7)
230 CPU_ZERO_S(size, set);
231 CPU_SET_S(cpu_max, size, set);
232#else
233 CPU_ZERO(set);
234 CPU_SET(cpu_max, set);
235#endif
236 if (sched_setaffinity(0, size, set) < 0) {
237 CPU_FREE(set);
Cyril Hrubis526fdf82014-12-04 14:35:01 +0100238 tst_brkm(TFAIL, NULL, "sched_setaffinity:errno:%d", errno);
subrata_modak5a4cf272008-08-22 21:09:58 +0000239 }
subrata_modak08216ea2010-01-07 11:03:10 +0000240 CPU_FREE(set);
subrata_modakbdbaec52009-02-26 12:14:51 +0000241 return cpu_max;
242}
subrata_modak5a4cf272008-08-22 21:09:58 +0000243
244/*
245 * Return the maximum cpu id
246 */
247#define BITS_PER_BYTE 8
subrata_modak08216ea2010-01-07 11:03:10 +0000248unsigned int max_cpuid(size_t size, cpu_set_t * set)
subrata_modak5a4cf272008-08-22 21:09:58 +0000249{
250 unsigned int index, max = 0;
subrata_modak08216ea2010-01-07 11:03:10 +0000251 for (index = 0; index < size * BITS_PER_BYTE; index++)
252#if __GLIBC_PREREQ(2, 7)
253 if (CPU_ISSET_S(index, size, set))
254#else
subrata_modak56207ce2009-03-23 13:35:39 +0000255 if (CPU_ISSET(index, set))
subrata_modak08216ea2010-01-07 11:03:10 +0000256#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000257 max = index;
subrata_modak5a4cf272008-08-22 21:09:58 +0000258 return max;
259}
260
subrata_modak5a4cf272008-08-22 21:09:58 +0000261/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000262 * get_nodeid(cpuid) - This will return the node to which selected cpu belongs
subrata_modak5a4cf272008-08-22 21:09:58 +0000263 */
subrata_modak56207ce2009-03-23 13:35:39 +0000264unsigned int get_nodeid(unsigned int cpu_id)
subrata_modak5a4cf272008-08-22 21:09:58 +0000265{
subrata_modak56207ce2009-03-23 13:35:39 +0000266 DIR *directory_parent, *directory_node;
267 struct dirent *de, *dn;
subrata_modak5a4cf272008-08-22 21:09:58 +0000268 char directory_path[255];
269 unsigned int cpu;
subrata_modak56207ce2009-03-23 13:35:39 +0000270 int node_id = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +0000271
subrata_modak56207ce2009-03-23 13:35:39 +0000272 directory_parent = opendir("/sys/devices/system/node");
273 if (!directory_parent) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800274 tst_resm(TCONF,
275 "/sys not mounted or not a numa system. Assuming one node");
276 tst_resm(TCONF,
277 "Error opening: /sys/devices/system/node :%s",
subrata_modak56207ce2009-03-23 13:35:39 +0000278 strerror(errno));
279 return 0; //By Default assume it to belong to node Zero
280 } else {
281 while ((de = readdir(directory_parent)) != NULL) {
282 if (strncmp(de->d_name, "node", 4))
subrata_modak5a4cf272008-08-22 21:09:58 +0000283 continue;
subrata_modak56207ce2009-03-23 13:35:39 +0000284 sprintf(directory_path, "/sys/devices/system/node/%s",
285 de->d_name);
286 directory_node = opendir(directory_path);
287 while ((dn = readdir(directory_node)) != NULL) {
288 if (strncmp(dn->d_name, "cpu", 3))
289 continue;
290 cpu = strtoul(dn->d_name + 3, NULL, 0);
291 if (cpu == cpu_id) {
292 node_id =
293 strtoul(de->d_name + 4, NULL, 0);
294 break;
295 }
subrata_modak5a4cf272008-08-22 21:09:58 +0000296 }
subrata_modak56207ce2009-03-23 13:35:39 +0000297 closedir(directory_node);
298 }
299 closedir(directory_parent);
300 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000301 return node_id;
subrata_modak5a4cf272008-08-22 21:09:58 +0000302}
303
304/*
305 * cleanup() - performs all the ONE TIME cleanup for this test at completion
306 * or premature exit.
307 */
subrata_modak56207ce2009-03-23 13:35:39 +0000308void cleanup(void)
subrata_modak5a4cf272008-08-22 21:09:58 +0000309{
Garrett Cooper2c282152010-12-16 00:55:50 -0800310
Chris Dearmanec6edca2012-10-17 19:54:01 -0700311}