feat: basic scheduler; basic composer
This commit is contained in:
@@ -1,4 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <types.h>
|
||||
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);
|
||||
@@ -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();
|
||||
@@ -5,6 +5,6 @@
|
||||
#include <types.h>
|
||||
|
||||
void timer_init(u32 freq);
|
||||
void timer_handler();
|
||||
u64 timer_handler(Registers *regs);
|
||||
void sleep(u64 ms);
|
||||
u64 get_uptime();
|
||||
|
||||
@@ -70,9 +70,10 @@ global %2
|
||||
mov rdi, rsp
|
||||
cld
|
||||
call irq_handler_c
|
||||
|
||||
mov rsp, rax
|
||||
|
||||
POPALL
|
||||
|
||||
add rsp, 16
|
||||
iretq
|
||||
%endmacro
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <core/panic.h>
|
||||
#include <core/scheduler.h>
|
||||
#include <mm/heap.h>
|
||||
|
||||
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");
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <core/string.h>
|
||||
|
||||
i32 strcmp(const char* s1, const char* s2) {
|
||||
i32 strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include <core/scheduler.h>
|
||||
#include <core/panic.h>
|
||||
#include <drivers/shitgui.h>
|
||||
#include <mm/heap.h>
|
||||
#include <mm/memory.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <drivers/timer.h>
|
||||
#include <io.h>
|
||||
#include <types.h>
|
||||
#include <core/scheduler.h>
|
||||
|
||||
#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) {
|
||||
|
||||
+10
-3
@@ -2,6 +2,7 @@
|
||||
// Copyright (c) 2025 0xKarinyash
|
||||
|
||||
#include "bootinfo.h"
|
||||
#include "core/scheduler.h"
|
||||
#include <shell/ksh.h>
|
||||
|
||||
#include <types.h>
|
||||
@@ -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?");
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <core/panic.h>
|
||||
#include <types.h>
|
||||
|
||||
#define HEAP_SIZE_PAGES 32
|
||||
#define HEAP_SIZE_PAGES 1024
|
||||
|
||||
extern u64* pml4_kernel;
|
||||
static block_header* heap_list_head = nullptr;
|
||||
|
||||
@@ -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 <drivers/timer.h>
|
||||
#include <drivers/console.h>
|
||||
#include <types.h>
|
||||
#include <shell/dbgcmd.h>
|
||||
|
||||
#include <core/scheduler.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user