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