blob: 8e672257a5a6f2c5838d0eb0ed637bdd1061de5e [file] [log] [blame]
/*
* Copyright (c) 2024 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/linker/sections.h>
#include <mmu.h> /* for k_mem_num_pagefaults_get() */
/*
* We want to artificially create a huge body of code hence the volatile
* to prevent the compiler from optimizing everything down.
*/
volatile long foo_val1;
volatile long foo_val2;
/*
* This function is tagged with __ondemand_func to be placed in a special
* "ondemand" segment by the linker. This means it is not loaded into memory
* at boot time but rather page-by-page on demand when actually executed.
* It is also subject to being evicted when memory reclamation occurs.
*/
static void __ondemand_func huge_evictable_function(void)
{
foo_val1 = 13131313;
foo_val2 = 45454545;
#define CODE \
foo_val1 *= foo_val2; \
foo_val2 += 1234567; \
foo_val1 -= 9876543210; \
__asm__ __volatile__ (".rep 1000; nop; .endr");
#define REPEAT_10(x) x x x x x x x x x x
#define REPEAT_1000(x) REPEAT_10(REPEAT_10(REPEAT_10(x)))
REPEAT_1000(CODE)
#undef REPEAT_1000
#undef REPEAT_10
#undef CODE
}
int main(void)
{
size_t free_pages_before, free_pages_after;
unsigned long faults_before, faults_after;
printk("Calling huge body of code that doesn't fit in memory\n");
free_pages_before = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
faults_before = k_mem_num_pagefaults_get();
huge_evictable_function();
free_pages_after = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
faults_after = k_mem_num_pagefaults_get();
printk("free memory pages: from %zd to %zd, %ld page faults\n",
free_pages_before, free_pages_after, faults_after - faults_before);
printk("Calling it a second time\n");
free_pages_before = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
faults_before = k_mem_num_pagefaults_get();
huge_evictable_function();
free_pages_after = k_mem_free_get() / CONFIG_MMU_PAGE_SIZE;
faults_after = k_mem_num_pagefaults_get();
printk("free memory pages: from %zd to %zd, %ld page faults\n",
free_pages_before, free_pages_after, faults_after - faults_before);
printk("Done.\n");
return 0;
}