cpuset_memory_test.c revision c5d8805b5dc5cf79b729ff3b60617649e2f9ea0c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 18/* */ 19/* Author: Miao Xie <miaox@cn.fujitsu.com> */ 20/* */ 21/******************************************************************************/ 22 23#include <unistd.h> 24#include <stdlib.h> 25#include <stdio.h> 26#include <signal.h> 27#include <err.h> 28#include <limits.h> 29#include <getopt.h> 30#include <string.h> 31#include <fcntl.h> 32#include <sys/types.h> 33#include <sys/stat.h> 34#include <sys/mman.h> 35#include <sys/shm.h> 36#include <syscall.h> 37#include <pthread.h> 38 39#include "../cpuset_lib/cpuset.h" 40 41char *TCID = "cpuset_memory_test"; 42int TST_TOTAL = 1; 43 44int fd; 45int flag_exit; 46 47int opt_mmap_anon; 48int opt_mmap_file; 49int opt_mmap_lock1; 50int opt_mmap_lock2; 51int opt_shm; 52int opt_hugepage; 53int opt_check; /* check node when munmap memory (only for mmap_anon()) */ 54int opt_thread; 55 56int key_id; /* used with opt_shm */ 57unsigned long memsize; 58 59#define FILE_HUGEPAGE "/hugetlb/hugepagefile" 60 61#define MMAP_ANON (SCHAR_MAX + 1) 62#define MMAP_FILE (SCHAR_MAX + 2) 63#define MMAP_LOCK1 (SCHAR_MAX + 3) 64#define MMAP_LOCK2 (SCHAR_MAX + 4) 65#define SHM (SCHAR_MAX + 5) 66#define HUGEPAGE (SCHAR_MAX + 6) 67#define CHECK (SCHAR_MAX + 7) 68#define THREAD (SCHAR_MAX + 8) 69 70const struct option long_opts[] = { 71 { "mmap-anon", 0, NULL, MMAP_ANON }, 72 { "mmap-file", 0, NULL, MMAP_FILE }, 73 { "mmap-lock1", 0, NULL, MMAP_LOCK1 }, 74 { "mmap-lock2", 0, NULL, MMAP_LOCK2 }, 75 { "shm", 0, NULL, SHM }, 76 { "hugepage", 0, NULL, HUGEPAGE }, 77 { "check", 0, NULL, CHECK }, 78 { "thread", 0, NULL, THREAD }, 79 { "size", 1, NULL, 's' }, 80 { "key", 1, NULL, 'k' }, 81 { NULL, 0, NULL, 0 }, 82}; 83 84/* 85 * process_options: read options from user input 86 */ 87void process_options(int argc, char *argv[]) 88{ 89 int c; 90 char *end; 91 92 while (1) { 93 c = getopt_long(argc, argv, "s:k:", long_opts, NULL); 94 if (c == -1) 95 break; 96 97 switch (c) { 98 case 's': 99 memsize = strtoul(optarg, &end, 10); 100 if (*end != '\0') 101 errx(1, "wrong -s argument!"); 102 break; 103 case 'k': 104 key_id = atoi(optarg); 105 break; 106 case MMAP_ANON: 107 opt_mmap_anon = 1; 108 break; 109 case MMAP_FILE: 110 opt_mmap_file = 1; 111 break; 112 case MMAP_LOCK1: 113 opt_mmap_lock1 = 1; 114 break; 115 case MMAP_LOCK2: 116 opt_mmap_lock2 = 1; 117 break; 118 case SHM: 119 opt_shm = 1; 120 break; 121 case HUGEPAGE: 122 opt_hugepage = 1; 123 break; 124 case CHECK: 125 opt_check = 1; 126 break; 127 case THREAD: 128 opt_thread = 1; 129 break; 130 default: 131 errx(1, "unknown option!\n"); 132 break; 133 } 134 } 135 136 if (!memsize) 137 memsize = getpagesize(); 138} 139 140/* 141 * touch_memory: force allocating phy memory 142 */ 143void touch_memory_and_echo_node(char *p, int size) 144{ 145 int i; 146 int pagesize = getpagesize(); 147 148 for (i = 0; i < size; i += pagesize) 149 p[i] = 0xef; 150 151 printf("%d\n", cpuset_addr2node(p)); 152} 153 154void mmap_anon(int flag_allocated) 155{ 156 static char *p; 157 158 if (!flag_allocated) { 159 p = mmap(NULL, memsize, PROT_WRITE | PROT_READ, 160 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 161 if (p == MAP_FAILED) 162 err(1, "mmap(anonymous) failed"); 163 touch_memory_and_echo_node(p, memsize); 164 } else { 165 if (opt_check) 166 touch_memory_and_echo_node(p, memsize); 167 if (munmap(p, memsize) == -1) 168 err(1, "munmap(anonymous) failed"); 169 } 170} 171 172void mmap_file(int flag_allocated) 173{ 174 static char *p; 175 static int fd_hugepage; 176 int fd_tmp; 177 178 if (!flag_allocated) { 179 if (opt_hugepage) { 180 fd_hugepage = open(FILE_HUGEPAGE, 181 O_CREAT | O_RDWR, 0755); 182 if (fd_hugepage < 0) 183 err(1, "open hugepage file failed"); 184 fd_tmp = fd_hugepage; 185 } else 186 fd_tmp = fd; 187 188 p = mmap(NULL, memsize, PROT_WRITE | PROT_READ, 189 MAP_SHARED, fd_tmp, 0); 190 if (p == MAP_FAILED) { 191 if (opt_hugepage) 192 unlink(FILE_HUGEPAGE); 193 err(1, "mmap(file) failed"); 194 } 195 touch_memory_and_echo_node(p, memsize); 196 } else { 197 if (!munmap(p, memsize) == -1) 198 err(1, "munmap(file) failed"); 199 200 if (opt_hugepage) { 201 close(fd_hugepage); 202 unlink(FILE_HUGEPAGE); 203 } 204 } 205} 206 207void mmap_lock1(int flag_allocated) 208{ 209 static char *p; 210 211 if (!flag_allocated) { 212 p = mmap(NULL, memsize, PROT_WRITE | PROT_READ, 213 MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, 0, 0); 214 if (p == MAP_FAILED) 215 err(1, "mmap(lock) failed"); 216 touch_memory_and_echo_node(p, memsize); 217 } else { 218 if (munmap(p, memsize) == -1) 219 err(1, "munmap(lock) failed"); 220 } 221} 222 223void mmap_lock2(int flag_allocated) 224{ 225 static char *p; 226 227 if (!flag_allocated) { 228 p = mmap(NULL, memsize, PROT_WRITE | PROT_READ, 229 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 230 if (p == MAP_FAILED) 231 err(1, "mmap failed"); 232 233 if (mlock(p, memsize)) 234 err(1, "mlock failed"); 235 touch_memory_and_echo_node(p, memsize); 236 } else { 237 if (!munmap(p, memsize) == -1) 238 err(1, "munmap failed"); 239 } 240} 241 242void shm(int flag_allocated) 243{ 244 static char *p; 245 static int shmid; 246 unsigned long flag; 247 248 key_t key; 249 250 if (!flag_allocated) { 251 flag = IPC_CREAT | SHM_R | SHM_W; 252 if (opt_hugepage) 253 flag |= SHM_HUGETLB; 254 255 key = ftok("/dev/null", key_id); 256 if (key == -1) 257 err(1, "ftok() failed\n"); 258 259 shmid = shmget(key, memsize, flag); 260 if (shmid == -1) 261 err(1, "shmget() failed\n"); 262 shmctl(shmid, IPC_RMID, NULL); 263 264 shmid = shmget(key, memsize, flag); 265 if (shmid == -1) 266 err(1, "shmget() failed\n"); 267 268 p = shmat(shmid, NULL, 0); 269 if (p == (void *)-1) { 270 shmctl(shmid, IPC_RMID, NULL); 271 err(1, "shmat() failed\n"); 272 } 273 touch_memory_and_echo_node(p, memsize); 274 } else { 275 if (shmdt(p) == -1) 276 err(1, "shmdt() failed\n"); 277 if (shmctl(shmid, IPC_RMID, NULL) == -1) 278 err(1, "shmctl() failed\n"); 279 } 280} 281 282/* 283 * sigint_handler: handle SIGINT by set the exit flag. 284 */ 285void sigint_handler(int __attribute__((unused)) signo) 286{ 287 flag_exit = 1; 288} 289 290/* 291 * sigusr_handler: handler SIGUSR 292 * 293 * When we receive SIGUSR, we allocate some memory according 294 * to the user input when the process started. 295 * 296 * When we recive SIGUSR again, we will free all the allocated 297 * memory. 298 */ 299void sigusr_handler(int __attribute__((unused)) signo) 300{ 301 static int flag_allocated = 0; 302 303 if (opt_mmap_anon) 304 mmap_anon(flag_allocated); 305 306 if (opt_mmap_file) 307 mmap_file(flag_allocated); 308 309 if (opt_mmap_lock1) 310 mmap_lock1(flag_allocated); 311 312 if (opt_mmap_lock2) 313 mmap_lock2(flag_allocated); 314 315 if (opt_shm) 316 shm(flag_allocated); 317 318 flag_allocated = !flag_allocated; 319} 320 321void sigusr2(int __attribute__((unused)) signo) 322{ 323 static int flag_allocated = 0; 324 mmap_anon(flag_allocated); 325 flag_allocated = !flag_allocated; 326} 327 328void *thread2_routine(void __attribute__((unused)) *arg) 329{ 330 sigset_t set; 331 struct sigaction sigusr2_action; 332 333 sigemptyset(&set); 334 sigaddset(&set, SIGUSR1); 335 sigaddset(&set, SIGINT); 336 pthread_sigmask(SIG_BLOCK, &set, NULL); 337 338 memset(&sigusr2_action, 0, sizeof(sigusr2_action)); 339 sigusr2_action.sa_handler = &sigusr2; 340 sigaction(SIGUSR2, &sigusr2_action, NULL); 341 342 while (!flag_exit) 343 sleep(1); 344 345 return NULL; 346} 347 348int main(int argc, char *argv[]) 349{ 350 struct sigaction sigint_action; 351 struct sigaction sigusr_action; 352 pthread_t thread2; 353 354 fd = open("/dev/zero", O_RDWR); 355 if (fd < 0) 356 err(1, "open /dev/zero failed"); 357 358 memset(&sigint_action, 0, sizeof(sigint_action)); 359 sigint_action.sa_handler = &sigint_handler; 360 sigaction(SIGINT, &sigint_action, NULL); 361 362 memset(&sigusr_action, 0, sizeof(sigusr_action)); 363 sigusr_action.sa_handler = &sigusr_handler; 364 sigaction(SIGUSR1, &sigusr_action, NULL); 365 366 process_options(argc, argv); 367 368 if (opt_thread) { 369 sigset_t set; 370 sigemptyset(&set); 371 sigaddset(&set, SIGUSR2); 372 373 pthread_create(&thread2, NULL, thread2_routine, NULL); 374 375 pthread_sigmask(SIG_BLOCK, &set, NULL); 376 } 377 378 while (!flag_exit) 379 sleep(1); 380 381 if (opt_thread) { 382 void *retv; 383 pthread_cancel(thread2); 384 pthread_join(thread2, &retv); 385 } 386 387 close(fd); 388 389 return 0; 390} 391