8static int future_mappings(
void) {
10 unsigned char* existing = MAP_FAILED;
11 unsigned char* victim = MAP_FAILED;
12 void* future = MAP_FAILED;
13 void* populated = MAP_FAILED;
14 void* locked = MAP_FAILED;
15 existing = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
16 victim = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
17 CHECK(existing != MAP_FAILED && victim != MAP_FAILED);
19 CHECK(ml_limit(2 * ml_page) == 0);
20 CHECK(mlock(existing, ml_page) == 0);
21 CHECK(mlockall(MCL_FUTURE | MCL_ONFAULT) == 0);
22 CHECK(ml_unprivileged() == 0);
23 future = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
24 CHECK(future != MAP_FAILED && ml_resident(future, 1, 0,
"future onfault mapping") == 0);
26 CHECK(madvise(existing, ml_page, MADV_DONTNEED) == -1 && errno == EINVAL);
28 CHECK(mmap(NULL, ml_page, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED &&
31 CHECK(mmap(victim, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1,
34 CHECK(victim[0] == 0x6d);
35 CHECK(munmap(future, ml_page) == 0);
37 future = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
38 CHECK(future != MAP_FAILED);
39 CHECK(munlockall() == 0 && madvise(existing, ml_page, MADV_DONTNEED) == 0);
40 CHECK(madvise(future, ml_page, MADV_DONTNEED) == 0);
43 mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0);
44 CHECK(locked != MAP_FAILED && ml_resident(locked, 1, 1,
"MAP_LOCKED eager mapping") == 0);
46 CHECK(mmap(NULL, 2 * ml_page, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_LOCKED, -1, 0) ==
49 populated = mmap(NULL, 2 * ml_page, PROT_READ | PROT_WRITE,
50 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
51 CHECK(populated != MAP_FAILED && ml_resident(populated, 2, 3,
"MAP_POPULATE") == 0);
52 CHECK(mlock(populated, ml_page) == 0);
54 CHECK(mlock((
unsigned char*)populated + ml_page, ml_page) == -1 && errno == ENOMEM);
57 if (locked != MAP_FAILED)
58 munmap(locked, ml_page);
59 if (populated != MAP_FAILED)
60 munmap(populated, 2 * ml_page);
61 if (future != MAP_FAILED)
62 munmap(future, ml_page);
63 if (victim != MAP_FAILED)
64 munmap(victim, ml_page);
65 if (existing != MAP_FAILED)
66 munmap(existing, ml_page);
70static int current_mappings(
void) {
72 void* lazy = MAP_FAILED;
73 void* later = MAP_FAILED;
74 CHECK(ml_limit(16 * 1024 * 1024) == 0);
75 lazy = mmap(NULL, 3 * ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
76 CHECK(lazy != MAP_FAILED && ml_resident(lazy, 3, 0,
"before CURRENT") == 0);
77 CHECK(mlockall(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT) == 0);
78 CHECK(ml_resident(lazy, 3, 0,
"CURRENT ONFAULT") == 0);
80 CHECK(madvise(lazy, 3 * ml_page, MADV_DONTNEED) == -1 && errno == EINVAL);
81 CHECK(mlockall(MCL_CURRENT) == 0);
82 CHECK(ml_resident(lazy, 3, 7,
"CURRENT eager population") == 0);
83 CHECK(ml_limit(0) == 0);
84 later = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
85 CHECK(later != MAP_FAILED && madvise(later, ml_page, MADV_DONTNEED) == 0);
87 CHECK(madvise(lazy, ml_page, MADV_DONTNEED) == -1 && errno == EINVAL);
88 CHECK(munlockall() == 0 && madvise(lazy, 3 * ml_page, MADV_DONTNEED) == 0);
91 if (later != MAP_FAILED)
92 munmap(later, ml_page);
93 if (lazy != MAP_FAILED)
94 munmap(lazy, 3 * ml_page);
98static int remap_charge(
void) {
100 unsigned char* source = MAP_FAILED;
101 unsigned char* target = MAP_FAILED;
102 void* extra = MAP_FAILED;
103 size_t source_length = 2 * ml_page;
105 CHECK(ml_limit(2 * ml_page) == 0);
106 source = mmap(NULL, source_length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
107 target = mmap(NULL, 3 * ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
108 extra = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
109 CHECK(source != MAP_FAILED && target != MAP_FAILED && extra != MAP_FAILED);
111 source[ml_page] = 0x62;
112 target[0] = target[2 * ml_page] = 0x74;
113 CHECK(mlock(source, source_length) == 0);
115 CHECK(mremap(source, source_length, 3 * ml_page, MREMAP_MAYMOVE | MREMAP_FIXED, target) ==
118 CHECK(source[0] == 0x39 && source[ml_page] == 0x62 && target[0] == 0x74);
119 CHECK(mremap(source, source_length, source_length, MREMAP_MAYMOVE | MREMAP_FIXED, target) ==
123 CHECK(source[0] == 0x39 && source[ml_page] == 0x62 && target[2 * ml_page] == 0x74);
124 CHECK(ml_resident(source, 2, 3,
"locked remap retains residency") == 0);
126 CHECK(mlock(extra, ml_page) == -1 && errno == ENOMEM);
127 CHECK(mremap(source, source_length, ml_page, 0) == source);
128 source_length = ml_page;
129 CHECK(mlock(extra, ml_page) == 0);
131 CHECK(madvise(source, ml_page, MADV_DONTNEED) == -1 && errno == EINVAL);
134 if (extra != MAP_FAILED)
135 munmap(extra, ml_page);
136 if (source != MAP_FAILED && !moved)
137 munmap(source, source_length);
138 if (target != MAP_FAILED)
139 munmap(target, 3 * ml_page);
143static int file_charge(
void) {
146 unsigned char* shared = MAP_FAILED;
147 unsigned char*
private = MAP_FAILED;
148 void* alias = MAP_FAILED;
149 CHECK(ml_limit(4 * ml_page) == 0);
150 fd = memfd_create(
"locked-file", MFD_CLOEXEC);
151 CHECK(fd >= 0 && ftruncate(fd, 3 * ml_page) == 0);
152 for (
size_t n = 0; n < 3; ++n) {
153 unsigned char value = 0x41 + n;
154 CHECK(pwrite(fd, &value, 1, n * ml_page) == 1);
156 shared = mmap(NULL, 3 * ml_page, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
157 private = mmap(NULL, ml_page, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
158 alias = mmap(NULL, ml_page, PROT_READ, MAP_SHARED, fd, ml_page);
159 CHECK(shared != MAP_FAILED &&
private != MAP_FAILED && alias != MAP_FAILED);
160 CHECK(mlock(shared, 3 * ml_page) == 0 && mlock(
private, ml_page) == 0);
162 CHECK(shared[0] == 0x41);
164 CHECK(mlock(alias, ml_page) == -1 && errno == ENOMEM);
166 CHECK(msync(shared, ml_page, MS_SYNC | MS_INVALIDATE) == -1 && errno == EBUSY);
167 CHECK(ftruncate(fd, ml_page + 137) == 0);
168 CHECK(ml_resident(shared, 2, 3,
"locked file retained prefix") == 0);
169 CHECK(shared[0] == 0x41 && shared[ml_page] == 0x42 &&
private[0] == 0x77);
171 CHECK(mlock(alias, ml_page) == -1 && errno == ENOMEM);
172 CHECK(ftruncate(fd, 3 * ml_page) == 0);
173 CHECK(shared[ml_page + 137] == 0 && shared[2 * ml_page] == 0);
174 CHECK(munlock(shared, ml_page) == 0 && mlock(alias, ml_page) == 0);
176 CHECK(madvise(shared, 3 * ml_page, MADV_DONTNEED) == -1 && errno == EINVAL);
177 CHECK(shared[0] == 0x41 &&
private[0] == 0x77);
180 if (alias != MAP_FAILED)
181 munmap(alias, ml_page);
182 if (
private != MAP_FAILED)
183 munmap(
private, ml_page);
184 if (shared != MAP_FAILED)
185 munmap(shared, 3 * ml_page);
191int ml_managed(
void) {
192 return future_mappings() || current_mappings() || remap_charge() || file_charge();