1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <dirent.h>
5 #include <sys/mman.h>
6 #include <sys/ipc.h>
7 #include <sys/shm.h>
8
9 int HPS;
10 char hugetlbfsdir[256];
11 #ifndef UTILS
12 #include "utils.h"
13 #endif
14 #define errmsg(x) fprintf(stderr, x), exit(1)
15
16 /*
17 * Function : write_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
18 * Parameters :
19 * addr head address of hugepage range
20 * nr_hugepage hugepage number from head address
21 * avoid_addr the address which avoid to be operated
22 */
write_hugepage(char * addr,int nr_hugepage,char * avoid_addr)23 void write_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
24 {
25 int i, j;
26 for (i = 0; i < nr_hugepage; i++) {
27 if ((addr + i * HPS) == avoid_addr)
28 continue;
29 for (j = 0; j < HPS; j++) {
30 *(addr + i * HPS + j) = (char)('a' + ((i + j) % 26));
31 }
32 }
33 }
34
35 /*
36 * Function : read_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
37 * Parameters :
38 * addr head address of hugepage range
39 * nr_hugepage hugepage number from head address
40 * avoid_addr the address which avoid to be operated
41 *
42 * return :
43 * 0 OK
44 * -1 if buffer content differs from the expected ones
45 */
read_hugepage(char * addr,int nr_hugepage,char * avoid_addr)46 int read_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
47 {
48 int i, j;
49 int ret = 0;
50
51 for (i = 0; i < nr_hugepage; i++) {
52 if ((addr + i * HPS) == avoid_addr)
53 continue;
54 for (j = 0; j < HPS; j++) {
55 if (*(addr + i * HPS + j) != (char)('a' + ((i + j) % 26))) {
56 printf("Mismatch at %d\n", i + j);
57 ret = -1;
58 break;
59 }
60 }
61 }
62 return ret;
63 }
64
hugetlbfs_root(char * dir)65 int hugetlbfs_root(char *dir)
66 {
67 int found = 0;
68 FILE *f = fopen("/proc/mounts", "r");
69 if (!f) err("open /proc/mounts");
70 char *line = NULL;
71 size_t linelen = 0;
72 char dummy[100];
73 while (getline(&line, &linelen, f) > 0) {
74 if (sscanf(line, "none %s hugetlbfs %[^ ]",
75 dir, dummy) >= 2) {
76 found = 1;
77 break;
78 }
79 }
80 free(line);
81 fclose(f);
82 if (!found)
83 printf("cannot find hugetlbfs directory in /proc/mounts\n");
84 return found;
85 }
86
87 /* Assume there is only one types of hugepage size for now. */
gethugepagesize(void)88 int gethugepagesize(void)
89 {
90 int hpagesize = 0;
91 struct dirent *dent;
92 DIR *dir;
93 dir = opendir("/sys/kernel/mm/hugepages");
94 if (!dir) err("open /sys/kernel/mm/hugepages");
95 while ((dent = readdir(dir)) != NULL)
96 if (sscanf(dent->d_name, "hugepages-%dkB", &hpagesize) >= 1)
97 break;
98 closedir(dir);
99 return hpagesize * 1024;
100 }
101
alloc_shm_hugepage(int * key,int size)102 void *alloc_shm_hugepage(int *key, int size)
103 {
104 void *addr;
105 int shmid;
106 if ((shmid = shmget(*key, size,
107 SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
108 perror("shmget");
109 return NULL;
110 }
111 addr = shmat(shmid, (void *)0x0UL, 0);
112 if (addr == (char *)-1) {
113 perror("Shared memory attach failure");
114 shmctl(shmid, IPC_RMID, NULL);
115 return NULL;
116 }
117 *key = shmid;
118 return addr;
119 }
120
alloc_anonymous_hugepage(int size,int private)121 void *alloc_anonymous_hugepage(int size, int private)
122 {
123 void *addr;
124 int mapflag = MAP_ANONYMOUS | 0x40000; /* MAP_HUGETLB */
125 if (private)
126 mapflag |= MAP_PRIVATE;
127 else
128 mapflag |= MAP_SHARED;
129 if ((addr = mmap(0, size,
130 PROT_READ|PROT_WRITE, mapflag, -1, 0)) == MAP_FAILED) {
131 perror("mmap");
132 return NULL;
133 }
134 return addr;
135 }
136
alloc_filebacked_hugepage(char * filepath,int size,int private,int * fd)137 void *alloc_filebacked_hugepage(char *filepath, int size, int private, int *fd)
138 {
139 int mapflag = MAP_SHARED;
140 void *addr;
141 if (private)
142 mapflag = MAP_PRIVATE;
143 if ((*fd = open(filepath, O_CREAT | O_RDWR, 0777)) < 0) {
144 perror("open");
145 return NULL;
146 }
147 if ((addr = mmap(0, size,
148 PROT_READ|PROT_WRITE, mapflag, *fd, 0)) == MAP_FAILED) {
149 perror("mmap");
150 unlink(filepath);
151 return NULL;
152 }
153 return addr;
154 }
155
free_shm_hugepage(int key,void * addr)156 int free_shm_hugepage(int key, void *addr)
157 {
158 if (shmdt((const void *)addr) != 0) {
159 perror("Detach failure");
160 shmctl(key, IPC_RMID, NULL);
161 return -1;
162 }
163 shmctl(key, IPC_RMID, NULL);
164 return 0;
165 }
166
free_anonymous_hugepage(void * addr,int size)167 int free_anonymous_hugepage(void *addr, int size)
168 {
169 int ret = 0;
170 if (munmap(addr, size)) {
171 perror("munmap");
172 ret = -1;
173 }
174 return ret;
175 }
176
free_filebacked_hugepage(void * addr,int size,int fd,char * filepath)177 int free_filebacked_hugepage(void *addr, int size, int fd, char *filepath)
178 {
179 int ret = 0;
180 if (munmap(addr, size)) {
181 perror("munmap");
182 ret = -1;
183 }
184 if (close(fd)) {
185 perror("close");
186 ret = -1;
187 }
188 if (filepath) {
189 if (unlink(filepath)) {
190 perror("unlink");
191 ret = -1;
192 }
193 } else {
194 fprintf(stderr, "Filepath not specified.\n");
195 ret = -1;
196 }
197 return ret;
198 }
199