1baa489faSSeongJae Park // SPDX-License-Identifier: GPL-2.0
2baa489faSSeongJae Park /*
3baa489faSSeongJae Park * This program reserves and uses hugetlb memory, supporting a bunch of
4baa489faSSeongJae Park * scenarios needed by the charged_reserved_hugetlb.sh test.
5baa489faSSeongJae Park */
6baa489faSSeongJae Park
7baa489faSSeongJae Park #include <err.h>
8baa489faSSeongJae Park #include <errno.h>
9baa489faSSeongJae Park #include <signal.h>
10baa489faSSeongJae Park #include <stdio.h>
11baa489faSSeongJae Park #include <stdlib.h>
12baa489faSSeongJae Park #include <string.h>
13baa489faSSeongJae Park #include <unistd.h>
14baa489faSSeongJae Park #include <fcntl.h>
15baa489faSSeongJae Park #include <sys/types.h>
16baa489faSSeongJae Park #include <sys/shm.h>
17baa489faSSeongJae Park #include <sys/stat.h>
18baa489faSSeongJae Park #include <sys/mman.h>
19baa489faSSeongJae Park
20baa489faSSeongJae Park /* Global definitions. */
21baa489faSSeongJae Park enum method {
22baa489faSSeongJae Park HUGETLBFS,
23baa489faSSeongJae Park MMAP_MAP_HUGETLB,
24baa489faSSeongJae Park SHM,
25baa489faSSeongJae Park MAX_METHOD
26baa489faSSeongJae Park };
27baa489faSSeongJae Park
28baa489faSSeongJae Park
29baa489faSSeongJae Park /* Global variables. */
30baa489faSSeongJae Park static const char *self;
31*dfb56976SDavid Hildenbrand static int *shmaddr;
32baa489faSSeongJae Park static int shmid;
33baa489faSSeongJae Park
34baa489faSSeongJae Park /*
35baa489faSSeongJae Park * Show usage and exit.
36baa489faSSeongJae Park */
exit_usage(void)37baa489faSSeongJae Park static void exit_usage(void)
38baa489faSSeongJae Park {
39baa489faSSeongJae Park printf("Usage: %s -p <path to hugetlbfs file> -s <size to map> "
40baa489faSSeongJae Park "[-m <0=hugetlbfs | 1=mmap(MAP_HUGETLB)>] [-l] [-r] "
41baa489faSSeongJae Park "[-o] [-w] [-n]\n",
42baa489faSSeongJae Park self);
43baa489faSSeongJae Park exit(EXIT_FAILURE);
44baa489faSSeongJae Park }
45baa489faSSeongJae Park
sig_handler(int signo)46baa489faSSeongJae Park void sig_handler(int signo)
47baa489faSSeongJae Park {
48baa489faSSeongJae Park printf("Received %d.\n", signo);
49baa489faSSeongJae Park if (signo == SIGINT) {
50*dfb56976SDavid Hildenbrand if (shmaddr) {
51baa489faSSeongJae Park printf("Deleting the memory\n");
52baa489faSSeongJae Park if (shmdt((const void *)shmaddr) != 0) {
53baa489faSSeongJae Park perror("Detach failure");
54baa489faSSeongJae Park shmctl(shmid, IPC_RMID, NULL);
55baa489faSSeongJae Park exit(4);
56baa489faSSeongJae Park }
57baa489faSSeongJae Park
58baa489faSSeongJae Park shmctl(shmid, IPC_RMID, NULL);
59baa489faSSeongJae Park printf("Done deleting the memory\n");
60baa489faSSeongJae Park }
61*dfb56976SDavid Hildenbrand }
62baa489faSSeongJae Park exit(2);
63baa489faSSeongJae Park }
64baa489faSSeongJae Park
main(int argc,char ** argv)65baa489faSSeongJae Park int main(int argc, char **argv)
66baa489faSSeongJae Park {
67baa489faSSeongJae Park int fd = 0;
68baa489faSSeongJae Park int key = 0;
69baa489faSSeongJae Park int *ptr = NULL;
70baa489faSSeongJae Park int c = 0;
71baa489faSSeongJae Park int size = 0;
72baa489faSSeongJae Park char path[256] = "";
73baa489faSSeongJae Park enum method method = MAX_METHOD;
74baa489faSSeongJae Park int want_sleep = 0, private = 0;
75baa489faSSeongJae Park int populate = 0;
76baa489faSSeongJae Park int write = 0;
77baa489faSSeongJae Park int reserve = 1;
78baa489faSSeongJae Park
79baa489faSSeongJae Park if (signal(SIGINT, sig_handler) == SIG_ERR)
80baa489faSSeongJae Park err(1, "\ncan't catch SIGINT\n");
81baa489faSSeongJae Park
82baa489faSSeongJae Park /* Parse command-line arguments. */
83baa489faSSeongJae Park setvbuf(stdout, NULL, _IONBF, 0);
84baa489faSSeongJae Park self = argv[0];
85baa489faSSeongJae Park
86baa489faSSeongJae Park while ((c = getopt(argc, argv, "s:p:m:owlrn")) != -1) {
87baa489faSSeongJae Park switch (c) {
88baa489faSSeongJae Park case 's':
89baa489faSSeongJae Park size = atoi(optarg);
90baa489faSSeongJae Park break;
91baa489faSSeongJae Park case 'p':
92baa489faSSeongJae Park strncpy(path, optarg, sizeof(path));
93baa489faSSeongJae Park break;
94baa489faSSeongJae Park case 'm':
95baa489faSSeongJae Park if (atoi(optarg) >= MAX_METHOD) {
96baa489faSSeongJae Park errno = EINVAL;
97baa489faSSeongJae Park perror("Invalid -m.");
98baa489faSSeongJae Park exit_usage();
99baa489faSSeongJae Park }
100baa489faSSeongJae Park method = atoi(optarg);
101baa489faSSeongJae Park break;
102baa489faSSeongJae Park case 'o':
103baa489faSSeongJae Park populate = 1;
104baa489faSSeongJae Park break;
105baa489faSSeongJae Park case 'w':
106baa489faSSeongJae Park write = 1;
107baa489faSSeongJae Park break;
108baa489faSSeongJae Park case 'l':
109baa489faSSeongJae Park want_sleep = 1;
110baa489faSSeongJae Park break;
111baa489faSSeongJae Park case 'r':
112baa489faSSeongJae Park private
113baa489faSSeongJae Park = 1;
114baa489faSSeongJae Park break;
115baa489faSSeongJae Park case 'n':
116baa489faSSeongJae Park reserve = 0;
117baa489faSSeongJae Park break;
118baa489faSSeongJae Park default:
119baa489faSSeongJae Park errno = EINVAL;
120baa489faSSeongJae Park perror("Invalid arg");
121baa489faSSeongJae Park exit_usage();
122baa489faSSeongJae Park }
123baa489faSSeongJae Park }
124baa489faSSeongJae Park
125baa489faSSeongJae Park if (strncmp(path, "", sizeof(path)) != 0) {
126baa489faSSeongJae Park printf("Writing to this path: %s\n", path);
127baa489faSSeongJae Park } else {
128baa489faSSeongJae Park errno = EINVAL;
129baa489faSSeongJae Park perror("path not found");
130baa489faSSeongJae Park exit_usage();
131baa489faSSeongJae Park }
132baa489faSSeongJae Park
133baa489faSSeongJae Park if (size != 0) {
134baa489faSSeongJae Park printf("Writing this size: %d\n", size);
135baa489faSSeongJae Park } else {
136baa489faSSeongJae Park errno = EINVAL;
137baa489faSSeongJae Park perror("size not found");
138baa489faSSeongJae Park exit_usage();
139baa489faSSeongJae Park }
140baa489faSSeongJae Park
141baa489faSSeongJae Park if (!populate)
142baa489faSSeongJae Park printf("Not populating.\n");
143baa489faSSeongJae Park else
144baa489faSSeongJae Park printf("Populating.\n");
145baa489faSSeongJae Park
146baa489faSSeongJae Park if (!write)
147baa489faSSeongJae Park printf("Not writing to memory.\n");
148baa489faSSeongJae Park
149baa489faSSeongJae Park if (method == MAX_METHOD) {
150baa489faSSeongJae Park errno = EINVAL;
151baa489faSSeongJae Park perror("-m Invalid");
152baa489faSSeongJae Park exit_usage();
153baa489faSSeongJae Park } else
154baa489faSSeongJae Park printf("Using method=%d\n", method);
155baa489faSSeongJae Park
156baa489faSSeongJae Park if (!private)
157baa489faSSeongJae Park printf("Shared mapping.\n");
158baa489faSSeongJae Park else
159baa489faSSeongJae Park printf("Private mapping.\n");
160baa489faSSeongJae Park
161baa489faSSeongJae Park if (!reserve)
162baa489faSSeongJae Park printf("NO_RESERVE mapping.\n");
163baa489faSSeongJae Park else
164baa489faSSeongJae Park printf("RESERVE mapping.\n");
165baa489faSSeongJae Park
166baa489faSSeongJae Park switch (method) {
167baa489faSSeongJae Park case HUGETLBFS:
168baa489faSSeongJae Park printf("Allocating using HUGETLBFS.\n");
169baa489faSSeongJae Park fd = open(path, O_CREAT | O_RDWR, 0777);
170baa489faSSeongJae Park if (fd == -1)
171baa489faSSeongJae Park err(1, "Failed to open file.");
172baa489faSSeongJae Park
173baa489faSSeongJae Park ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
174baa489faSSeongJae Park (private ? MAP_PRIVATE : MAP_SHARED) |
175baa489faSSeongJae Park (populate ? MAP_POPULATE : 0) |
176baa489faSSeongJae Park (reserve ? 0 : MAP_NORESERVE),
177baa489faSSeongJae Park fd, 0);
178baa489faSSeongJae Park
179baa489faSSeongJae Park if (ptr == MAP_FAILED) {
180baa489faSSeongJae Park close(fd);
181baa489faSSeongJae Park err(1, "Error mapping the file");
182baa489faSSeongJae Park }
183baa489faSSeongJae Park break;
184baa489faSSeongJae Park case MMAP_MAP_HUGETLB:
185baa489faSSeongJae Park printf("Allocating using MAP_HUGETLB.\n");
186baa489faSSeongJae Park ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
187baa489faSSeongJae Park (private ? (MAP_PRIVATE | MAP_ANONYMOUS) :
188baa489faSSeongJae Park MAP_SHARED) |
189baa489faSSeongJae Park MAP_HUGETLB | (populate ? MAP_POPULATE : 0) |
190baa489faSSeongJae Park (reserve ? 0 : MAP_NORESERVE),
191baa489faSSeongJae Park -1, 0);
192baa489faSSeongJae Park
193baa489faSSeongJae Park if (ptr == MAP_FAILED)
194baa489faSSeongJae Park err(1, "mmap");
195baa489faSSeongJae Park
196baa489faSSeongJae Park printf("Returned address is %p\n", ptr);
197baa489faSSeongJae Park break;
198baa489faSSeongJae Park case SHM:
199baa489faSSeongJae Park printf("Allocating using SHM.\n");
200baa489faSSeongJae Park shmid = shmget(key, size,
201baa489faSSeongJae Park SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
202baa489faSSeongJae Park if (shmid < 0) {
203baa489faSSeongJae Park shmid = shmget(++key, size,
204baa489faSSeongJae Park SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
205baa489faSSeongJae Park if (shmid < 0)
206baa489faSSeongJae Park err(1, "shmget");
207baa489faSSeongJae Park }
208baa489faSSeongJae Park printf("shmid: 0x%x, shmget key:%d\n", shmid, key);
209baa489faSSeongJae Park
210baa489faSSeongJae Park ptr = shmat(shmid, NULL, 0);
211baa489faSSeongJae Park if (ptr == (int *)-1) {
212baa489faSSeongJae Park perror("Shared memory attach failure");
213baa489faSSeongJae Park shmctl(shmid, IPC_RMID, NULL);
214baa489faSSeongJae Park exit(2);
215baa489faSSeongJae Park }
216*dfb56976SDavid Hildenbrand shmaddr = ptr;
217*dfb56976SDavid Hildenbrand printf("shmaddr: %p\n", shmaddr);
218baa489faSSeongJae Park
219baa489faSSeongJae Park break;
220baa489faSSeongJae Park default:
221baa489faSSeongJae Park errno = EINVAL;
222baa489faSSeongJae Park err(1, "Invalid method.");
223baa489faSSeongJae Park }
224baa489faSSeongJae Park
225baa489faSSeongJae Park if (write) {
226baa489faSSeongJae Park printf("Writing to memory.\n");
227baa489faSSeongJae Park memset(ptr, 1, size);
228baa489faSSeongJae Park }
229baa489faSSeongJae Park
230baa489faSSeongJae Park if (want_sleep) {
231baa489faSSeongJae Park /* Signal to caller that we're done. */
232baa489faSSeongJae Park printf("DONE\n");
233baa489faSSeongJae Park
234baa489faSSeongJae Park /* Hold memory until external kill signal is delivered. */
235baa489faSSeongJae Park while (1)
236baa489faSSeongJae Park sleep(100);
237baa489faSSeongJae Park }
238baa489faSSeongJae Park
239baa489faSSeongJae Park if (method == HUGETLBFS)
240baa489faSSeongJae Park close(fd);
241baa489faSSeongJae Park
242baa489faSSeongJae Park return 0;
243baa489faSSeongJae Park }
244