Reputation: 2433
I have a character driver exposing a character device file under /dev
. I'd like to use the huge pages when I map some menory.
MAP_HUGETLB
seems to be only available when grouped with MAP_ANONYMOUS
or with transparent huge-page but am not interested in it.
mmap(...,MAP_HUGETLB|MAP_ANONYMOUS,..., -1, 0);
How can we implement the huge-pages feature for a character device? Is it already done somewhere?
I didn't find an example the kernel's tree.
Upvotes: 1
Views: 1168
Reputation: 422
This code worked for me, I am aligning an address to 2MB and passing it as hint address for second mmap with MAP_HUGETLB flag. I checked "HugePages_Total" in /proc/meminfo before doing this
#include<stdio.h>
#include<stdlib.h>
#include <sys/mman.h>
#define EIGHTMB 8388608
#define TWOMB 2097152
int main(int argc, char* argv[]){
int sum = 0;
char * ptr = (char*)mmap(NULL, EIGHTMB+TWOMB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
if (ptr == MAP_FAILED){
printf("error\n");
exit(0);
}
unsigned long align_ptr = (((unsigned long)ptr+TWOMB)>>21)<<21;
printf("ptr:%p,%lx\n",ptr,align_ptr);
munmap(ptr, EIGHTMB+TWOMB);
ptr = (char*)mmap((void*)align_ptr, EIGHTMB, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB,-1,0);
if (ptr == MAP_FAILED){
printf("error\n");
exit(0);
}
printf("ptr:%p\n",ptr);
ptr[0] = 'A';
ptr[4096] = 'B';
munmap(ptr, EIGHTMB);
return 0;
}
Upvotes: 1
Reputation: 69276
This isn't possible. You can only mmap
files with MAP_HUGETLB
if they reside in a hugetlbfs
filesystem. Since /proc
is a procfs
filesystem, you have no way of mapping those files through huge pages.
You can also see this from the checks performed in mmap
by the kernel:
/* ... */
if (!(flags & MAP_ANONYMOUS)) { // <== File-backed mapping?
audit_mmap_fd(fd, flags);
file = fget(fd);
if (!file)
return -EBADF;
if (is_file_hugepages(file)) { // <== Check that FS is hugetlbfs
len = ALIGN(len, huge_page_size(hstate_file(file)));
} else if (unlikely(flags & MAP_HUGETLB)) { // <== If not, MAP_HUGETLB isn't allowed
retval = -EINVAL;
goto out_fput;
}
} else if (flags & MAP_HUGETLB) { // <== Anonymous MAP_HUGETLB mapping?
/* ... */
See also:
Upvotes: 1