312 lines
6.0 KiB
C
312 lines
6.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (c) 2009 FUJITSU LIMITED
|
|
* Author: Li Zefan <lizf@cn.fujitsu.com>
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/shm.h>
|
|
#include <sys/stat.h>
|
|
#include <err.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <limits.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#define TST_NO_DEFAULT_MAIN
|
|
#include "tst_test.h"
|
|
|
|
static int fd;
|
|
|
|
static volatile int flag_exit;
|
|
static volatile int flag_allocated;
|
|
|
|
static int opt_mmap_anon;
|
|
static int opt_mmap_file;
|
|
static int opt_mmap_lock1;
|
|
static int opt_mmap_lock2;
|
|
static int opt_shm;
|
|
static int opt_hugepage;
|
|
|
|
static int key_id; /* used with opt_shm */
|
|
static unsigned long memsize;
|
|
|
|
#define FILE_HUGEPAGE "/hugetlb/hugepagefile"
|
|
|
|
#define MMAP_ANON (SCHAR_MAX + 1)
|
|
#define MMAP_FILE (SCHAR_MAX + 2)
|
|
#define MMAP_LOCK1 (SCHAR_MAX + 3)
|
|
#define MMAP_LOCK2 (SCHAR_MAX + 4)
|
|
#define SHM (SCHAR_MAX + 5)
|
|
#define HUGEPAGE (SCHAR_MAX + 6)
|
|
|
|
static const struct option long_opts[] = {
|
|
{"mmap-anon", 0, NULL, MMAP_ANON},
|
|
{"mmap-file", 0, NULL, MMAP_FILE},
|
|
{"mmap-lock1", 0, NULL, MMAP_LOCK1},
|
|
{"mmap-lock2", 0, NULL, MMAP_LOCK2},
|
|
{"shm", 0, NULL, SHM},
|
|
{"hugepage", 0, NULL, HUGEPAGE},
|
|
{"size", 1, NULL, 's'},
|
|
{"key", 1, NULL, 'k'},
|
|
{NULL, 0, NULL, 0},
|
|
};
|
|
|
|
/*
|
|
* process_options: read options from user input
|
|
*/
|
|
static void process_options(int argc, char *argv[])
|
|
{
|
|
int c;
|
|
char *end;
|
|
|
|
while ((c = getopt_long(argc, argv, "k:s:", long_opts, NULL)) != -1) {
|
|
switch (c) {
|
|
case 'k':
|
|
key_id = atoi(optarg);
|
|
break;
|
|
case 's':
|
|
memsize = strtoul(optarg, &end, 10);
|
|
if (*end != '\0')
|
|
errx(1, "wrong -s argument!");
|
|
break;
|
|
case MMAP_ANON:
|
|
opt_mmap_anon = 1;
|
|
break;
|
|
case MMAP_FILE:
|
|
opt_mmap_file = 1;
|
|
break;
|
|
case MMAP_LOCK1:
|
|
opt_mmap_lock1 = 1;
|
|
break;
|
|
case MMAP_LOCK2:
|
|
opt_mmap_lock2 = 1;
|
|
break;
|
|
case SHM:
|
|
opt_shm = 1;
|
|
break;
|
|
case HUGEPAGE:
|
|
opt_hugepage = 1;
|
|
break;
|
|
default:
|
|
errx(1, "unknown option: %c", c);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* touch_memory: force allocating phy memory
|
|
*/
|
|
static void touch_memory(char *p, int size)
|
|
{
|
|
int i;
|
|
int pagesize = getpagesize();
|
|
|
|
for (i = 0; i < size; i += pagesize)
|
|
p[i] = 0xef;
|
|
}
|
|
|
|
static void mmap_anon(void)
|
|
{
|
|
static char *p;
|
|
|
|
if (!flag_allocated) {
|
|
p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
|
|
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
|
if (p == MAP_FAILED)
|
|
err(1, "mmap(anonymous) failed");
|
|
touch_memory(p, memsize);
|
|
} else {
|
|
if (munmap(p, memsize) == -1)
|
|
err(1, "munmap(anonymous) failed");
|
|
}
|
|
}
|
|
|
|
static void mmap_file(void)
|
|
{
|
|
static char *p;
|
|
static int fd_hugepage;
|
|
int fd_tmp;
|
|
|
|
if (!flag_allocated) {
|
|
if (opt_hugepage) {
|
|
fd_hugepage = open(FILE_HUGEPAGE,
|
|
O_CREAT | O_RDWR, 0755);
|
|
if (fd_hugepage < 0)
|
|
err(1, "open hugepage file failed");
|
|
fd_tmp = fd_hugepage;
|
|
} else
|
|
fd_tmp = fd;
|
|
|
|
p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
|
|
MAP_SHARED, fd_tmp, 0);
|
|
if (p == MAP_FAILED) {
|
|
if (opt_hugepage)
|
|
unlink(FILE_HUGEPAGE);
|
|
err(1, "mmap(file) failed");
|
|
}
|
|
touch_memory(p, memsize);
|
|
} else {
|
|
if (munmap(p, memsize) == -1)
|
|
err(1, "munmap(file) failed");
|
|
|
|
if (opt_hugepage) {
|
|
close(fd_hugepage);
|
|
unlink(FILE_HUGEPAGE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mmap_lock1(void)
|
|
{
|
|
static char *p;
|
|
|
|
if (!flag_allocated) {
|
|
p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
|
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, 0, 0);
|
|
if (p == MAP_FAILED)
|
|
err(1, "mmap(lock) failed");
|
|
touch_memory(p, memsize);
|
|
} else {
|
|
if (munmap(p, memsize) == -1)
|
|
err(1, "munmap(lock) failed");
|
|
}
|
|
}
|
|
|
|
static void mmap_lock2(void)
|
|
{
|
|
static char *p;
|
|
|
|
if (!flag_allocated) {
|
|
p = mmap(NULL, memsize, PROT_WRITE | PROT_READ,
|
|
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
|
if (p == MAP_FAILED)
|
|
err(1, "mmap failed");
|
|
|
|
if (mlock(p, memsize) == -1) {
|
|
if (errno == EAGAIN)
|
|
exit(2);
|
|
else
|
|
err(1, "mlock failed");
|
|
}
|
|
} else {
|
|
if (munmap(p, memsize) == -1)
|
|
err(1, "munmap failed");
|
|
}
|
|
}
|
|
|
|
static void shm(void)
|
|
{
|
|
static char *p;
|
|
static int shmid;
|
|
unsigned long flag;
|
|
|
|
key_t key;
|
|
|
|
if (!flag_allocated) {
|
|
flag = IPC_CREAT | SHM_R | SHM_W;
|
|
if (opt_hugepage)
|
|
flag |= SHM_HUGETLB;
|
|
|
|
key = ftok("/dev/null", key_id);
|
|
if (key == -1)
|
|
err(1, "ftok() failed");
|
|
|
|
shmid = shmget(key, memsize, flag);
|
|
if (shmid == -1)
|
|
err(1, "shmget() failed");
|
|
|
|
p = shmat(shmid, NULL, 0);
|
|
if (p == (void *)-1) {
|
|
shmctl(shmid, IPC_RMID, NULL);
|
|
err(1, "shmat() failed");
|
|
}
|
|
|
|
if (shmctl(shmid, IPC_RMID, NULL) == -1)
|
|
err(1, "shmctl() failed");
|
|
|
|
touch_memory(p, memsize);
|
|
} else {
|
|
if (shmdt(p) == -1)
|
|
err(1, "shmdt() failed");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* sigint_handler: handle SIGINT by set the exit flag.
|
|
*/
|
|
static void sigint_handler(int __attribute__ ((unused)) signo)
|
|
{
|
|
flag_exit = 1;
|
|
}
|
|
|
|
/*
|
|
* sigusr_handler: handler SIGUSR
|
|
*
|
|
* When we receive SIGUSR, we allocate some memory according
|
|
* to the user input when the process started.
|
|
*
|
|
* When we receive SIGUSR again, we will free all the allocated
|
|
* memory.
|
|
*/
|
|
static void sigusr_handler(int __attribute__ ((unused)) signo)
|
|
{
|
|
if (opt_mmap_anon)
|
|
mmap_anon();
|
|
|
|
if (opt_mmap_file)
|
|
mmap_file();
|
|
|
|
if (opt_mmap_lock1)
|
|
mmap_lock1();
|
|
|
|
if (opt_mmap_lock2)
|
|
mmap_lock2();
|
|
|
|
if (opt_shm)
|
|
shm();
|
|
|
|
flag_allocated = !flag_allocated;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct sigaction sigint_action;
|
|
struct sigaction sigusr_action;
|
|
|
|
if ((fd = open("/dev/zero", O_RDWR)) == -1)
|
|
err(1, "open /dev/zero failed");
|
|
|
|
memset(&sigint_action, 0, sizeof(sigint_action));
|
|
memset(&sigusr_action, 0, sizeof(sigusr_action));
|
|
|
|
sigemptyset(&sigint_action.sa_mask);
|
|
sigint_action.sa_handler = &sigint_handler;
|
|
if (sigaction(SIGINT, &sigint_action, NULL))
|
|
err(1, "sigaction(SIGINT)");
|
|
|
|
sigemptyset(&sigusr_action.sa_mask);
|
|
sigusr_action.sa_handler = &sigusr_handler;
|
|
if (sigaction(SIGUSR1, &sigusr_action, NULL))
|
|
err(1, "sigaction(SIGUSR1)");
|
|
|
|
process_options(argc, argv);
|
|
|
|
tst_reinit();
|
|
|
|
TST_CHECKPOINT_WAKE(0);
|
|
|
|
while (!flag_exit)
|
|
sleep(1);
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
}
|