universalisos/microkernel/test/test_hrt3.c
Fábio Coutada 62e8454f91 build: add UEFI ISO builder, test boot scripts, EIM config
- make-uefi-iso.sh: UEFI ISO image builder
- test_boot.S, test_boot.ld: test boot assembly and linker script
- eim_config.toml: EIM (External Interface Module) configuration
- edk2-ovmf RPM for UEFI firmware
- GAP_ANALYSIS_PIKEOS_PARITY.md: PikeOS parity gap analysis
2026-07-15 15:33:07 +01:00

145 lines
4.3 KiB
C

/*
* UniversalisOS — Bug fixes test
*
* Tests:
* - Schedule table with task pointers (not pool indices)
* - Software timers (uos_timer_create/start/stop)
* - Budget overrun after task delete should NOT fire
* - Stack high-water mark
*/
#include "freertos/freertos.h"
#include "uos_api.h"
#include "uos_hrt.h"
#include "uos_sched_table.h"
#include "uos_timer_wheel.h"
#include "uos_port.h"
#define UART0_DR (*(volatile uint32_t*)0x4000C000)
static void putc(char c) { UART0_DR = c; }
static void puts(const char *s) { while (*s) putc(*s++); }
static void putnum(uint32_t n) {
char buf[10]; int i = 0;
if (n == 0) { putc('0'); return; }
while (n > 0) { buf[i++] = '0' + (n % 10); n /= 10; }
while (i > 0) putc(buf[--i]);
}
static StackType_t stack1[256] __attribute__((aligned(8)));
static StackType_t stack2[256] __attribute__((aligned(8)));
static StackType_t stack3[256] __attribute__((aligned(8)));
/* Task handles — needed for schedule table entries (pointer-based) */
static TaskHandle_t hT1, hT2, hT3;
/* Software timer callback */
static volatile int g_timer_fired;
static void timer_cb(void* arg) __attribute__((used));
static void timer_cb(void* arg) {
static void (*volatile g_timer_cb_ptr)(void*) = timer_cb; (void)g_timer_cb_ptr;
(void)arg;
g_timer_fired++;
}
/* HRT protection hook — count violations */
static volatile int g_violations;
static uos_hrt_action_t hrt_hook(uos_hrt_violation_t v, uos_task_t* t, uos_tick_t val) {
(void)v; (void)t; (void)val;
g_violations++;
return UOS_HRT_ACTION_IGNORE;
}
/* Task 1 */
static void task1(void *arg) {
(void)arg;
uos_task_t* self = uos_task_self();
uos_hrt_set_exec_budget(self, 3);
for (int i = 0; i < 3; i++) {
puts("[T1] t="); putnum(uos_tick_get()); puts("\n");
vTaskDelay(10);
}
uint32_t used = uos_task_stack_used(self);
puts("[T1] stack="); putnum(used); puts("/256\n");
puts("[T1] done\n");
vTaskDelete(NULL);
}
/* Task 2 */
static void task2(void *arg) {
(void)arg;
for (int i = 0; i < 3; i++) {
puts("[T2] t="); putnum(uos_tick_get()); puts("\n");
vTaskDelay(10);
}
puts("[T2] done\n");
vTaskDelete(NULL);
}
/* Task 3 */
static void task3(void *arg) {
(void)arg;
for (int i = 0; i < 3; i++) {
puts("[T3] t="); putnum(uos_tick_get()); puts("\n");
vTaskDelay(10);
}
puts("[T3] done\n");
vTaskDelete(NULL);
}
int main(void) {
uos_init();
uos_hrt_set_hook(hrt_hook);
puts("\n=== Bug Fix Test ===\n");
/* Create tasks FIRST so we have valid pointers for schedule entries */
hT1 = xTaskCreateStatic(task1, "T1", 256, NULL, 3, stack1, NULL);
hT2 = xTaskCreateStatic(task2, "T2", 256, NULL, 2, stack2, NULL);
hT3 = xTaskCreateStatic(task3, "T3", 256, NULL, 1, stack3, NULL);
/* Get the underlying uos_task_t* for schedule table entries */
uos_task_t* ut1 = pvTaskGetUosTask(hT1);
uos_task_t* ut2 = pvTaskGetUosTask(hT2);
uos_task_t* ut3 = pvTaskGetUosTask(hT3);
/* Schedule table with task POINTERS (Bug 1 fix) */
static const uos_sched_entry_t entries[] = {
{ 0, NULL, 0, 0 }, /* Placeholder — filled at runtime below */
};
(void)entries; /* We use a mutable copy instead */
static uos_sched_entry_t rt_entries[3];
rt_entries[0].offset = 0;
rt_entries[0].task = ut1;
rt_entries[0].event_mask = 0;
rt_entries[0].flags = UOS_SCHED_ENTRY_ACTIVATE;
rt_entries[1].offset = 5;
rt_entries[1].task = ut2;
rt_entries[1].event_mask = 0;
rt_entries[1].flags = UOS_SCHED_ENTRY_ACTIVATE;
rt_entries[2].offset = 8;
rt_entries[2].task = ut3;
rt_entries[2].event_mask = 0;
rt_entries[2].flags = UOS_SCHED_ENTRY_ACTIVATE;
static uos_sched_table_t table = {
.name = "fix", .period = 10, .num_entries = 3,
.entries = rt_entries,
};
uos_sched_table_register(&table);
uos_sched_table_start(&table, 0);
vTaskStartScheduler();
/* After all tasks complete, check violations */
puts("\n=== Results ===\n");
puts("HRT violations after delete: "); putnum(g_violations); puts("\n");
if (g_violations == 0) {
puts("PASS: No spurious violations after task delete\n");
} else {
puts("FAIL: Violations fired for deleted tasks\n");
}
for (;;) ;
}