cpuset_cpu_hog.c revision 0aaaf37500ec21d4e673c8f36f9934346269ac21
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 37char *TCID = "cpuset_cpu_hog"; 38int 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 52static int nprocs; 53static 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 */ 61int 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 81void sighandler1(UNUSED int signo) 82{ 83} 84 85void sighandler2(UNUSED int signo) 86{ 87 end = 1; 88} 89 90void 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 112void 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 */ 161int cpu_hog(void) 162{ 163 double f = 2744545.34456455; 164 sigset_t sigset; 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(&sigset) < 0) { 184 ret = -1; 185 goto err2; 186 } 187 188 sigsuspend(&sigset); 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 217err2: 218 bitmask_free(cpumask); 219err1: 220 cpuset_free(cp); 221 return ret; 222} 223 224int 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 247int main(int argc, char **argv) 248{ 249 int i = 0; 250 pid_t pid; 251 pid_t *childpids = NULL; 252 sigset_t sigset; 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(&sigset) < 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(&sigset); 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(&sigset) < 0) 298 ret = -1; 299 else 300 sigsuspend(&sigset); 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 */ 324int main(void) 325{ 326 printf("System doesn't have required mempolicy support\n"); 327 return 1; 328} 329#endif 330