• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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