int main(int argc, char *argv[])
{
- size_t alloc_size = 134217728;
- size_t page_size = getpagesize();
+ const size_t alloc_size = 2 * 1024 * 1024;
+ int retry_count = 10;
+ bool dropped;
void *alloc;
- pid_t child;
ksft_print_header();
ksft_set_plan(1);
exit(KSFT_FAIL);
}
memset(alloc, 'A', alloc_size);
- for (size_t i = 0; i < alloc_size; i += page_size)
- assert(*(uint8_t *)(alloc + i));
-
- child = fork();
- assert(child >= 0);
- if (!child) {
- for (;;)
- *(char *)malloc(page_size) = 'B';
- }
- for (bool done = false; !done;) {
- for (size_t i = 0; i < alloc_size; i += page_size) {
- if (!*(uint8_t *)(alloc + i)) {
- done = true;
- break;
+ while (retry_count--) {
+ if (madvise(alloc, alloc_size, MADV_PAGEOUT)) {
+ if (errno == EINVAL) {
+ ksft_test_result_skip("madvise(MADV_PAGEOUT) not supported\n");
+ exit(KSFT_SKIP);
}
+ ksft_test_result_fail("madvise(MADV_PAGEOUT) error: %s\n", strerror(errno));
+ exit(KSFT_FAIL);
}
+
+ dropped = memchr(alloc, 'A', alloc_size) == NULL;
+
+ /*
+ * Speculative reference can temporarily prevent some
+ * pages from getting dropped. So sleep and retry.
+ *
+ * If a page is not droppable for 10s, something
+ * is seriously messed up and we want to fail.
+ */
+ if (dropped)
+ break;
+ sleep(1);
}
- kill(child, SIGTERM);
- ksft_test_result_pass("MAP_DROPPABLE: PASS\n");
- exit(KSFT_PASS);
+ ksft_test_result(dropped, "madvise(MADV_PAGEOUT) behavior\n");
+
+ ksft_finished();
}