forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
2.8 KiB
143 lines
2.8 KiB
#include <fcntl.h> |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
|
|
#include <sys/ioctl.h> |
|
#include <sys/mman.h> |
|
#include <sys/prctl.h> |
|
#include <sys/stat.h> |
|
#include <sys/types.h> |
|
|
|
#include <linux/types.h> |
|
|
|
#define MB (1UL << 20) |
|
#define PAGE_SIZE sysconf(_SC_PAGESIZE) |
|
|
|
#define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark) |
|
#define GUP_BENCHMARK _IOWR('g', 2, struct gup_benchmark) |
|
|
|
/* Similar to above, but use FOLL_PIN instead of FOLL_GET. */ |
|
#define PIN_FAST_BENCHMARK _IOWR('g', 3, struct gup_benchmark) |
|
#define PIN_BENCHMARK _IOWR('g', 4, struct gup_benchmark) |
|
#define PIN_LONGTERM_BENCHMARK _IOWR('g', 5, struct gup_benchmark) |
|
|
|
/* Just the flags we need, copied from mm.h: */ |
|
#define FOLL_WRITE 0x01 /* check pte is writable */ |
|
|
|
struct gup_benchmark { |
|
__u64 get_delta_usec; |
|
__u64 put_delta_usec; |
|
__u64 addr; |
|
__u64 size; |
|
__u32 nr_pages_per_call; |
|
__u32 flags; |
|
__u64 expansion[10]; /* For future use */ |
|
}; |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
struct gup_benchmark gup; |
|
unsigned long size = 128 * MB; |
|
int i, fd, filed, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0; |
|
int cmd = GUP_FAST_BENCHMARK, flags = MAP_PRIVATE; |
|
char *file = "/dev/zero"; |
|
char *p; |
|
|
|
while ((opt = getopt(argc, argv, "m:r:n:f:abtTLUuwSH")) != -1) { |
|
switch (opt) { |
|
case 'a': |
|
cmd = PIN_FAST_BENCHMARK; |
|
break; |
|
case 'b': |
|
cmd = PIN_BENCHMARK; |
|
break; |
|
case 'L': |
|
cmd = PIN_LONGTERM_BENCHMARK; |
|
break; |
|
case 'm': |
|
size = atoi(optarg) * MB; |
|
break; |
|
case 'r': |
|
repeats = atoi(optarg); |
|
break; |
|
case 'n': |
|
nr_pages = atoi(optarg); |
|
break; |
|
case 't': |
|
thp = 1; |
|
break; |
|
case 'T': |
|
thp = 0; |
|
break; |
|
case 'U': |
|
cmd = GUP_BENCHMARK; |
|
break; |
|
case 'u': |
|
cmd = GUP_FAST_BENCHMARK; |
|
break; |
|
case 'w': |
|
write = 1; |
|
break; |
|
case 'f': |
|
file = optarg; |
|
break; |
|
case 'S': |
|
flags &= ~MAP_PRIVATE; |
|
flags |= MAP_SHARED; |
|
break; |
|
case 'H': |
|
flags |= (MAP_HUGETLB | MAP_ANONYMOUS); |
|
break; |
|
default: |
|
return -1; |
|
} |
|
} |
|
|
|
filed = open(file, O_RDWR|O_CREAT); |
|
if (filed < 0) { |
|
perror("open"); |
|
exit(filed); |
|
} |
|
|
|
gup.nr_pages_per_call = nr_pages; |
|
if (write) |
|
gup.flags |= FOLL_WRITE; |
|
|
|
fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR); |
|
if (fd == -1) { |
|
perror("open"); |
|
exit(1); |
|
} |
|
|
|
p = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, filed, 0); |
|
if (p == MAP_FAILED) { |
|
perror("mmap"); |
|
exit(1); |
|
} |
|
gup.addr = (unsigned long)p; |
|
|
|
if (thp == 1) |
|
madvise(p, size, MADV_HUGEPAGE); |
|
else if (thp == 0) |
|
madvise(p, size, MADV_NOHUGEPAGE); |
|
|
|
for (; (unsigned long)p < gup.addr + size; p += PAGE_SIZE) |
|
p[0] = 0; |
|
|
|
for (i = 0; i < repeats; i++) { |
|
gup.size = size; |
|
if (ioctl(fd, cmd, &gup)) { |
|
perror("ioctl"); |
|
exit(1); |
|
} |
|
|
|
printf("Time: get:%lld put:%lld us", gup.get_delta_usec, |
|
gup.put_delta_usec); |
|
if (gup.size != size) |
|
printf(", truncated (size: %lld)", gup.size); |
|
printf("\n"); |
|
} |
|
|
|
return 0; |
|
}
|
|
|