did some restructuring, got multitasking almost working
This commit is contained in:
@@ -4,8 +4,9 @@
|
||||
#define KHEAP_START 0xE0000000
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
size_t size;
|
||||
uint8_t free;
|
||||
uint32_t next_blk;
|
||||
void* next_blk;
|
||||
} alloc_header_t;
|
||||
|
||||
void memcpy(const void* src, void* dst, size_t sz) {
|
||||
@@ -42,18 +43,6 @@ static void* kernel_heap_end = (void*)KHEAP_START;
|
||||
alloc_header_t* blk_list = NULL;
|
||||
|
||||
void kgrow(size_t pages) {
|
||||
if (kernel_heap_end == kernel_heap_start) {
|
||||
// probaably not great, but if we don't have a heap yet, allocate the first (or only) frame requested.
|
||||
// Then initialize the first block header for the allocator
|
||||
void* frame = p_alloc_frame();
|
||||
map_page((uint32_t)kernel_heap_end, (uint32_t)frame, PAGE_PRESENT | PAGE_WRITABLE);
|
||||
kernel_heap_end = (void*)((uint32_t)kernel_heap_end + PAGE_SIZE);
|
||||
pages--;
|
||||
blk_list = kernel_heap_start;
|
||||
blk_list->free = 1;
|
||||
blk_list->next_blk = 0;
|
||||
}
|
||||
|
||||
for (size_t p = 0; p < pages; p++) {
|
||||
void* frame = p_alloc_frame();
|
||||
map_page((uint32_t)kernel_heap_end, (uint32_t)frame, PAGE_PRESENT | PAGE_WRITABLE);
|
||||
@@ -61,34 +50,60 @@ void kgrow(size_t pages) {
|
||||
}
|
||||
}
|
||||
|
||||
#define ALIGNMENT 4
|
||||
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
|
||||
void* kalloc(size_t sz) {
|
||||
if (sz == 0) {
|
||||
return NULL;
|
||||
sz = ALIGN(sz);
|
||||
|
||||
if (kernel_heap_end == kernel_heap_start) {
|
||||
// probaably not great, but if we don't have a heap yet, allocate the first (or only) frame requested.
|
||||
// Then initialize the first block header for the allocator
|
||||
kgrow(4);
|
||||
|
||||
blk_list = (alloc_header_t*)kernel_heap_start;
|
||||
blk_list->size = ((uint32_t)kernel_heap_end - (uint32_t)kernel_heap_start) - sizeof(alloc_header_t);
|
||||
blk_list->free = 1;
|
||||
blk_list->next_blk = NULL;
|
||||
}
|
||||
|
||||
alloc_header_t* header = blk_list;
|
||||
while (!header->free) {
|
||||
if (header->next_blk == 0) {
|
||||
return NULL;
|
||||
alloc_header_t* curr = blk_list;
|
||||
alloc_header_t* prev = NULL;
|
||||
|
||||
while (curr != NULL) {
|
||||
if (curr->free && curr->size >= sz) {
|
||||
if (curr->size >= sz + sizeof(alloc_header_t) + ALIGNMENT) {
|
||||
alloc_header_t* new_blk = (alloc_header_t*)((uint32_t)curr + sizeof(alloc_header_t) + sz);
|
||||
|
||||
new_blk->size = curr->size - sz - sizeof(alloc_header_t);
|
||||
new_blk->free = 1;
|
||||
new_blk->next_blk = curr->next_blk;
|
||||
|
||||
curr->size = sz;
|
||||
curr->next_blk = new_blk;
|
||||
}
|
||||
|
||||
curr->free = 0;
|
||||
return (void*)((uint32_t)curr + sizeof(alloc_header_t));
|
||||
}
|
||||
header = (alloc_header_t*)header->next_blk;
|
||||
prev = curr;
|
||||
curr = curr->next_blk;
|
||||
}
|
||||
|
||||
uint32_t data_ptr = (uint32_t)header + sizeof(alloc_header_t);
|
||||
if (data_ptr >= (uint32_t)kernel_heap_end) {
|
||||
return NULL;
|
||||
} // if the start of the data is already at the end, we don't have room
|
||||
|
||||
uint32_t end_of_blk = data_ptr + sz;
|
||||
if (end_of_blk > (uint32_t)kernel_heap_end) {
|
||||
return NULL;
|
||||
} // if the end of the data is past the end, we don't have room
|
||||
|
||||
if (end_of_blk != header->next_blk && end_of_blk < ((uint32_t)kernel_heap_end - sizeof(alloc_header_t))) {
|
||||
header->next_blk = end_of_blk;
|
||||
alloc_header_t* next_header = (alloc_header_t*)header->next_blk;
|
||||
next_header->f
|
||||
} // see if we have room to place the next header and at least 1 byte of data
|
||||
|
||||
return (void*)data_ptr;
|
||||
// no more space, grow!!
|
||||
size_t required_space = sz + sizeof(alloc_header_t);
|
||||
size_t pages_to_grow = (required_space + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||
|
||||
alloc_header_t* new_heap_blk = (alloc_header_t*)kernel_heap_end;
|
||||
|
||||
kgrow(pages_to_grow);
|
||||
|
||||
new_heap_blk->size = (pages_to_grow * PAGE_SIZE) - sizeof(alloc_header_t);
|
||||
new_heap_blk->free = 1;
|
||||
new_heap_blk->next_blk = NULL;
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->next_blk = new_heap_blk;
|
||||
}
|
||||
|
||||
return kalloc(sz);
|
||||
}
|
||||
@@ -11,7 +11,7 @@ int strcmp(const char *s1, const char *s2);
|
||||
int strlen(const char* str);
|
||||
|
||||
void kgrow(size_t pages);
|
||||
void* alloc(size_t sz);
|
||||
void* kalloc(size_t sz);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,20 +1,25 @@
|
||||
#include "print.h"
|
||||
#include "stream.h"
|
||||
#include "tasks.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
extern print_stream_t* kout;
|
||||
#include <drivers/vga/vga.h>
|
||||
|
||||
spinlock_t kwrite_lock = {0};
|
||||
|
||||
static char* hex_chars = "0123456789abcdef";
|
||||
|
||||
static void kprint(const char *str) {
|
||||
while (*str) {
|
||||
kout->putchar(*str);
|
||||
vga_putchar(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static void kputd(int d) {
|
||||
if (d == 0) {
|
||||
kout->putchar('0');
|
||||
vga_putchar('0');
|
||||
return;
|
||||
}
|
||||
char buffer[12];
|
||||
@@ -24,13 +29,13 @@ static void kputd(int d) {
|
||||
d /= 10;
|
||||
}
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
kout->putchar(buffer[j]);
|
||||
vga_putchar(buffer[j]);
|
||||
}
|
||||
}
|
||||
|
||||
static void kputx(unsigned int x) {
|
||||
if (x == 0) {
|
||||
kout->putchar('0');
|
||||
vga_putchar('0');
|
||||
return;
|
||||
}
|
||||
char buffer[8];
|
||||
@@ -41,15 +46,18 @@ static void kputx(unsigned int x) {
|
||||
x >>= 4;
|
||||
}
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
kout->putchar(buffer[j]);
|
||||
vga_putchar(buffer[j]);
|
||||
}
|
||||
}
|
||||
|
||||
void kputc(const char c) {
|
||||
kout->putchar(c);
|
||||
spin_lock(&kwrite_lock);
|
||||
vga_putchar(c);
|
||||
spin_unlock(&kwrite_lock);
|
||||
}
|
||||
|
||||
void kprintf(const char* fmt, ...) {
|
||||
spin_lock(&kwrite_lock);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
@@ -73,19 +81,20 @@ void kprintf(const char* fmt, ...) {
|
||||
break;
|
||||
}
|
||||
case '%':
|
||||
kout->putchar('%');
|
||||
vga_putchar('%');
|
||||
break;
|
||||
default:
|
||||
kout->putchar('%');
|
||||
kout->putchar(*fmt);
|
||||
vga_putchar('%');
|
||||
vga_putchar(*fmt);
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
} else {
|
||||
kout->putchar(*fmt);
|
||||
vga_putchar(*fmt);
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
spin_unlock(&kwrite_lock);
|
||||
}
|
||||
11
kernel/lib/tasks.c
Normal file
11
kernel/lib/tasks.c
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <lib/tasks.h>
|
||||
|
||||
void spin_lock(spinlock_t *lock) {
|
||||
while (__sync_lock_test_and_set(&lock->locked, 1)) {
|
||||
asm volatile("pause");
|
||||
}
|
||||
}
|
||||
|
||||
void spin_unlock(spinlock_t *lock) {
|
||||
__sync_lock_release(&lock->locked);
|
||||
}
|
||||
13
kernel/lib/tasks.h
Normal file
13
kernel/lib/tasks.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef KTASKS_H
|
||||
#define KTASKS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
volatile uint32_t locked;
|
||||
} spinlock_t;
|
||||
|
||||
void spin_lock(spinlock_t *lock);
|
||||
void spin_unlock(spinlock_t *lock);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user