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 9int HPS; 10char 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 */ 23void 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 */ 46int 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 65int 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. */ 88int 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 102void *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 121void *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 137void *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 156int 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 167int 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 177int 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