test_mem_stressed/
stressed.rs1#![no_std]
2#![no_main]
3
4use core::panic::PanicInfo;
5use strat9_syscall::call;
6
7const PAGE_SIZE: usize = 4096;
8
9fn write_fd(fd: usize, msg: &str) {
11 let _ = call::write(fd, msg.as_bytes());
12}
13
14fn log(msg: &str) {
16 write_fd(1, msg);
17}
18
19fn log_err(msg: &str) {
21 write_fd(2, msg);
22}
23
24fn log_u64(mut value: u64) {
26 let mut buf = [0u8; 21];
27 if value == 0 {
28 log("0");
29 return;
30 }
31 let mut i = buf.len();
32 while value > 0 {
33 i -= 1;
34 buf[i] = b'0' + (value % 10) as u8;
35 value /= 10;
36 }
37 let s = unsafe { core::str::from_utf8_unchecked(&buf[i..]) };
38 log(s);
39}
40
41fn log_hex_u64(mut value: u64) {
43 let mut buf = [0u8; 16];
44 for i in (0..16).rev() {
45 let nibble = (value & 0xF) as u8;
46 buf[i] = if nibble < 10 {
47 b'0' + nibble
48 } else {
49 b'a' + (nibble - 10)
50 };
51 value >>= 4;
52 }
53 log("0x");
54 let s = unsafe { core::str::from_utf8_unchecked(&buf) };
55 log(s);
56}
57
58fn section(title: &str) {
60 log("\n############################################################\n");
61 log("[test_mem_stressed] ");
62 log(title);
63 log("\n############################################################\n");
64}
65
66fn query_brk() -> usize {
68 match call::brk(0) {
69 Ok(v) => v,
70 Err(e) => {
71 log_err("[test_mem_stressed] brk(0) failed: ");
72 log_err(e.name());
73 log_err("\n");
74 call::exit(201);
75 }
76 }
77}
78
79fn set_brk(new_brk: usize, ctx: &str) -> usize {
81 match call::brk(new_brk) {
82 Ok(v) => v,
83 Err(e) => {
84 log_err("[test_mem_stressed] brk(set) failed in ");
85 log_err(ctx);
86 log_err(": ");
87 log_err(e.name());
88 log_err("\n");
89 call::exit(202);
90 }
91 }
92}
93
94fn pattern_byte(seed: u8, page: usize, pos: usize) -> u8 {
96 seed.wrapping_add((page as u8).wrapping_mul(13))
97 .wrapping_add(pos as u8)
98}
99
100fn touch_pages(base: usize, pages: usize, seed: u8, tag: &str) {
102 log("[test_mem_stressed] touch ");
103 log(tag);
104 log(" base=");
105 log_hex_u64(base as u64);
106 log(" pages=");
107 log_u64(pages as u64);
108 log(" seed=");
109 log_hex_u64(seed as u64);
110 log("\n");
111
112 let total = pages * PAGE_SIZE;
113 let buf = unsafe { core::slice::from_raw_parts_mut(base as *mut u8, total) };
114 let marks = [0usize, 31usize, 511usize, 2047usize, 4095usize];
115
116 for p in 0..pages {
117 let page_off = p * PAGE_SIZE;
118 for &m in &marks {
119 buf[page_off + m] = pattern_byte(seed, p, m);
120 }
121 }
122
123 for p in 0..pages {
124 let page_off = p * PAGE_SIZE;
125 for &m in &marks {
126 let expected = pattern_byte(seed, p, m);
127 let got = buf[page_off + m];
128 if got != expected {
129 log_err("[test_mem_stressed] verify mismatch page=");
130 log_u64(p as u64);
131 log_err(" mark=");
132 log_u64(m as u64);
133 log_err(" expected=");
134 log_hex_u64(expected as u64);
135 log_err(" got=");
136 log_hex_u64(got as u64);
137 log_err(" tag=");
138 log_err(tag);
139 log_err("\n");
140 call::exit(203);
141 }
142 }
143 }
144}
145
146fn stage_fixed_rounds() {
148 section("Stage A: fixed-size rounds (up to 128 pages)");
149 let base = query_brk();
150 let rounds = [1usize, 2, 4, 8, 16, 32, 64, 128];
151 for (i, pages) in rounds.iter().enumerate() {
152 let target = base + pages * PAGE_SIZE;
153 log("[test_mem_stressed] round=");
154 log_u64(i as u64);
155 log(" grow->pages=");
156 log_u64(*pages as u64);
157 log(" target=");
158 log_hex_u64(target as u64);
159 log("\n");
160 let _ = set_brk(target, "stage_fixed_rounds_grow");
161 touch_pages(
162 base,
163 *pages,
164 (0x20 + i as u8).wrapping_mul(3),
165 "fixed_round",
166 );
167 let _ = set_brk(base, "stage_fixed_rounds_shrink");
168 }
169}
170
171fn stage_sawtooth_heavy() {
173 section("Stage B: heavy saw-tooth (split/coalesce pressure)");
174 let base = query_brk();
175 let mut pages = 3usize;
176
177 for step in 0..120usize {
178 let grow = base + pages * PAGE_SIZE;
179 let _ = set_brk(grow, "sawtooth_grow");
180 touch_pages(base, pages, (0x60u8).wrapping_add(step as u8), "sawtooth");
181
182 let shrink_pages = (pages / 3).max(1);
183 let shrink = base + shrink_pages * PAGE_SIZE;
184 let _ = set_brk(shrink, "sawtooth_shrink");
185
186 if step % 10 == 0 {
187 log("[test_mem_stressed] step=");
188 log_u64(step as u64);
189 log(" pages=");
190 log_u64(pages as u64);
191 log(" shrink_pages=");
192 log_u64(shrink_pages as u64);
193 log("\n");
194 }
195
196 pages = if pages >= 192 { 5 } else { pages + 7 };
197 let _ = call::sched_yield();
198 }
199
200 let _ = set_brk(base, "sawtooth_end");
201}
202
203fn stage_churn_loops() {
205 section("Stage C: many small/medium churn loops");
206 let base = query_brk();
207 for i in 0..300usize {
208 let pages = 1 + ((i * 11) % 48);
209 let target = base + pages * PAGE_SIZE;
210 let _ = set_brk(target, "churn_grow");
211 touch_pages(base, pages, (0xA0u8).wrapping_add(i as u8), "churn");
212 let _ = set_brk(base, "churn_shrink");
213
214 if i % 25 == 0 {
215 log("[test_mem_stressed] churn checkpoint i=");
216 log_u64(i as u64);
217 log(" pages=");
218 log_u64(pages as u64);
219 log("\n");
220 }
221 }
222}
223
224#[panic_handler]
225fn panic(_info: &PanicInfo) -> ! {
227 log_err("[test_mem_stressed] PANIC\n");
228 call::exit(250)
229}
230
231#[no_mangle]
232pub extern "C" fn _start() -> ! {
234 section("Start");
235 log("[test_mem_stressed] test intensif (verbose) demarre\n");
236 log("[test_mem_stressed] NOTE: binaire manuel, non lance automatiquement a l'init\n");
237
238 let pid = call::getpid().unwrap_or(0);
239 let tid = call::gettid().unwrap_or(0);
240 log("[test_mem_stressed] pid=");
241 log_u64(pid as u64);
242 log(" tid=");
243 log_u64(tid as u64);
244 log("\n");
245
246 stage_fixed_rounds();
247 stage_sawtooth_heavy();
248 stage_churn_loops();
249
250 section("Done");
251 log("[test_mem_stressed] SUCCESS\n");
252 call::exit(0)
253}