2 * Stress test for transparent huge pages, memory compaction and migration.
4 * Authors: Konstantin Khlebnikov <koct9i@gmail.com>
6 * This is free and unencumbered software released into the public domain.
19 #include "../kselftest.h"
22 int mmap_flags
= MAP_ANONYMOUS
| MAP_NORESERVE
| MAP_PRIVATE
;
23 #define PROT_RW (PROT_READ | PROT_WRITE)
25 int main(int argc
, char **argv
)
29 struct timespec start
, a
, b
;
40 ram
= sysconf(_SC_PHYS_PAGES
);
41 if (ram
> SIZE_MAX
/ psize() / 4)
48 if (!strcmp(argv
[i
], "-h"))
49 ksft_exit_fail_msg("usage: %s [-f <filename>] [-d <duration>] [size in MiB]\n",
51 else if (!strcmp(argv
[i
], "-f"))
53 else if (!strcmp(argv
[i
], "-d"))
54 duration
= atoi(argv
[++i
]);
56 len
= atoll(argv
[i
]) << 20;
62 backing_fd
= open(name
, O_RDWR
);
64 ksft_exit_fail_msg("open %s\n", name
);
65 mmap_flags
= MAP_SHARED
;
68 warnx("allocate %zd transhuge pages, using %zd MiB virtual memory"
69 " and %zd MiB of ram", len
>> HPAGE_SHIFT
, len
>> 20,
70 ram
>> (20 + HPAGE_SHIFT
- pshift() - 1));
72 pagemap_fd
= open("/proc/self/pagemap", O_RDONLY
);
74 ksft_exit_fail_msg("open pagemap\n");
76 len
-= len
% HPAGE_SIZE
;
77 ptr
= mmap(NULL
, len
+ HPAGE_SIZE
, PROT_RW
, mmap_flags
, backing_fd
, 0);
78 if (ptr
== MAP_FAILED
)
79 ksft_exit_fail_msg("initial mmap");
80 ptr
+= HPAGE_SIZE
- (uintptr_t)ptr
% HPAGE_SIZE
;
82 if (madvise(ptr
, len
, MADV_HUGEPAGE
))
83 ksft_exit_fail_msg("MADV_HUGEPAGE");
85 map_len
= ram
>> (HPAGE_SHIFT
- 1);
86 map
= malloc(map_len
);
88 ksft_exit_fail_msg("map malloc\n");
90 clock_gettime(CLOCK_MONOTONIC
, &start
);
93 int nr_succeed
= 0, nr_failed
= 0, nr_pages
= 0;
95 memset(map
, 0, map_len
);
97 clock_gettime(CLOCK_MONOTONIC
, &a
);
98 for (p
= ptr
; p
< ptr
+ len
; p
+= HPAGE_SIZE
) {
101 pfn
= allocate_transhuge(p
, pagemap_fd
);
106 size_t idx
= pfn
>> (HPAGE_SHIFT
- pshift());
109 if (idx
>= map_len
) {
110 map
= realloc(map
, idx
+ 1);
112 ksft_exit_fail_msg("map realloc\n");
113 memset(map
+ map_len
, 0, idx
+ 1 - map_len
);
121 /* split transhuge page, keep last page */
122 if (madvise(p
, HPAGE_SIZE
- psize(), MADV_DONTNEED
))
123 ksft_exit_fail_msg("MADV_DONTNEED");
125 clock_gettime(CLOCK_MONOTONIC
, &b
);
126 s
= b
.tv_sec
- a
.tv_sec
+ (b
.tv_nsec
- a
.tv_nsec
) / 1000000000.;
128 ksft_print_msg("%.3f s/loop, %.3f ms/page, %10.3f MiB/s\t"
129 "%4d succeed, %4d failed, %4d different pages\n",
130 s
, s
* 1000 / (len
>> HPAGE_SHIFT
), len
/ s
/ (1 << 20),
131 nr_succeed
, nr_failed
, nr_pages
);
133 if (duration
> 0 && b
.tv_sec
- start
.tv_sec
>= duration
) {
134 ksft_test_result_pass("Completed\n");