tianole/kernel/selftest/sched.c

109 lines
2.6 KiB
C

#include <stdint.h>
#include <tianole/early_log.h>
#include <tianole/sched.h>
#include <tianole/spinlock.h>
#include "sched/sched.h"
#define STACK_ALIGNMENT 16u
static void thread_selftest_entry(void *arg)
{
(void)arg;
}
void sched_selftest(void)
{
struct spinlock test_lock;
struct thread *first =
kernel_thread_create("worker-a", thread_selftest_entry, 0);
struct thread *second =
kernel_thread_create("worker-b", thread_selftest_entry, 0);
uint64_t flags;
test_lock.locked = 0;
if (first == 0 || second == 0 || first == second) {
panic("kernel thread selftest allocation failed");
}
if (first->id == second->id || first->state != THREAD_READY ||
second->state != THREAD_READY) {
panic("kernel thread selftest state failed");
}
if ((first->stack_top & (STACK_ALIGNMENT - 1)) != 0 ||
(second->stack_top & (STACK_ALIGNMENT - 1)) != 0) {
panic("kernel thread selftest stack alignment failed");
}
if (run_queue_head != first || first->next != second ||
run_queue_tail != second) {
panic("kernel thread selftest run queue failed");
}
spin_lock_irqsave(&test_lock, &flags);
spin_unlock_irqrestore(&test_lock, flags);
early_log_puts("kernel thread selftest ok\n");
}
static void scheduler_demo_entry(void *arg)
{
uint64_t id = (uint64_t)(uintptr_t)arg;
uint64_t step;
for (step = 1; step <= 3; step++) {
early_log_puts("preempt thread ");
early_log_u64_decimal(id);
early_log_puts(" step=");
early_log_u64_decimal(step);
early_log_puts("\n");
sched_sleep(2);
}
}
static struct wait_queue demo_wait_queue;
static void wait_queue_demo_waiter(void *arg)
{
(void)arg;
early_log_puts("waiter sleeping\n");
wait_queue_sleep(&demo_wait_queue);
early_log_puts("waiter woke\n");
}
static void wait_queue_demo_waker(void *arg)
{
(void)arg;
early_log_puts("waker sleeping\n");
sched_sleep(4);
early_log_puts("waker wake_one\n");
wait_queue_wake_one(&demo_wait_queue);
}
void sched_demo_start(void)
{
struct thread *first = kernel_thread_create(
"round-robin-a", scheduler_demo_entry, (void *)(uintptr_t)1);
struct thread *second = kernel_thread_create(
"round-robin-b", scheduler_demo_entry, (void *)(uintptr_t)2);
struct thread *waiter =
kernel_thread_create("waiter", wait_queue_demo_waiter, 0);
struct thread *waker =
kernel_thread_create("waker", wait_queue_demo_waker, 0);
if (first == 0 || second == 0 || waiter == 0 || waker == 0) {
panic("scheduler demo thread creation failed");
}
wait_queue_init(&demo_wait_queue);
early_log_puts("scheduler starting\n");
sched_yield();
panic("scheduler returned to boot context");
}