projects/linux·blob master · refs

66 lines · 1.5 KiB

1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2024 Jason A. Donenfeld <[email protected]>. All Rights Reserved.
4 */
5
6#include <assert.h>
7#include <stdbool.h>
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <signal.h>
13#include <sys/mman.h>
14#include <linux/mman.h>
15
16#include "kselftest.h"
17
18int main(int argc, char *argv[])
19{
20 const size_t alloc_size = 2 * 1024 * 1024;
21 int retry_count = 10;
22 bool dropped;
23 void *alloc;
24
25 ksft_print_header();
26 ksft_set_plan(1);
27
28 alloc = mmap(0, alloc_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
29 if (alloc == MAP_FAILED) {
30 if ((errno == EOPNOTSUPP) || (errno == EINVAL)) {
31 ksft_test_result_skip("MAP_DROPPABLE not supported\n");
32 exit(KSFT_SKIP);
33 }
34 ksft_test_result_fail("mmap error: %s\n", strerror(errno));
35 exit(KSFT_FAIL);
36 }
37 memset(alloc, 'A', alloc_size);
38
39 while (retry_count--) {
40 if (madvise(alloc, alloc_size, MADV_PAGEOUT)) {
41 if (errno == EINVAL) {
42 ksft_test_result_skip("madvise(MADV_PAGEOUT) not supported\n");
43 exit(KSFT_SKIP);
44 }
45 ksft_test_result_fail("madvise(MADV_PAGEOUT) error: %s\n", strerror(errno));
46 exit(KSFT_FAIL);
47 }
48
49 dropped = memchr(alloc, 'A', alloc_size) == NULL;
50
51 /*
52 * Speculative reference can temporarily prevent some
53 * pages from getting dropped. So sleep and retry.
54 *
55 * If a page is not droppable for 10s, something
56 * is seriously messed up and we want to fail.
57 */
58 if (dropped)
59 break;
60 sleep(1);
61 }
62
63 ksft_test_result(dropped, "madvise(MADV_PAGEOUT) behavior\n");
64
65 ksft_finished();
66}