blob: 437f441faec1d6aa5962278ee792dd58a24b74ee [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"
61#include "usctest.h"
62#include <sys/types.h>
63#include <dirent.h>
64
65#if defined(__i386__) || defined(__x86_64__)
subrata_modak56207ce2009-03-23 13:35:39 +000066#if __GLIBC_PREREQ(2,6)
67#if defined(__x86_64__)
68#include <utmpx.h>
69#endif
70int sys_support = 1;
71#elif defined(__i386__)
72int sys_support = 1;
73#else
74int sys_support = 0;
75#endif
subrata_modak5a4cf272008-08-22 21:09:58 +000076#else
77int sys_support = 0;
78#endif
subrata_modakbdbaec52009-02-26 12:14:51 +000079
subrata_modak08216ea2010-01-07 11:03:10 +000080#if !(__GLIBC_PREREQ(2, 7))
81#define CPU_FREE(ptr) free(ptr)
82#endif
83
subrata_modak5a4cf272008-08-22 21:09:58 +000084void cleanup(void);
85void setup(void);
86static inline int getcpu(unsigned int *, unsigned int *, void *);
87unsigned int set_cpu_affinity();
88unsigned int get_nodeid(unsigned int);
subrata_modak08216ea2010-01-07 11:03:10 +000089unsigned int max_cpuid(size_t, cpu_set_t *);
subrata_modak4bb656a2009-02-26 12:02:09 +000090
subrata_modak56207ce2009-03-23 13:35:39 +000091char *TCID = "getcpu01";
subrata_modak5a4cf272008-08-22 21:09:58 +000092int TST_TOTAL = 1;
subrata_modak5a4cf272008-08-22 21:09:58 +000093
subrata_modak5a4cf272008-08-22 21:09:58 +000094int main(int ac, char **av)
95{
Cyril Hrubis89af32a2012-10-24 16:39:11 +020096 int lc;
97 char *msg;
subrata_modak56207ce2009-03-23 13:35:39 +000098 unsigned int cpu_id, node_id = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +000099 unsigned int cpu_set;
subrata_modak56207ce2009-03-23 13:35:39 +0000100#ifdef __i386__
subrata_modak5a4cf272008-08-22 21:09:58 +0000101 unsigned int node_set;
subrata_modak56207ce2009-03-23 13:35:39 +0000102#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000103
104 /* Check For Kernel Version */
subrata_modak56207ce2009-03-23 13:35:39 +0000105 if (((tst_kvercmp(2, 6, 20)) < 0) || !(sys_support)) {
106 tst_resm(TCONF, "This test can only run on kernels that are ");
107 tst_resm(TCONF,
108 "2.6.20 and higher and glibc version 2.6 and above");
109 tst_resm(TCONF, "Currently the test case has been");
110 tst_resm(TCONF, "developed only for i386 and x86_64");
111 exit(0);
112 }
subrata_modak5a4cf272008-08-22 21:09:58 +0000113
Garrett Cooper45e285d2010-11-22 12:19:25 -0800114 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800115 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
subrata_modakbdbaec52009-02-26 12:14:51 +0000116
subrata_modak56207ce2009-03-23 13:35:39 +0000117 setup(); /* global setup */
subrata_modak5a4cf272008-08-22 21:09:58 +0000118
119 /* The following loop checks looping state if -i option given */
120
121 for (lc = 0; TEST_LOOPING(lc); lc++) {
Caspar Zhangd59a6592013-03-07 14:59:12 +0800122 /* reset tst_count in case we are looping */
123 tst_count = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +0000124
125 /* call the system call with the TEST() macro */
126 cpu_set = set_cpu_affinity();
subrata_modak56207ce2009-03-23 13:35:39 +0000127#ifdef __i386__
128 node_set = get_nodeid(cpu_set);
129#endif
130 TEST(getcpu(&cpu_id, &node_id, NULL));
131 if (TEST_RETURN == 0) {
132 if (cpu_id != cpu_set) {
133 tst_resm(TFAIL, "getcpu() returned wrong value"
134 " expected cpuid:%d, returned value cpuid: %d",
135 cpu_set, cpu_id);
Garrett Cooper2c282152010-12-16 00:55:50 -0800136
subrata_modak4bb656a2009-02-26 12:02:09 +0000137 }
subrata_modak56207ce2009-03-23 13:35:39 +0000138#ifdef __i386__
139 else if (node_id != node_set) {
140 tst_resm(TFAIL, "getcpu() returned wrong value"
141 " expected node id:%d returned node id:%d",
142 node_set, node_id);
Garrett Cooper2c282152010-12-16 00:55:50 -0800143
subrata_modak56207ce2009-03-23 13:35:39 +0000144 }
145#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000146 else
subrata_modak56207ce2009-03-23 13:35:39 +0000147 tst_resm(TPASS, "getcpu() returned proper"
148 " cpuid:%d, node id:%d", cpu_id,
149 node_id);
subrata_modak5a4cf272008-08-22 21:09:58 +0000150 } else {
subrata_modak4bb656a2009-02-26 12:02:09 +0000151 tst_resm(TFAIL, "getcpu() Failed, errno=%d:%s",
subrata_modak56207ce2009-03-23 13:35:39 +0000152 TEST_ERRNO, strerror(TEST_ERRNO));
Garrett Cooper2c282152010-12-16 00:55:50 -0800153
subrata_modak5a4cf272008-08-22 21:09:58 +0000154 }
155 }
156
157 cleanup();
158
Garrett Cooper7d0a4a52010-12-16 10:05:08 -0800159 tst_exit();
subrata_modak5a4cf272008-08-22 21:09:58 +0000160}
161
subrata_modak4bb656a2009-02-26 12:02:09 +0000162/*
subrata_modak5a4cf272008-08-22 21:09:58 +0000163 * getcpu() - calls the system call
164 */
subrata_modak56207ce2009-03-23 13:35:39 +0000165static inline int getcpu(unsigned *cpu_id, unsigned *node_id,
166 void *cache_struct)
subrata_modak5a4cf272008-08-22 21:09:58 +0000167{
subrata_modak56207ce2009-03-23 13:35:39 +0000168#if defined(__i386__)
169 return syscall(318, cpu_id, node_id, cache_struct);
170#elif __GLIBC_PREREQ(2,6)
171 *cpu_id = sched_getcpu();
172#endif
subrata_modak5a4cf272008-08-22 21:09:58 +0000173 return 0;
174}
175
subrata_modak5a4cf272008-08-22 21:09:58 +0000176/*
177 * setup() - performs all the ONE TIME setup for this test.
178 */
subrata_modak56207ce2009-03-23 13:35:39 +0000179void setup(void)
subrata_modak5a4cf272008-08-22 21:09:58 +0000180{
Garrett Cooper2c282152010-12-16 00:55:50 -0800181
subrata_modakbdbaec52009-02-26 12:14:51 +0000182 /* ?? */
Garrett Cooper2c282152010-12-16 00:55:50 -0800183
subrata_modak5a4cf272008-08-22 21:09:58 +0000184 TEST_PAUSE;
185}
186
187/*
188 * This will set the affinity to max cpu on which process can run
189 * and return that cpu id to the calling process
190 */
subrata_modak56207ce2009-03-23 13:35:39 +0000191unsigned int set_cpu_affinity()
subrata_modak5a4cf272008-08-22 21:09:58 +0000192{
193 unsigned cpu_max;
subrata_modak08216ea2010-01-07 11:03:10 +0000194 cpu_set_t *set;
195 size_t size;
196 int nrcpus = 1024;
197#if __GLIBC_PREREQ(2, 7)
198realloc:
199 set = CPU_ALLOC(nrcpus);
200#else
201 set = malloc(sizeof(cpu_set_t));
202#endif
203 if (set == NULL) {
204 tst_resm(TFAIL, "CPU_ALLOC:errno:%d", errno);
subrata_modak56207ce2009-03-23 13:35:39 +0000205 tst_exit();
subrata_modak5a4cf272008-08-22 21:09:58 +0000206 }
subrata_modak08216ea2010-01-07 11:03:10 +0000207#if __GLIBC_PREREQ(2, 7)
208 size = CPU_ALLOC_SIZE(nrcpus);
209 CPU_ZERO_S(size, set);
210#else
211 size = sizeof(cpu_set_t);
212 CPU_ZERO(set);
213#endif
214 if (sched_getaffinity(0, size, set) < 0) {
215 CPU_FREE(set);
216#if __GLIBC_PREREQ(2, 7)
217 if (errno == EINVAL && nrcpus < (1024 << 8)) {
218 nrcpus = nrcpus << 2;
219 goto realloc;
220 }
221#else
222 if (errno == EINVAL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800223 tst_resm(TFAIL,
224 "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 +0000225 else
226#endif
227 tst_resm(TFAIL, "sched_getaffinity:errno:%d", errno);
228 tst_exit();
229 }
230 cpu_max = max_cpuid(size, set);
231#if __GLIBC_PREREQ(2, 7)
232 CPU_ZERO_S(size, set);
233 CPU_SET_S(cpu_max, size, set);
234#else
235 CPU_ZERO(set);
236 CPU_SET(cpu_max, set);
237#endif
238 if (sched_setaffinity(0, size, set) < 0) {
239 CPU_FREE(set);
subrata_modak56207ce2009-03-23 13:35:39 +0000240 tst_resm(TFAIL, "sched_setaffinity:errno:%d", errno);
241 tst_exit();
subrata_modak5a4cf272008-08-22 21:09:58 +0000242 }
subrata_modak08216ea2010-01-07 11:03:10 +0000243 CPU_FREE(set);
subrata_modakbdbaec52009-02-26 12:14:51 +0000244 return cpu_max;
245}
subrata_modak5a4cf272008-08-22 21:09:58 +0000246
247/*
248 * Return the maximum cpu id
249 */
250#define BITS_PER_BYTE 8
subrata_modak08216ea2010-01-07 11:03:10 +0000251unsigned int max_cpuid(size_t size, cpu_set_t * set)
subrata_modak5a4cf272008-08-22 21:09:58 +0000252{
253 unsigned int index, max = 0;
subrata_modak08216ea2010-01-07 11:03:10 +0000254 for (index = 0; index < size * BITS_PER_BYTE; index++)
255#if __GLIBC_PREREQ(2, 7)
256 if (CPU_ISSET_S(index, size, set))
257#else
subrata_modak56207ce2009-03-23 13:35:39 +0000258 if (CPU_ISSET(index, set))
subrata_modak08216ea2010-01-07 11:03:10 +0000259#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000260 max = index;
subrata_modak5a4cf272008-08-22 21:09:58 +0000261 return max;
262}
263
subrata_modak5a4cf272008-08-22 21:09:58 +0000264/*
subrata_modak4bb656a2009-02-26 12:02:09 +0000265 * get_nodeid(cpuid) - This will return the node to which selected cpu belongs
subrata_modak5a4cf272008-08-22 21:09:58 +0000266 */
subrata_modak56207ce2009-03-23 13:35:39 +0000267unsigned int get_nodeid(unsigned int cpu_id)
subrata_modak5a4cf272008-08-22 21:09:58 +0000268{
subrata_modak56207ce2009-03-23 13:35:39 +0000269 DIR *directory_parent, *directory_node;
270 struct dirent *de, *dn;
subrata_modak5a4cf272008-08-22 21:09:58 +0000271 char directory_path[255];
272 unsigned int cpu;
subrata_modak56207ce2009-03-23 13:35:39 +0000273 int node_id = 0;
subrata_modak5a4cf272008-08-22 21:09:58 +0000274
subrata_modak56207ce2009-03-23 13:35:39 +0000275 directory_parent = opendir("/sys/devices/system/node");
276 if (!directory_parent) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800277 tst_resm(TCONF,
278 "/sys not mounted or not a numa system. Assuming one node");
279 tst_resm(TCONF,
280 "Error opening: /sys/devices/system/node :%s",
subrata_modak56207ce2009-03-23 13:35:39 +0000281 strerror(errno));
282 return 0; //By Default assume it to belong to node Zero
283 } else {
284 while ((de = readdir(directory_parent)) != NULL) {
285 if (strncmp(de->d_name, "node", 4))
subrata_modak5a4cf272008-08-22 21:09:58 +0000286 continue;
subrata_modak56207ce2009-03-23 13:35:39 +0000287 sprintf(directory_path, "/sys/devices/system/node/%s",
288 de->d_name);
289 directory_node = opendir(directory_path);
290 while ((dn = readdir(directory_node)) != NULL) {
291 if (strncmp(dn->d_name, "cpu", 3))
292 continue;
293 cpu = strtoul(dn->d_name + 3, NULL, 0);
294 if (cpu == cpu_id) {
295 node_id =
296 strtoul(de->d_name + 4, NULL, 0);
297 break;
298 }
subrata_modak5a4cf272008-08-22 21:09:58 +0000299 }
subrata_modak56207ce2009-03-23 13:35:39 +0000300 closedir(directory_node);
301 }
302 closedir(directory_parent);
303 }
subrata_modakbdbaec52009-02-26 12:14:51 +0000304 return node_id;
subrata_modak5a4cf272008-08-22 21:09:58 +0000305}
306
307/*
308 * cleanup() - performs all the ONE TIME cleanup for this test at completion
309 * or premature exit.
310 */
subrata_modak56207ce2009-03-23 13:35:39 +0000311void cleanup(void)
subrata_modak5a4cf272008-08-22 21:09:58 +0000312{
313 /*
314 * print timing stats if that option was specified.
315 * print errno log if that option was specified.
316 */
317 TEST_CLEANUP;
Garrett Cooper2c282152010-12-16 00:55:50 -0800318
Chris Dearmanec6edca2012-10-17 19:54:01 -0700319}