Skip to main content

test_mem_stressed/
stressed.rs

1#![no_std]
2#![no_main]
3
4use core::panic::PanicInfo;
5use strat9_syscall::call;
6
7const PAGE_SIZE: usize = 4096;
8
9/// Writes fd.
10fn write_fd(fd: usize, msg: &str) {
11    let _ = call::write(fd, msg.as_bytes());
12}
13
14/// Implements log.
15fn log(msg: &str) {
16    write_fd(1, msg);
17}
18
19/// Implements log err.
20fn log_err(msg: &str) {
21    write_fd(2, msg);
22}
23
24/// Implements log u64.
25fn 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
41/// Implements log hex u64.
42fn 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
58/// Implements section.
59fn section(title: &str) {
60    log("\n############################################################\n");
61    log("[test_mem_stressed] ");
62    log(title);
63    log("\n############################################################\n");
64}
65
66/// Implements query brk.
67fn 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
79/// Sets brk.
80fn 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
94/// Implements pattern byte.
95fn 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
100/// Implements touch pages.
101fn 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
146/// Implements stage fixed rounds.
147fn 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
171/// Implements stage sawtooth heavy.
172fn 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
203/// Implements stage churn loops.
204fn 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]
225/// Implements panic.
226fn panic(_info: &PanicInfo) -> ! {
227    log_err("[test_mem_stressed] PANIC\n");
228    call::exit(250)
229}
230
231#[no_mangle]
232/// Implements start.
233pub 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}