mirror of
https://github.com/Leonmmcoset/cleonos.git
synced 2026-04-21 18:44:01 +00:00
Stage 9
This commit is contained in:
1
Makefile
1
Makefile
@@ -92,6 +92,7 @@ C_SOURCES := \
|
|||||||
clks/kernel/fs.c \
|
clks/kernel/fs.c \
|
||||||
clks/kernel/userland.c \
|
clks/kernel/userland.c \
|
||||||
clks/kernel/driver.c \
|
clks/kernel/driver.c \
|
||||||
|
clks/kernel/service.c \
|
||||||
clks/lib/string.c \
|
clks/lib/string.c \
|
||||||
clks/drivers/serial/serial.c \
|
clks/drivers/serial/serial.c \
|
||||||
clks/drivers/video/framebuffer.c \
|
clks/drivers/video/framebuffer.c \
|
||||||
|
|||||||
@@ -4,10 +4,13 @@
|
|||||||
typedef unsigned long long u64;
|
typedef unsigned long long u64;
|
||||||
typedef unsigned long long usize;
|
typedef unsigned long long usize;
|
||||||
|
|
||||||
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL
|
#define CLEONOS_SYSCALL_LOG_WRITE 0ULL
|
||||||
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
|
#define CLEONOS_SYSCALL_TIMER_TICKS 1ULL
|
||||||
#define CLEONOS_SYSCALL_TASK_COUNT 2ULL
|
#define CLEONOS_SYSCALL_TASK_COUNT 2ULL
|
||||||
#define CLEONOS_SYSCALL_CUR_TASK 3ULL
|
#define CLEONOS_SYSCALL_CUR_TASK 3ULL
|
||||||
|
#define CLEONOS_SYSCALL_SERVICE_COUNT 4ULL
|
||||||
|
#define CLEONOS_SYSCALL_SERVICE_READY_COUNT 5ULL
|
||||||
|
#define CLEONOS_SYSCALL_CONTEXT_SWITCHES 6ULL
|
||||||
|
|
||||||
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
u64 cleonos_sys_log_write(const char *message, u64 length);
|
u64 cleonos_sys_log_write(const char *message, u64 length);
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ struct clks_scheduler_stats {
|
|||||||
|
|
||||||
void clks_scheduler_init(void);
|
void clks_scheduler_init(void);
|
||||||
clks_bool clks_scheduler_add_kernel_task(const char *name, u32 time_slice_ticks);
|
clks_bool clks_scheduler_add_kernel_task(const char *name, u32 time_slice_ticks);
|
||||||
|
clks_bool clks_scheduler_add_kernel_task_ex(const char *name, u32 time_slice_ticks, clks_task_entry_fn entry);
|
||||||
void clks_scheduler_on_timer_tick(u64 tick);
|
void clks_scheduler_on_timer_tick(u64 tick);
|
||||||
|
void clks_scheduler_dispatch_current(u64 tick);
|
||||||
struct clks_scheduler_stats clks_scheduler_get_stats(void);
|
struct clks_scheduler_stats clks_scheduler_get_stats(void);
|
||||||
const struct clks_task_descriptor *clks_scheduler_get_task(u32 task_id);
|
const struct clks_task_descriptor *clks_scheduler_get_task(u32 task_id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
36
clks/include/clks/service.h
Normal file
36
clks/include/clks/service.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef CLKS_SERVICE_H
|
||||||
|
#define CLKS_SERVICE_H
|
||||||
|
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_SERVICE_NAME_MAX 24U
|
||||||
|
|
||||||
|
enum clks_service_id {
|
||||||
|
CLKS_SERVICE_LOG = 1,
|
||||||
|
CLKS_SERVICE_MEM = 2,
|
||||||
|
CLKS_SERVICE_FS = 3,
|
||||||
|
CLKS_SERVICE_DRIVER = 4,
|
||||||
|
CLKS_SERVICE_SCHED = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum clks_service_state {
|
||||||
|
CLKS_SERVICE_STATE_OFFLINE = 0,
|
||||||
|
CLKS_SERVICE_STATE_READY = 1,
|
||||||
|
CLKS_SERVICE_STATE_DEGRADED = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clks_service_info {
|
||||||
|
u32 id;
|
||||||
|
char name[CLKS_SERVICE_NAME_MAX];
|
||||||
|
enum clks_service_state state;
|
||||||
|
u64 heartbeat_count;
|
||||||
|
u64 last_heartbeat_tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
void clks_service_init(void);
|
||||||
|
clks_bool clks_service_heartbeat(u32 service_id, u64 tick);
|
||||||
|
u64 clks_service_count(void);
|
||||||
|
u64 clks_service_ready_count(void);
|
||||||
|
clks_bool clks_service_get(u32 service_id, struct clks_service_info *out_info);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,13 +3,16 @@
|
|||||||
|
|
||||||
#include <clks/types.h>
|
#include <clks/types.h>
|
||||||
|
|
||||||
#define CLKS_SYSCALL_LOG_WRITE 0ULL
|
#define CLKS_SYSCALL_LOG_WRITE 0ULL
|
||||||
#define CLKS_SYSCALL_TIMER_TICKS 1ULL
|
#define CLKS_SYSCALL_TIMER_TICKS 1ULL
|
||||||
#define CLKS_SYSCALL_TASK_COUNT 2ULL
|
#define CLKS_SYSCALL_TASK_COUNT 2ULL
|
||||||
#define CLKS_SYSCALL_CURRENT_TASK_ID 3ULL
|
#define CLKS_SYSCALL_CURRENT_TASK_ID 3ULL
|
||||||
|
#define CLKS_SYSCALL_SERVICE_COUNT 4ULL
|
||||||
|
#define CLKS_SYSCALL_SERVICE_READY_COUNT 5ULL
|
||||||
|
#define CLKS_SYSCALL_CONTEXT_SWITCHES 6ULL
|
||||||
|
|
||||||
void clks_syscall_init(void);
|
void clks_syscall_init(void);
|
||||||
u64 clks_syscall_dispatch(void *frame_ptr);
|
u64 clks_syscall_dispatch(void *frame_ptr);
|
||||||
u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#define CLKS_TASK_NAME_MAX 32U
|
#define CLKS_TASK_NAME_MAX 32U
|
||||||
|
|
||||||
|
typedef void (*clks_task_entry_fn)(u64 tick);
|
||||||
|
|
||||||
enum clks_task_state {
|
enum clks_task_state {
|
||||||
CLKS_TASK_UNUSED = 0,
|
CLKS_TASK_UNUSED = 0,
|
||||||
CLKS_TASK_READY = 1,
|
CLKS_TASK_READY = 1,
|
||||||
@@ -20,6 +22,9 @@ struct clks_task_descriptor {
|
|||||||
u32 remaining_ticks;
|
u32 remaining_ticks;
|
||||||
u64 total_ticks;
|
u64 total_ticks;
|
||||||
u64 switch_count;
|
u64 switch_count;
|
||||||
|
u64 run_count;
|
||||||
|
u64 last_run_tick;
|
||||||
|
clks_task_entry_fn entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,11 +11,46 @@
|
|||||||
#include <clks/pmm.h>
|
#include <clks/pmm.h>
|
||||||
#include <clks/scheduler.h>
|
#include <clks/scheduler.h>
|
||||||
#include <clks/serial.h>
|
#include <clks/serial.h>
|
||||||
|
#include <clks/service.h>
|
||||||
#include <clks/syscall.h>
|
#include <clks/syscall.h>
|
||||||
#include <clks/tty.h>
|
#include <clks/tty.h>
|
||||||
#include <clks/types.h>
|
#include <clks/types.h>
|
||||||
#include <clks/userland.h>
|
#include <clks/userland.h>
|
||||||
|
|
||||||
|
static void clks_task_klogd(u64 tick) {
|
||||||
|
static u64 last_emit = 0ULL;
|
||||||
|
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_LOG, tick);
|
||||||
|
|
||||||
|
if (tick - last_emit >= 1000ULL) {
|
||||||
|
clks_log_hex(CLKS_LOG_DEBUG, "TASK", "KLOGD_TICK", tick);
|
||||||
|
last_emit = tick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clks_task_kworker(u64 tick) {
|
||||||
|
static u32 phase = 0U;
|
||||||
|
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_SCHED, tick);
|
||||||
|
|
||||||
|
switch (phase) {
|
||||||
|
case 0U:
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_MEM, tick);
|
||||||
|
break;
|
||||||
|
case 1U:
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_FS, tick);
|
||||||
|
break;
|
||||||
|
case 2U:
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_DRIVER, tick);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
clks_service_heartbeat(CLKS_SERVICE_LOG, tick);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
phase = (phase + 1U) & 3U;
|
||||||
|
}
|
||||||
|
|
||||||
void clks_kernel_main(void) {
|
void clks_kernel_main(void) {
|
||||||
const struct limine_framebuffer *boot_fb;
|
const struct limine_framebuffer *boot_fb;
|
||||||
const struct limine_memmap_response *boot_memmap;
|
const struct limine_memmap_response *boot_memmap;
|
||||||
@@ -41,7 +76,7 @@ void clks_kernel_main(void) {
|
|||||||
clks_tty_init();
|
clks_tty_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE8 START");
|
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE9 START");
|
||||||
|
|
||||||
if (boot_fb == CLKS_NULL) {
|
if (boot_fb == CLKS_NULL) {
|
||||||
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
|
||||||
@@ -112,17 +147,19 @@ void clks_kernel_main(void) {
|
|||||||
|
|
||||||
clks_scheduler_init();
|
clks_scheduler_init();
|
||||||
|
|
||||||
if (clks_scheduler_add_kernel_task("klogd", 4U) == CLKS_FALSE) {
|
if (clks_scheduler_add_kernel_task_ex("klogd", 4U, clks_task_klogd) == CLKS_FALSE) {
|
||||||
clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KLOGD TASK");
|
clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KLOGD TASK");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clks_scheduler_add_kernel_task("kworker", 3U) == CLKS_FALSE) {
|
if (clks_scheduler_add_kernel_task_ex("kworker", 3U, clks_task_kworker) == CLKS_FALSE) {
|
||||||
clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KWORKER TASK");
|
clks_log(CLKS_LOG_WARN, "SCHED", "FAILED TO ADD KWORKER TASK");
|
||||||
}
|
}
|
||||||
|
|
||||||
sched_stats = clks_scheduler_get_stats();
|
sched_stats = clks_scheduler_get_stats();
|
||||||
clks_log_hex(CLKS_LOG_INFO, "SCHED", "TASK_COUNT", sched_stats.task_count);
|
clks_log_hex(CLKS_LOG_INFO, "SCHED", "TASK_COUNT", sched_stats.task_count);
|
||||||
|
|
||||||
|
clks_service_init();
|
||||||
|
|
||||||
clks_elfrunner_init();
|
clks_elfrunner_init();
|
||||||
|
|
||||||
if (clks_elfrunner_probe_kernel_executable() == CLKS_FALSE) {
|
if (clks_elfrunner_probe_kernel_executable() == CLKS_FALSE) {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void clks_scheduler_init(void) {
|
|||||||
clks_total_timer_ticks = 0;
|
clks_total_timer_ticks = 0;
|
||||||
clks_context_switch_count = 0;
|
clks_context_switch_count = 0;
|
||||||
|
|
||||||
clks_scheduler_add_kernel_task("idle", 1U);
|
clks_scheduler_add_kernel_task_ex("idle", 1U, CLKS_NULL);
|
||||||
|
|
||||||
clks_tasks[0].state = CLKS_TASK_RUNNING;
|
clks_tasks[0].state = CLKS_TASK_RUNNING;
|
||||||
clks_tasks[0].remaining_ticks = clks_tasks[0].time_slice_ticks;
|
clks_tasks[0].remaining_ticks = clks_tasks[0].time_slice_ticks;
|
||||||
@@ -52,7 +52,7 @@ void clks_scheduler_init(void) {
|
|||||||
clks_log(CLKS_LOG_INFO, "SCHED", "ROUND-ROBIN ONLINE");
|
clks_log(CLKS_LOG_INFO, "SCHED", "ROUND-ROBIN ONLINE");
|
||||||
}
|
}
|
||||||
|
|
||||||
clks_bool clks_scheduler_add_kernel_task(const char *name, u32 time_slice_ticks) {
|
clks_bool clks_scheduler_add_kernel_task_ex(const char *name, u32 time_slice_ticks, clks_task_entry_fn entry) {
|
||||||
struct clks_task_descriptor *task;
|
struct clks_task_descriptor *task;
|
||||||
|
|
||||||
if (name == CLKS_NULL) {
|
if (name == CLKS_NULL) {
|
||||||
@@ -73,13 +73,42 @@ clks_bool clks_scheduler_add_kernel_task(const char *name, u32 time_slice_ticks)
|
|||||||
task->state = CLKS_TASK_READY;
|
task->state = CLKS_TASK_READY;
|
||||||
task->time_slice_ticks = time_slice_ticks;
|
task->time_slice_ticks = time_slice_ticks;
|
||||||
task->remaining_ticks = time_slice_ticks;
|
task->remaining_ticks = time_slice_ticks;
|
||||||
task->total_ticks = 0;
|
task->total_ticks = 0ULL;
|
||||||
task->switch_count = 0;
|
task->switch_count = 0ULL;
|
||||||
|
task->run_count = 0ULL;
|
||||||
|
task->last_run_tick = 0ULL;
|
||||||
|
task->entry = entry;
|
||||||
|
|
||||||
clks_task_count++;
|
clks_task_count++;
|
||||||
return CLKS_TRUE;
|
return CLKS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clks_bool clks_scheduler_add_kernel_task(const char *name, u32 time_slice_ticks) {
|
||||||
|
return clks_scheduler_add_kernel_task_ex(name, time_slice_ticks, CLKS_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clks_scheduler_dispatch_current(u64 tick) {
|
||||||
|
struct clks_task_descriptor *current;
|
||||||
|
|
||||||
|
if (clks_task_count == 0U) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = &clks_tasks[clks_current_task];
|
||||||
|
|
||||||
|
if (current->state != CLKS_TASK_RUNNING && current->state != CLKS_TASK_READY) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->state = CLKS_TASK_RUNNING;
|
||||||
|
current->run_count++;
|
||||||
|
current->last_run_tick = tick;
|
||||||
|
|
||||||
|
if (current->entry != CLKS_NULL) {
|
||||||
|
current->entry(tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void clks_scheduler_on_timer_tick(u64 tick) {
|
void clks_scheduler_on_timer_tick(u64 tick) {
|
||||||
struct clks_task_descriptor *current;
|
struct clks_task_descriptor *current;
|
||||||
|
|
||||||
@@ -88,7 +117,6 @@ void clks_scheduler_on_timer_tick(u64 tick) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clks_total_timer_ticks = tick;
|
clks_total_timer_ticks = tick;
|
||||||
|
|
||||||
current = &clks_tasks[clks_current_task];
|
current = &clks_tasks[clks_current_task];
|
||||||
|
|
||||||
if (current->state == CLKS_TASK_RUNNING || current->state == CLKS_TASK_READY) {
|
if (current->state == CLKS_TASK_RUNNING || current->state == CLKS_TASK_READY) {
|
||||||
@@ -116,6 +144,8 @@ void clks_scheduler_on_timer_tick(u64 tick) {
|
|||||||
clks_context_switch_count++;
|
clks_context_switch_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clks_scheduler_dispatch_current(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct clks_scheduler_stats clks_scheduler_get_stats(void) {
|
struct clks_scheduler_stats clks_scheduler_get_stats(void) {
|
||||||
@@ -135,4 +165,4 @@ const struct clks_task_descriptor *clks_scheduler_get_task(u32 task_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &clks_tasks[task_id];
|
return &clks_tasks[task_id];
|
||||||
}
|
}
|
||||||
|
|||||||
138
clks/kernel/service.c
Normal file
138
clks/kernel/service.c
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
#include <clks/driver.h>
|
||||||
|
#include <clks/fs.h>
|
||||||
|
#include <clks/heap.h>
|
||||||
|
#include <clks/log.h>
|
||||||
|
#include <clks/scheduler.h>
|
||||||
|
#include <clks/service.h>
|
||||||
|
#include <clks/string.h>
|
||||||
|
#include <clks/types.h>
|
||||||
|
|
||||||
|
#define CLKS_SERVICE_MAX 8U
|
||||||
|
|
||||||
|
static struct clks_service_info clks_services[CLKS_SERVICE_MAX];
|
||||||
|
static u64 clks_service_used = 0ULL;
|
||||||
|
|
||||||
|
static void clks_service_copy_name(char *dst, usize dst_size, const char *src) {
|
||||||
|
usize i = 0U;
|
||||||
|
|
||||||
|
if (dst == CLKS_NULL || dst_size == 0U) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i + 1U < dst_size && src[i] != '\0') {
|
||||||
|
dst[i] = src[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[i] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static i32 clks_service_find_index(u32 service_id) {
|
||||||
|
u64 i;
|
||||||
|
|
||||||
|
for (i = 0ULL; i < clks_service_used; i++) {
|
||||||
|
if (clks_services[i].id == service_id) {
|
||||||
|
return (i32)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static clks_bool clks_service_register(u32 id, const char *name, enum clks_service_state state) {
|
||||||
|
struct clks_service_info *slot;
|
||||||
|
|
||||||
|
if (clks_service_used >= CLKS_SERVICE_MAX) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot = &clks_services[clks_service_used];
|
||||||
|
clks_memset(slot, 0, sizeof(*slot));
|
||||||
|
|
||||||
|
slot->id = id;
|
||||||
|
clks_service_copy_name(slot->name, sizeof(slot->name), name);
|
||||||
|
slot->state = state;
|
||||||
|
slot->heartbeat_count = 0ULL;
|
||||||
|
slot->last_heartbeat_tick = 0ULL;
|
||||||
|
|
||||||
|
clks_service_used++;
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clks_service_init(void) {
|
||||||
|
struct clks_heap_stats heap_stats;
|
||||||
|
|
||||||
|
clks_memset(clks_services, 0, sizeof(clks_services));
|
||||||
|
clks_service_used = 0ULL;
|
||||||
|
|
||||||
|
heap_stats = clks_heap_get_stats();
|
||||||
|
|
||||||
|
clks_service_register(CLKS_SERVICE_LOG, "log", CLKS_SERVICE_STATE_READY);
|
||||||
|
clks_service_register(CLKS_SERVICE_MEM,
|
||||||
|
"memory",
|
||||||
|
(heap_stats.total_bytes > 0U) ? CLKS_SERVICE_STATE_READY : CLKS_SERVICE_STATE_DEGRADED);
|
||||||
|
clks_service_register(CLKS_SERVICE_FS,
|
||||||
|
"filesystem",
|
||||||
|
(clks_fs_is_ready() == CLKS_TRUE) ? CLKS_SERVICE_STATE_READY : CLKS_SERVICE_STATE_DEGRADED);
|
||||||
|
clks_service_register(CLKS_SERVICE_DRIVER,
|
||||||
|
"driver",
|
||||||
|
(clks_driver_count() > 0ULL) ? CLKS_SERVICE_STATE_READY : CLKS_SERVICE_STATE_DEGRADED);
|
||||||
|
clks_service_register(CLKS_SERVICE_SCHED,
|
||||||
|
"scheduler",
|
||||||
|
CLKS_SERVICE_STATE_READY);
|
||||||
|
|
||||||
|
clks_log(CLKS_LOG_INFO, "SRV", "KERNEL SERVICES ONLINE");
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "SRV", "COUNT", clks_service_count());
|
||||||
|
clks_log_hex(CLKS_LOG_INFO, "SRV", "READY", clks_service_ready_count());
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_service_heartbeat(u32 service_id, u64 tick) {
|
||||||
|
i32 idx = clks_service_find_index(service_id);
|
||||||
|
|
||||||
|
if (idx < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_services[(u32)idx].heartbeat_count++;
|
||||||
|
clks_services[(u32)idx].last_heartbeat_tick = tick;
|
||||||
|
|
||||||
|
if (clks_services[(u32)idx].state == CLKS_SERVICE_STATE_OFFLINE) {
|
||||||
|
clks_services[(u32)idx].state = CLKS_SERVICE_STATE_READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 clks_service_count(void) {
|
||||||
|
return clks_service_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 clks_service_ready_count(void) {
|
||||||
|
u64 i;
|
||||||
|
u64 ready = 0ULL;
|
||||||
|
|
||||||
|
for (i = 0ULL; i < clks_service_used; i++) {
|
||||||
|
if (clks_services[i].state == CLKS_SERVICE_STATE_READY) {
|
||||||
|
ready++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ready;
|
||||||
|
}
|
||||||
|
|
||||||
|
clks_bool clks_service_get(u32 service_id, struct clks_service_info *out_info) {
|
||||||
|
i32 idx;
|
||||||
|
|
||||||
|
if (out_info == CLKS_NULL) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = clks_service_find_index(service_id);
|
||||||
|
|
||||||
|
if (idx < 0) {
|
||||||
|
return CLKS_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_info = clks_services[(u32)idx];
|
||||||
|
return CLKS_TRUE;
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <clks/interrupts.h>
|
#include <clks/interrupts.h>
|
||||||
#include <clks/log.h>
|
#include <clks/log.h>
|
||||||
#include <clks/scheduler.h>
|
#include <clks/scheduler.h>
|
||||||
|
#include <clks/service.h>
|
||||||
#include <clks/syscall.h>
|
#include <clks/syscall.h>
|
||||||
#include <clks/types.h>
|
#include <clks/types.h>
|
||||||
|
|
||||||
@@ -83,6 +84,14 @@ u64 clks_syscall_dispatch(void *frame_ptr) {
|
|||||||
struct clks_scheduler_stats stats = clks_scheduler_get_stats();
|
struct clks_scheduler_stats stats = clks_scheduler_get_stats();
|
||||||
return stats.current_task_id;
|
return stats.current_task_id;
|
||||||
}
|
}
|
||||||
|
case CLKS_SYSCALL_SERVICE_COUNT:
|
||||||
|
return clks_service_count();
|
||||||
|
case CLKS_SYSCALL_SERVICE_READY_COUNT:
|
||||||
|
return clks_service_ready_count();
|
||||||
|
case CLKS_SYSCALL_CONTEXT_SWITCHES: {
|
||||||
|
struct clks_scheduler_stats stats = clks_scheduler_get_stats();
|
||||||
|
return stats.context_switch_count;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return (u64)-1;
|
return (u64)-1;
|
||||||
}
|
}
|
||||||
@@ -99,4 +108,4 @@ u64 clks_syscall_invoke_kernel(u64 id, u64 arg0, u64 arg1, u64 arg2) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
36
docs/stage9.md
Normal file
36
docs/stage9.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# CLeonOS Stage9
|
||||||
|
|
||||||
|
## Stage Goal
|
||||||
|
- Add kernel service layer to represent core kernel capabilities.
|
||||||
|
- Extend scheduler with real task execution callbacks on timer ticks.
|
||||||
|
- Connect worker tasks (`klogd`, `kworker`) to service heartbeat updates.
|
||||||
|
- Extend syscall interface with service and scheduler runtime counters.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
- Kernel boots and prints `CLEONOS STAGE9 START`.
|
||||||
|
- Service framework logs `KERNEL SERVICES ONLINE`.
|
||||||
|
- Service counters (`COUNT`, `READY`) are logged.
|
||||||
|
- Scheduler still reports task count and runs without panic.
|
||||||
|
- Syscall layer remains online and returns valid ticks after interrupt init.
|
||||||
|
|
||||||
|
## Build Targets
|
||||||
|
- `make setup`
|
||||||
|
- `make userapps`
|
||||||
|
- `make iso`
|
||||||
|
- `make run`
|
||||||
|
- `make debug`
|
||||||
|
|
||||||
|
## QEMU Command
|
||||||
|
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
|
||||||
|
|
||||||
|
## Common Bugs and Debugging
|
||||||
|
- `undefined reference` for service APIs:
|
||||||
|
- Ensure `clks/kernel/service.c` is listed in `C_SOURCES`.
|
||||||
|
- Task callbacks never run:
|
||||||
|
- Confirm timer IRQ path still calls `clks_scheduler_on_timer_tick()`.
|
||||||
|
- Service count is 0:
|
||||||
|
- Verify `clks_service_init()` is called after scheduler/driver/fs init.
|
||||||
|
- Syscall service counters return `-1`:
|
||||||
|
- Check syscall IDs in kernel and user headers match.
|
||||||
|
- Boot panic after Stage9 merge:
|
||||||
|
- Re-check `kmain` init order: FS -> userland -> driver -> scheduler -> service -> interrupts.
|
||||||
Reference in New Issue
Block a user