From 358061cd6c44d2902533b50afff63c7dc5743beb Mon Sep 17 00:00:00 2001 From: Karina Date: Tue, 30 Dec 2025 23:53:59 +0400 Subject: [PATCH] feat: basic scheduler; basic composer --- kernel/inc/core/scheduler.h | 14 ++++- kernel/inc/drivers/shitgui.h | 9 ++++ kernel/inc/drivers/timer.h | 2 +- kernel/src/arch/x86_64/interrupts.asm | 3 +- kernel/src/arch/x86_64/interrupts.c | 8 +-- kernel/src/core/scheduler.c | 75 +++++++++++++++++++++++++++ kernel/src/core/string.c | 2 +- kernel/src/drivers/shitgui.c | 73 ++++++++++++++++++++++++++ kernel/src/drivers/timer.c | 4 +- kernel/src/kmain.c | 13 +++-- kernel/src/mm/heap.c | 2 +- kernel/src/shell/dbgcmd.c | 61 +++++++++++++++++++--- 12 files changed, 247 insertions(+), 19 deletions(-) create mode 100644 kernel/src/core/scheduler.c diff --git a/kernel/inc/core/scheduler.h b/kernel/inc/core/scheduler.h index 8ce17a1..4013c20 100644 --- a/kernel/inc/core/scheduler.h +++ b/kernel/inc/core/scheduler.h @@ -1,4 +1,16 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2025 0xKarinyash -#pragma once \ No newline at end of file +#pragma once +#include +typedef struct task { + u64 rsp; + struct task* next; + u32 id; + u32 sleep_ticks; +} task_t; + +void sched_init(); +task_t* sched_spawn(void(*entry)()); +u64 sched_next(u64 curr_rsp); +void yield(u64 ticks); \ No newline at end of file diff --git a/kernel/inc/drivers/shitgui.h b/kernel/inc/drivers/shitgui.h index 1bb7a52..36a749c 100644 --- a/kernel/inc/drivers/shitgui.h +++ b/kernel/inc/drivers/shitgui.h @@ -26,6 +26,15 @@ typedef struct { const unsigned char* base; } SG_Font; +typedef struct { + SG_Context *ctx; + SG_Point pos; + const char *title; +} SG_Window; + +void sg_init(SG_Context *ctx); void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img); void sg_draw_rect(SG_Context *ctx, SG_Point *p, u32 w, u32 h, u32 color); void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Font *font); +SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position); +void composer_task(); \ No newline at end of file diff --git a/kernel/inc/drivers/timer.h b/kernel/inc/drivers/timer.h index bf988e2..632a473 100644 --- a/kernel/inc/drivers/timer.h +++ b/kernel/inc/drivers/timer.h @@ -5,6 +5,6 @@ #include void timer_init(u32 freq); -void timer_handler(); +u64 timer_handler(Registers *regs); void sleep(u64 ms); u64 get_uptime(); diff --git a/kernel/src/arch/x86_64/interrupts.asm b/kernel/src/arch/x86_64/interrupts.asm index ce391fe..96f5dc7 100644 --- a/kernel/src/arch/x86_64/interrupts.asm +++ b/kernel/src/arch/x86_64/interrupts.asm @@ -70,9 +70,10 @@ global %2 mov rdi, rsp cld call irq_handler_c + + mov rsp, rax POPALL - add rsp, 16 iretq %endmacro diff --git a/kernel/src/arch/x86_64/interrupts.c b/kernel/src/arch/x86_64/interrupts.c index 3a2e65f..e1e4fc2 100644 --- a/kernel/src/arch/x86_64/interrupts.c +++ b/kernel/src/arch/x86_64/interrupts.c @@ -16,12 +16,14 @@ void isr_handler_c(Registers *regs) { panic_exception(regs); } -void irq_handler_c(Registers *regs) { +u64 irq_handler_c(Registers *regs) { + u64 curr_rsp = (u64)regs; switch (regs->int_no) { - case 32: return timer_handler(); - case 33: return kb_handler(); + case 32: curr_rsp = timer_handler(regs); break; + case 33: kb_handler(); break; default: outb(SLAVE_COMMAND, 0x20); break; } outb(MASTER_COMMAND, 0x20); + return curr_rsp; } \ No newline at end of file diff --git a/kernel/src/core/scheduler.c b/kernel/src/core/scheduler.c new file mode 100644 index 0000000..9ef5501 --- /dev/null +++ b/kernel/src/core/scheduler.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2025 0xKarinyash + +#include +#include +#include + +task_t* curr_task = nullptr; +u32 next_pid = 1; + +extern void irq0_handler(); + +void sched_init() { + task_t* kt = (task_t*)malloc(sizeof(task_t)); + + kt->id = 0; + kt->sleep_ticks = 0; + kt->next = kt; + + curr_task = kt; +} + +task_t* sched_spawn(void(*entry)()) { + task_t* t = (task_t*)malloc(sizeof(task_t)); + if (!t) return nullptr; + + u64 stack_size = 16384; + u8* stack_base = (u8*)malloc(stack_size); + if (!stack_base) panic("OOM for task stack"); + u64* rsp = (u64*)(stack_base + stack_size); + + *--rsp = 0x10; // SS -- Kernel data + *--rsp = (u64)stack_base + stack_size; // rsp + *--rsp = 0x202; // RFLAGS -- Interrupts Enabled | Reserved bit; + *--rsp = 0x08; // CS -- Kernel Code; + *--rsp = (u64)entry; // RIP + + *--rsp = 0; // int no + *--rsp = 0; // err code + + for (u8 i = 0; i < 15; i++) *--rsp = 0; // R15 .. RAX + + t->rsp = (u64)rsp; + t->id = next_pid++; + t->sleep_ticks = 0; + t->next = curr_task->next; + curr_task->next = t; + + return t; +} + +u64 sched_next(u64 curr_rsp) { + if (!curr_task) return curr_rsp; + + curr_task->rsp = curr_rsp; + task_t* it = curr_task->next; + + do { + if (it->sleep_ticks > 0) it->sleep_ticks--; + it = it->next; + } while (it != curr_task->next); + + if (curr_task->sleep_ticks > 0) curr_task->sleep_ticks--; + + task_t* next = curr_task->next; + while (next != curr_task && next->sleep_ticks > 0) next = next->next; // what the fuck i just wrote + + curr_task = next; + return curr_task->rsp; +} + +void yield(u64 ticks) { + curr_task->sleep_ticks = ticks; + __asm__ volatile("hlt"); +} \ No newline at end of file diff --git a/kernel/src/core/string.c b/kernel/src/core/string.c index 7cba331..49a1e1a 100644 --- a/kernel/src/core/string.c +++ b/kernel/src/core/string.c @@ -3,7 +3,7 @@ #include -i32 strcmp(const char* s1, const char* s2) { +i32 strcmp(const char *s1, const char *s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; diff --git a/kernel/src/drivers/shitgui.c b/kernel/src/drivers/shitgui.c index 08d3f07..9068277 100644 --- a/kernel/src/drivers/shitgui.c +++ b/kernel/src/drivers/shitgui.c @@ -1,9 +1,22 @@ // SPDX-License-Identifier: GPL-3.0-or-later // Copyright (c) 2025 0xKarinyash +#include +#include #include +#include +#include #define SHITGUI_TRANSPARENCY_KEY 0xFF00FF +#define SHITGUI_MAX_WINDOWS_AMOUNT 64 + +SG_Context* main_context; +SG_Window* windows[SHITGUI_MAX_WINDOWS_AMOUNT]; // нет блять линукс +u64 windows_amount = 0; + +void sg_init(SG_Context *ctx) { + main_context = ctx; +} void sg_put_img(SG_Context *ctx, SG_Point *p, SG_Image *img) { if (!ctx->fb || !img) return; @@ -67,4 +80,64 @@ void sg_draw_char_bitmap(SG_Context *ctx, SG_Point *p, char c, u32 color, SG_Fon } } } +} + +SG_Window* create_window(const char *title, SG_Point* size, SG_Point* position) { + if (windows_amount >= SHITGUI_MAX_WINDOWS_AMOUNT) return nullptr; + SG_Context* ctx = nullptr; + u32* fb = nullptr; + SG_Window* window = nullptr; + + ctx = (SG_Context*)malloc(sizeof(SG_Context)); + if (!ctx) goto fail; // goto is GOOD for cleaning up in C stfu. + // Mainline linux kernel contains 100k gotos + + fb = malloc(size->x * size->y * sizeof(u32)); + if (!fb) goto fail; + memset(fb, 0, size->x * size->y * sizeof(u32)); + + window = (SG_Window*)malloc(sizeof(SG_Window)); + if (!window) goto fail; + + ctx->fb = fb; + ctx->height = size->y; + ctx->width = size->x; + ctx->pitch = size->x; + + + window->ctx = ctx; + window->title = title; + window->pos.x = position->x; + window->pos.y = position->y; + + windows[windows_amount] = window; + windows_amount++; + + return window; + +fail: + if (ctx) free(ctx); + if (fb) free(fb); + if (window) free(window); + + return nullptr; +} + +void render_window(SG_Context *ctx, SG_Window *window) { + SG_Image img = {0}; + img.buffer = window->ctx->fb; + if (!img.buffer) panic("No img buffer found"); + img.height = window->ctx->height; + img.width = window->ctx->width; + + sg_put_img(ctx, &window->pos, &img); +} + +void composer_task() { + while (true) { + for (u64 i = 0; i < windows_amount; i++) { + render_window(main_context, windows[i]); + } + yield(1); + } } \ No newline at end of file diff --git a/kernel/src/drivers/timer.c b/kernel/src/drivers/timer.c index 0ce13c7..2bd8291 100644 --- a/kernel/src/drivers/timer.c +++ b/kernel/src/drivers/timer.c @@ -4,6 +4,7 @@ #include #include #include +#include #define PIT_BASE_CLOCK 1193180 #define PIT_CMD 0x43 @@ -23,9 +24,10 @@ void timer_init(u32 freq) { outb(0x21, mask); } -void timer_handler() { +u64 timer_handler(Registers *regs) { ticks++; outb(MASTER_COMMAND, 0x20); + return sched_next((u64)regs); } void sleep(u64 ms) { diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index ec651aa..cb1d315 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -2,6 +2,7 @@ // Copyright (c) 2025 0xKarinyash #include "bootinfo.h" +#include "core/scheduler.h" #include #include @@ -48,6 +49,10 @@ void kmain(Bootinfo* info) { kprintf("Timer initialized\n"); heap_init(); kprintf("Heap initialized\n"); + sched_init(); + kprintf("Scheduler initialized\n"); + sg_init(&sg_ctx); + kprintf("Shitgui initialized"); info = (Bootinfo*)PHYS_TO_HHDM((u64)info); @@ -65,8 +70,10 @@ void kmain(Bootinfo* info) { show_splash(&sg_ctx); - ksh(); - - panic("Kernel main loop exited"); + sched_spawn(composer_task); + sched_spawn(ksh); + __asm__ volatile("sti"); + while (true) __asm__ volatile("hlt"); + panic("How in the name of God you got here?"); } \ No newline at end of file diff --git a/kernel/src/mm/heap.c b/kernel/src/mm/heap.c index 57cb173..02319ad 100644 --- a/kernel/src/mm/heap.c +++ b/kernel/src/mm/heap.c @@ -8,7 +8,7 @@ #include #include -#define HEAP_SIZE_PAGES 32 +#define HEAP_SIZE_PAGES 1024 extern u64* pml4_kernel; static block_header* heap_list_head = nullptr; diff --git a/kernel/src/shell/dbgcmd.c b/kernel/src/shell/dbgcmd.c index 9755fb9..e34e1e8 100644 --- a/kernel/src/shell/dbgcmd.c +++ b/kernel/src/shell/dbgcmd.c @@ -3,18 +3,65 @@ // contents of this file will be changed CONSTANTLY // im just testing new stuff here +#include "core/panic.h" +#include "drivers/shitgui.h" #include #include #include #include +#include + +SG_Window* win_a = nullptr; +SG_Window* win_b = nullptr; + +void a() { + SG_Point sizes = {0}; + sizes.x = win_a->ctx->width; + sizes.y = win_a->ctx->height; + + u64 t = 0; + while (true) { + for (u32 y = 0; y < sizes.y; y++) { + for (u32 x = 0; x < sizes.x; x++) { + win_a->ctx->fb[y * sizes.x + x] = (x * y) ^ t; + } + } + t++; + } +} +void b() { + SG_Point sizes = {0}; + sizes.x = win_b->ctx->width; + sizes.y = win_b->ctx->height; + + u64 t = 0; + while (true) { + for (u32 y = 0; y < sizes.y; y++) { + for (u32 x = 0; x < sizes.x; x++) { + win_b->ctx->fb[y * sizes.x + x] = (x ^ y) ^ t; + } + } + t++; + } +} + u64 debug() { - kprintf("Float test\n"); - kprintf("Trying 3.14 + 1.44 in 3 seconds..\n"); - sleep(3000); - volatile float a = 3.14; - volatile float b = 1.44; - volatile float c = a + b; - kprintf("%d", (i32)c); + kprintf("scheduler test\n"); + SG_Point sizes = {0}; + sizes.x = 256; + sizes.y = 256; + SG_Point pos_a = {0}; + pos_a.x = 100; + pos_a.y = 40; + SG_Point pos_b = {0}; + pos_b.x = 512; + pos_b.y = 40; + win_a = create_window("A", &sizes, &pos_a); + if (!win_a) panic("No win a"); + win_b = create_window("B", &sizes, &pos_b); + if (!win_b) panic("No win b"); + sched_spawn(a); + sched_spawn(b); return 0; } \ No newline at end of file