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