11static int anonymous_discard(
void) {
13 const size_t p = vm_page;
15 mmap(NULL, 4 * p, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
16 unsigned char* target = MAP_FAILED;
17 unsigned char vector[4];
18 CHECK(area != MAP_FAILED);
19 memset(area, 0x71, 4 * p);
20 CHECK(mprotect(area + p, p, PROT_READ) == 0 && mprotect(area + 2 * p, p, PROT_NONE) == 0);
21 CHECK(madvise(area + p, 2 * p, MADV_DONTNEED) == 0);
22 CHECK(mincore(area, 4 * p, vector) == 0 && vector[0] == 1 && vector[1] == 0 && vector[2] == 0 &&
24 CHECK(vm_uniform(area, p, 0x71) && vm_uniform(area + p, p, 0) &&
25 vm_uniform(area + 3 * p, p, 0x71));
26 CHECK(vm_fault(area + p, 1, SIGSEGV) == 0 && vm_fault(area + 2 * p, 0, SIGSEGV) == 0);
27 CHECK(mprotect(area + 2 * p, p, PROT_READ | PROT_WRITE) == 0 && vm_uniform(area + 2 * p, p, 0));
28 CHECK(madvise(area + 1, p, MADV_DONTNEED) == -1 && errno == EINVAL);
29 CHECK(madvise(area, p, MADV_FREE) == -1 && errno == EINVAL);
30 CHECK(madvise(area, p, 0x7fffffff) == -1 && errno == EINVAL);
31 CHECK(madvise(area, 0, MADV_DONTNEED) == 0 && vm_uniform(area, p, 0x71));
32 CHECK(munmap(area + 3 * p, p) == 0);
33 CHECK(madvise(area, 4 * p, MADV_DONTNEED) == -1 && errno == ENOMEM);
34 CHECK(vm_uniform(area, p, 0x71));
35 CHECK(madvise(area, p, MADV_DONTNEED) == 0);
36 CHECK((target = mmap(NULL, p, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED);
37 CHECK(mremap(area, p, p, MREMAP_FIXED | MREMAP_MAYMOVE, target) == target);
38 CHECK(mincore(target, p, vector) == 0 && vector[0] == 0 && vm_uniform(target, p, 0));
40 if (target != MAP_FAILED)
42 if (area != MAP_FAILED)
47static int file_discard(
void) {
48 int failed = 0, fd = -1;
49 const size_t p = vm_page;
50 unsigned char *
private = MAP_FAILED, *shared = MAP_FAILED, *alias = MAP_FAILED,
52 CHECK((fd = vm_file(3, NULL)) >= 0);
53 CHECK((
private = mmap(NULL, 2 * p, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, p)) != MAP_FAILED);
54 CHECK((shared = mmap(NULL, 2 * p, PROT_READ | PROT_WRITE, MAP_SHARED, fd, p)) != MAP_FAILED);
55 CHECK((alias = mmap(NULL, 3 * p, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) != MAP_FAILED);
58 CHECK(alias[p] == 0x21 && alias[2 * p] == 0xe2);
59 CHECK(close(fd) == 0);
61 CHECK(madvise(
private, 2 * p, MADV_DONTNEED) == 0 &&
private[0] == 0x21 &&
private[p] == 0xe2);
62 CHECK(madvise(shared, 2 * p, MADV_DONTNEED) == 0 && shared[0] == 0x21 && shared[p] == 0xe2);
63 CHECK(alias[2 * p] == 0xe2);
65 CHECK(shared[0] == 0xe3);
66 CHECK(mprotect(
private, 2 * p, PROT_READ) == 0 && madvise(
private, 2 * p, MADV_DONTNEED) == 0);
67 CHECK(
private[0] == 0xe3 &&
private[p] == 0xe2);
68 CHECK(vm_fault(
private, 1, SIGSEGV) == 0);
69 CHECK((target = mmap(NULL, 2 * p, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED);
70 CHECK(mremap(
private, 2 * p, 2 * p, MREMAP_MAYMOVE | MREMAP_FIXED, target) == target);
71 CHECK(target[0] == 0xe3 && target[p] == 0xe2 && vm_fault(target, 1, SIGSEGV) == 0);
75 if (
private != MAP_FAILED)
76 munmap(
private, 2 * p);
77 if (shared != MAP_FAILED)
78 munmap(shared, 2 * p);
79 if (alias != MAP_FAILED)
81 if (target != MAP_FAILED)
82 munmap(target, 2 * p);
86static int shm_discard(
void) {
87 int failed = 0,
id = -1;
88 const size_t p = vm_page;
89 unsigned char *view = (
void*)-1, *alias = (
void*)-1;
90 struct shmid_ds status;
91 CHECK((
id = shmget(IPC_PRIVATE, 2 * p, 0600)) >= 0);
92 CHECK((view = shmat(
id, NULL, 0)) != (
void*)-1 && (alias = shmat(
id, NULL, 0)) != (
void*)-1);
93 memset(view, 0xf1, 2 * p);
95 CHECK(shmctl(
id, SHM_LOCK, NULL) == 0);
96 CHECK(madvise(view, 2 * p, MADV_DONTNEED) == 0 && vm_uniform(alias, 2 * p, 0xf1) &&
97 vm_uniform(view, 2 * p, 0xf1));
98 CHECK(shmctl(
id, IPC_STAT, &status) == 0 && status.shm_nattch == 2 && status.shm_segsz == 2 * p);
100 CHECK(shmctl(
id, SHM_UNLOCK, NULL) == 0);
101 CHECK(shmctl(
id, IPC_RMID, NULL) == 0);
102 CHECK(madvise(view, 2 * p, MADV_DONTNEED) == 0 && madvise(alias, 2 * p, MADV_DONTNEED) == 0);
103 CHECK(vm_uniform(view, 2 * p, 0xf1));
105 CHECK(view[0] == 0xf2);
107 if (view != (
void*)-1)
109 if (alias != (
void*)-1)
112 shmctl(
id, IPC_RMID, NULL);
116static int fork_discard(
void) {
117 int failed = 0, gate[2] = {-1, -1};
118 const size_t p = vm_page;
120 unsigned char* area =
121 mmap(NULL, 2 * p, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
122 CHECK(area != MAP_FAILED);
123 memset(area, 0x81, 2 * p);
124 CHECK(pipe(gate) == 0 && (child = fork()) >= 0);
128 if (read(gate[0], &
byte, 1) != 1 || !vm_uniform(area, 2 * p, 0x81))
130 for (
int n = 0; n < 8; ++n) {
131 if (madvise(area, 2 * p, MADV_DONTNEED) || !vm_uniform(area, 2 * p, 0))
133 memset(area, 0xd0 + n, 2 * p);
135 if (!vm_uniform(area, 2 * p, 0xd0 + n))
140 CHECK(write(gate[1],
"g", 1) == 1);
141 for (
int n = 0; n < 8; ++n) {
142 memset(area, 0xa0 + n, 2 * p);
144 CHECK(vm_uniform(area, 2 * p, 0xa0 + n));
146 int result = vm_reap(child, 3000);
148 CHECK(result == 0 && vm_uniform(area, 2 * p, 0xa7));
151 kill(child, SIGKILL);
152 vm_reap(child, 1000);
154 if (area != MAP_FAILED)
156 for (
int n = 0; n < 2; ++n)
162int vm_test_discard(
void) {
163 return anonymous_discard() || file_discard() || shm_discard() || fork_discard();