blob: ba5bb34773b65b5722aa5e8d7cb8f5b9d8d58634 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
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;
}