1 /*
2 * Copyright (c) 2024 BayLibre SAS
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/linker/sections.h>
9
10 #include <mmu.h> /* for k_mem_num_pagefaults_get() */
11
12 /*
13 * We want to artificially create a huge body of code hence the volatile
14 * to prevent the compiler from optimizing everything down.
15 */
16 volatile long foo_val1;
17 volatile long foo_val2;
18
19 /*
20 * This function is tagged with __ondemand_func to be placed in a special
21 * "ondemand" segment by the linker. This means it is not loaded into memory
22 * at boot time but rather page-by-page on demand when actually executed.
23 * It is also subject to being evicted when memory reclamation occurs.
24 */
huge_evictable_function(void)25 static void __ondemand_func huge_evictable_function(void)
26 {
27 foo_val1 = 13131313;
28 foo_val2 = 45454545;
29
30 #define CODE \
31 foo_val1 *= foo_val2; \
32 foo_val2 += 1234567; \
33 foo_val1 -= 9876543210; \
34 __asm__ __volatile__ (".rep 1000; nop; .endr");
35
36 #define REPEAT_10(x) x x x x x x x x x x
37 #define REPEAT_1000(x) REPEAT_10(REPEAT_10(REPEAT_10(x)))
38
39 REPEAT_1000(CODE)
40
41 #undef REPEAT_1000
42 #undef REPEAT_10
43 #undef CODE
44 }
45
main(void)46 int main(void)
47 {
48 size_t free_pages_before, free_pages_after;
49 unsigned long faults_before, faults_after;
50
51 printk("Calling huge body of code that doesn't fit in memory\n");
52 free_pages_before = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
53 faults_before = k_mem_num_pagefaults_get();
54
55 huge_evictable_function();
56
57 free_pages_after = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
58 faults_after = k_mem_num_pagefaults_get();
59 printk("free memory pages: from %zd to %zd, %ld page faults\n",
60 free_pages_before, free_pages_after, faults_after - faults_before);
61
62 printk("Calling it a second time\n");
63 free_pages_before = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
64 faults_before = k_mem_num_pagefaults_get();
65
66 huge_evictable_function();
67
68 free_pages_after = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
69 faults_after = k_mem_num_pagefaults_get();
70 printk("free memory pages: from %zd to %zd, %ld page faults\n",
71 free_pages_before, free_pages_after, faults_after - faults_before);
72
73 printk("Done.\n");
74 return 0;
75 }
76