#include #include #include #include #include #include #include int HPS; char hugetlbfsdir[256]; #ifndef UTILS #include "utils.h" #endif #define errmsg(x) fprintf(stderr, x), exit(1) /* * Function : write_hugepage(char *addr, int nr_hugepage, char *avoid_addr) * Parameters : * addr head address of hugepage range * nr_hugepage hugepage number from head address * avoid_addr the address which avoid to be operated */ void write_hugepage(char *addr, int nr_hugepage, char *avoid_addr) { int i, j; for (i = 0; i < nr_hugepage; i++) { if ((addr + i * HPS) == avoid_addr) continue; for (j = 0; j < HPS; j++) { *(addr + i * HPS + j) = (char)('a' + ((i + j) % 26)); } } } /* * Function : read_hugepage(char *addr, int nr_hugepage, char *avoid_addr) * Parameters : * addr head address of hugepage range * nr_hugepage hugepage number from head address * avoid_addr the address which avoid to be operated * * return : * 0 OK * -1 if buffer content differs from the expected ones */ int read_hugepage(char *addr, int nr_hugepage, char *avoid_addr) { int i, j; int ret = 0; for (i = 0; i < nr_hugepage; i++) { if ((addr + i * HPS) == avoid_addr) continue; for (j = 0; j < HPS; j++) { if (*(addr + i * HPS + j) != (char)('a' + ((i + j) % 26))) { printf("Mismatch at %d\n", i + j); ret = -1; break; } } } return ret; } int hugetlbfs_root(char *dir) { int found = 0; FILE *f = fopen("/proc/mounts", "r"); if (!f) err("open /proc/mounts"); char *line = NULL; size_t linelen = 0; char dummy[100]; while (getline(&line, &linelen, f) > 0) { if (sscanf(line, "none %s hugetlbfs %[^ ]", dir, dummy) >= 2) { found = 1; break; } } free(line); fclose(f); if (!found) printf("cannot find hugetlbfs directory in /proc/mounts\n"); return found; } /* Assume there is only one types of hugepage size for now. */ int gethugepagesize(void) { int hpagesize = 0; struct dirent *dent; DIR *dir; dir = opendir("/sys/kernel/mm/hugepages"); if (!dir) err("open /sys/kernel/mm/hugepages"); while ((dent = readdir(dir)) != NULL) if (sscanf(dent->d_name, "hugepages-%dkB", &hpagesize) >= 1) break; closedir(dir); return hpagesize * 1024; } void *alloc_shm_hugepage(int *key, int size) { void *addr; int shmid; if ((shmid = shmget(*key, size, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) { perror("shmget"); return NULL; } addr = shmat(shmid, (void *)0x0UL, 0); if (addr == (char *)-1) { perror("Shared memory attach failure"); shmctl(shmid, IPC_RMID, NULL); return NULL; } *key = shmid; return addr; } void *alloc_anonymous_hugepage(int size, int private) { void *addr; int mapflag = MAP_ANONYMOUS | 0x40000; /* MAP_HUGETLB */ if (private) mapflag |= MAP_PRIVATE; else mapflag |= MAP_SHARED; if ((addr = mmap(0, size, PROT_READ|PROT_WRITE, mapflag, -1, 0)) == MAP_FAILED) { perror("mmap"); return NULL; } return addr; } void *alloc_filebacked_hugepage(char *filepath, int size, int private, int *fd) { int mapflag = MAP_SHARED; void *addr; if (private) mapflag = MAP_PRIVATE; if ((*fd = open(filepath, O_CREAT | O_RDWR, 0777)) < 0) { perror("open"); return NULL; } if ((addr = mmap(0, size, PROT_READ|PROT_WRITE, mapflag, *fd, 0)) == MAP_FAILED) { perror("mmap"); unlink(filepath); return NULL; } return addr; } int free_shm_hugepage(int key, void *addr) { if (shmdt((const void *)addr) != 0) { perror("Detach failure"); shmctl(key, IPC_RMID, NULL); return -1; } shmctl(key, IPC_RMID, NULL); return 0; } int free_anonymous_hugepage(void *addr, int size) { int ret = 0; if (munmap(addr, size)) { perror("munmap"); ret = -1; } return ret; } int free_filebacked_hugepage(void *addr, int size, int fd, char *filepath) { int ret = 0; if (munmap(addr, size)) { perror("munmap"); ret = -1; } if (close(fd)) { perror("close"); ret = -1; } if (filepath) { if (unlink(filepath)) { perror("unlink"); ret = -1; } } else { fprintf(stderr, "Filepath not specified.\n"); ret = -1; } return ret; }