• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /*                                                                            */
3 /* Copyright (c) 2009 FUJITSU LIMITED                                         */
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 02110-1301 USA    */
18 /*                                                                            */
19 /* Author: Miao Xie <miaox@cn.fujitsu.com>                                    */
20 /*                                                                            */
21 /******************************************************************************/
22 
23 #include "config.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <math.h>
29 #include <err.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 
37 char *TCID = "cpuset_cpu_hog";
38 int TST_TOTAL = 1;
39 
40 #if HAVE_LINUX_MEMPOLICY_H
41 
42 #include "../cpuset_lib/common.h"
43 #include "../cpuset_lib/bitmask.h"
44 #include "../cpuset_lib/cpuset.h"
45 
46 #define MAX_NPROCS	1000
47 #define USAGE	("Usage: %s [-p nprocs] [-h]\n"		\
48 		 "\t-p nprocs\n"					\
49 		 "\t\tThe num of the procs. [Default = 2 * nr_cpus]\n"	\
50 		 "\t-h\tHelp.\n")
51 
52 static int nprocs;
53 static volatile int end;
54 
55 /*
56  * report executing result to the parent by fifo
57  *     "0\n" - everything is OK
58  *     "1\n" - everything is OK, but break the test
59  *     "2\n" - something failed
60  */
report_result(char str[])61 int report_result(char str[])
62 {
63 	int fd;
64 
65 	fd = open("./myfifo", O_WRONLY);
66 	if (fd == -1) {
67 		warn("open fifo failed");
68 		return -1;
69 	}
70 
71 	if (write(fd, str, strlen(str)) == -1) {
72 		warn("write fifo failed.");
73 		close(fd);
74 		return -1;
75 	}
76 
77 	close(fd);
78 	return 0;
79 }
80 
sighandler1(UNUSED int signo)81 void sighandler1(UNUSED int signo)
82 {
83 }
84 
sighandler2(UNUSED int signo)85 void sighandler2(UNUSED int signo)
86 {
87 	end = 1;
88 }
89 
usage(char * prog_name,int status)90 void usage(char *prog_name, int status)
91 {
92 	FILE *output = NULL;
93 
94 	if (prog_name == NULL)
95 		prog_name = "cpu-hog";
96 
97 	if (status)
98 		output = stderr;
99 	else
100 		output = stdout;
101 
102 	fprintf(output, USAGE, prog_name);
103 
104 	if (status)
105 		report_result("2\n");
106 	else
107 		report_result("1\n");
108 
109 	exit(status);
110 }
111 
checkopt(int argc,char ** argv)112 void checkopt(int argc, char **argv)
113 {
114 	char c = '\0';
115 	char *endptr = NULL;
116 	long nr_cpus = 0;
117 	long opt_value = 0;
118 
119 	nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
120 	if (nr_cpus <= 0) {
121 		fprintf(stderr, "Error: sysconf failed\n");
122 		report_result("2\n");
123 		exit(1);
124 	}
125 
126 	while ((c = getopt(argc, argv, "p:h")) != -1) {
127 		switch (c) {
128 		case 'p':
129 			if (optarg[0] == '-' && !isdigit(optarg[1]))
130 				OPT_MISSING(argv[0], c);
131 			else {
132 				opt_value = strtol(optarg, &endptr, DECIMAL);
133 				if (errno || (endptr != NULL && *endptr != '\0')
134 				    || opt_value <= 0 || opt_value > MAX_NPROCS)
135 					ARG_WRONG(argv[0], c, optarg);
136 				nprocs = atoi(optarg);
137 			}
138 			break;
139 		case 'h':	/* usage message */
140 			usage(argv[0], 0);
141 			break;
142 		default:
143 			usage(argv[0], 1);
144 			break;
145 		}
146 	}
147 
148 	if (nprocs == 0)
149 		nprocs = 2 * nr_cpus;
150 }
151 
152 /*
153  * hog the cpu time and check the cpu which the task is running on is in the
154  * cpus of the cpuset or not.
155  *
156  * return value: 0  - success.
157  *               1  - the cpu which the task is running on isn't in the cpus
158  *                    of the cpuset.
159  *               -1 - failure for other reason.
160  */
cpu_hog(void)161 int cpu_hog(void)
162 {
163 	double f = 2744545.34456455;
164 	sigset_t signalset;
165 	struct cpuset *cp = NULL;
166 	struct bitmask *cpumask = NULL;
167 	int cpu;
168 	int nbits;
169 	int ret = 0;
170 
171 	nbits = cpuset_cpus_nbits();
172 
173 	cp = cpuset_alloc();
174 	if (cp == NULL)
175 		return -1;
176 
177 	cpumask = bitmask_alloc(nbits);
178 	if (cpumask == NULL) {
179 		ret = -1;
180 		goto err1;
181 	}
182 
183 	if (sigemptyset(&signalset) < 0) {
184 		ret = -1;
185 		goto err2;
186 	}
187 
188 	sigsuspend(&signalset);
189 
190 	if (cpuset_cpusetofpid(cp, 0) < 0) {
191 		ret = -1;
192 		goto err2;
193 	}
194 	if (cpuset_getcpus(cp, cpumask) != 0) {
195 		ret = -1;
196 		goto err2;
197 	}
198 
199 	while (!end) {
200 		f = sqrt(f * f);
201 		cpu = cpuset_latestcpu(0);
202 		if (cpu < 0) {
203 			warn("get latest cpu failed.\n");
204 			ret = -1;
205 			goto err2;
206 		}
207 		if (!bitmask_isbitset(cpumask, cpu)) {
208 			char str[50];
209 			bitmask_displaylist(str, 50, cpumask);
210 			warn("the task(%d) is running on the cpu(%d) excluded"
211 			     " by cpuset(cpus: %s)\n", getpid(), cpu, str);
212 			ret = 1;
213 			goto err2;
214 		}
215 	}
216 
217 err2:
218 	bitmask_free(cpumask);
219 err1:
220 	cpuset_free(cp);
221 	return ret;
222 }
223 
initialize(void)224 int initialize(void)
225 {
226 	struct sigaction sa1, sa2;
227 
228 	sa1.sa_handler = sighandler1;
229 	if (sigemptyset(&sa1.sa_mask) < 0)
230 		return -1;
231 
232 	sa1.sa_flags = 0;
233 	if (sigaction(SIGUSR1, &sa1, NULL) < 0)
234 		return -1;
235 
236 	sa2.sa_handler = sighandler2;
237 	if (sigemptyset(&sa2.sa_mask) < 0)
238 		return -1;
239 
240 	sa2.sa_flags = 0;
241 	if (sigaction(SIGUSR2, &sa2, NULL) < 0)
242 		return -1;
243 
244 	return 0;
245 }
246 
main(int argc,char ** argv)247 int main(int argc, char **argv)
248 {
249 	int i = 0;
250 	pid_t pid;
251 	pid_t *childpids = NULL;
252 	sigset_t signalset;
253 	int status = 0;
254 	int ret = 0;
255 
256 	checkopt(argc, argv);
257 	if (initialize()) {
258 		warn("initialize failed");
259 		report_result("2\n");
260 		exit(EXIT_FAILURE);
261 	}
262 
263 	if (sigemptyset(&signalset) < 0) {
264 		warn("sigemptyset failed");
265 		report_result("2\n");
266 		exit(EXIT_FAILURE);
267 	}
268 
269 	childpids = malloc((nprocs) * sizeof(pid_t));
270 	if (childpids == NULL) {
271 		warn("alloc for child pids failed");
272 		report_result("2\n");
273 		exit(EXIT_FAILURE);
274 	}
275 	memset(childpids, 0, (nprocs) * sizeof(pid_t));
276 
277 	report_result("0\n");
278 	sigsuspend(&signalset);
279 	for (; i < nprocs; i++) {
280 		pid = fork();
281 		if (pid == -1) {
282 			while (--i >= 0)
283 				kill(childpids[i], SIGKILL);
284 			warn("fork test tasks failed");
285 			report_result("2\n");
286 			exit(EXIT_FAILURE);
287 		} else if (!pid) {
288 			ret = cpu_hog();
289 			exit(ret);
290 		}
291 		childpids[i] = pid;
292 	}
293 
294 	report_result("0\n");
295 
296 	while (!end) {
297 		if (sigemptyset(&signalset) < 0)
298 			ret = -1;
299 		else
300 			sigsuspend(&signalset);
301 
302 		if (ret || end) {
303 			for (i = 0; i < nprocs; i++) {
304 				kill(childpids[i], SIGUSR2);
305 			}
306 			break;
307 		} else {
308 			for (i = 0; i < nprocs; i++) {
309 				kill(childpids[i], SIGUSR1);
310 			}
311 		}
312 	}
313 	for (i = 0; i < nprocs; i++) {
314 		wait(&status);
315 		if (status)
316 			ret = EXIT_FAILURE;
317 	}
318 
319 	free(childpids);
320 	return ret;
321 }
322 
323 #else /* ! HAVE_LINUX_MEMPOLICY_H */
main(void)324 int main(void)
325 {
326 	printf("System doesn't have required mempolicy support\n");
327 	return 1;
328 }
329 #endif
330