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