mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Made malloc() and free()! They're in header stdlib.h as syscalls 3 & 4.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
#ifndef STDLIB_H
|
||||
#define STDLIB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void* malloc(const uint32_t size) { // Use Syscall(3) - Malloc()
|
||||
void* ptr = 0;
|
||||
__asm__ volatile ("int $0x80" : : "a"(3), "b"(size));
|
||||
__asm__ volatile ("movl %%eax, %0" : "=r"(ptr));
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free(const void* ptr) { // Use Syscall(4) - Free()
|
||||
__asm__ volatile ("int $0x80" : : "a"(4), "b"(ptr));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,14 @@
|
||||
#ifndef SYSCALL_H
|
||||
#define SYSCALL_H
|
||||
|
||||
#include <interrupt/idt.h>
|
||||
#include <interrupt/pit.h>
|
||||
#include <screen/text.h>
|
||||
#include <keyboard/keyboard.h>
|
||||
#include <memory/malloc.h>
|
||||
|
||||
// System call count
|
||||
#define MAX_SYSCALLS 3
|
||||
#define MAX_SYSCALLS 5
|
||||
|
||||
// Args: ebx - number of miliseconds
|
||||
void sys_sleep() {
|
||||
@@ -35,22 +37,48 @@ void sys_gets() {
|
||||
read(s);
|
||||
}
|
||||
|
||||
// Args: ebx - amount of bytes to malloc
|
||||
void sys_malloc() {
|
||||
uint32_t size = 0;
|
||||
__asm__ volatile ("movl %%ebx, %0" : "=b"(size));
|
||||
|
||||
// First Malloc()
|
||||
if (!mallocListHead) {
|
||||
mallocInit(size); // Setup malloc linked list
|
||||
}
|
||||
|
||||
void* ptr = mallocNextNode(size);
|
||||
mallocMergeFree();
|
||||
|
||||
// Return allocated address in eax
|
||||
__asm__ volatile ("movl %0, %%eax" : : "r"(ptr));
|
||||
}
|
||||
|
||||
// Args: ebx - allocated pointer
|
||||
void sys_free() {
|
||||
void* ptr = NULL;
|
||||
__asm__ volatile ("movl %%ebx, %0" : "=b"(ptr));
|
||||
mallocFree(ptr);
|
||||
}
|
||||
|
||||
// System call table
|
||||
void* syscalls[MAX_SYSCALLS] = {
|
||||
sys_sleep, // Syscall(0)
|
||||
sys_puts, // Syscall(1)
|
||||
sys_gets, // Syscall(2)
|
||||
sys_sleep, // Syscall(0)
|
||||
sys_puts, // Syscall(1)
|
||||
sys_gets, // Syscall(2)
|
||||
sys_malloc, // Syscall(3)
|
||||
sys_free, // Syscall(4)
|
||||
};
|
||||
|
||||
// int 0x80 - Syscall interrupt, handled by this function
|
||||
// eax : Syscall number
|
||||
__attribute__ ((naked)) // No prologue or epilogue, just assembly
|
||||
void syscallHandler(void) {
|
||||
void syscallHandler(intFrame_t* iframe) {
|
||||
// Interrupt - Stack should contain: ss, esp, eflags, cs, eip
|
||||
// We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx
|
||||
__asm__ volatile (
|
||||
".intel_syntax noprefix\n" // We use intel syntax
|
||||
".equ MAX_SYSCALLS, 3\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this
|
||||
".equ MAX_SYSCALLS, 5\n" // Define MAX_SYSCALLS again TODO: I don't want to have to do this
|
||||
|
||||
// Check if syscall exists
|
||||
"cmp eax, MAX_SYSCALLS - 1\n"
|
||||
@@ -86,6 +114,7 @@ void syscallHandler(void) {
|
||||
|
||||
// TODO: Send an error or something here
|
||||
"invalidSyscall:\n"
|
||||
"mov eax, -1\n" // Current error thing
|
||||
"iretd\n"
|
||||
|
||||
".att_syntax" // Switch back to Att Syntax (Just in case)
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
#ifndef MALLOC_H
|
||||
#define MALLOC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <memory/virtual.h>
|
||||
#include <memory/physical.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Singly linked list!
|
||||
typedef struct mallocNode_s {
|
||||
uint32_t size;
|
||||
bool free;
|
||||
struct mallocNode_s* next;
|
||||
} mallocNode_t;
|
||||
|
||||
mallocNode_t* mallocListHead = NULL;
|
||||
static uint32_t mallocVirtualAddr = 0;
|
||||
static uint32_t mallocPhysicalAddr = 0;
|
||||
static uint32_t mallocPages = 0;
|
||||
|
||||
void mallocInit(uint32_t size) {
|
||||
mallocPages = size / PAGE_SIZE;
|
||||
if (size % PAGE_SIZE > 0) { mallocPages++; }
|
||||
|
||||
mallocPhysicalAddr = (uint32_t)allocBlocks(mallocPages);
|
||||
mallocListHead = (mallocNode_t*)mallocVirtualAddr;
|
||||
|
||||
// Map pages
|
||||
for (uint32_t i = 0, virtualAddr = mallocVirtualAddr; i < mallocPages; i++, virtualAddr += PAGE_SIZE) {
|
||||
mapPage((void*)(mallocPhysicalAddr + i * PAGE_SIZE), (void*)virtualAddr);
|
||||
|
||||
ptEntry_t* page = getPage(virtualAddr);
|
||||
SET_ATTR(page, PTE_READ_WRITE);
|
||||
}
|
||||
|
||||
if (mallocListHead) {
|
||||
mallocListHead->size = (mallocPages * PAGE_SIZE) - sizeof(mallocNode_t);
|
||||
mallocListHead->free = true;
|
||||
mallocListHead->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void mallocSplit(mallocNode_t* node, uint32_t size) {
|
||||
if (node->size < size + sizeof(mallocNode_t)) { return; } // Can't split - node too small
|
||||
|
||||
// Remainder node
|
||||
mallocNode_t* newNode = (mallocNode_t*)((void*)node + size + sizeof(mallocNode_t));
|
||||
newNode->size = node->size - size - sizeof(mallocNode_t);
|
||||
newNode->free = true;
|
||||
newNode->next = node->next;
|
||||
|
||||
// Split node
|
||||
node->size = size;
|
||||
node->free = false;
|
||||
node->next = newNode;
|
||||
}
|
||||
|
||||
void* mallocNextNode(uint32_t size) {
|
||||
if (size == 0) { return NULL; } // Why would you try that? (undefined behaviour i guess)
|
||||
|
||||
mallocNode_t* current = mallocListHead;
|
||||
|
||||
if (mallocListHead->size == 0) { mallocInit(size); }
|
||||
|
||||
while (((current->size < size) || !current->free) && current->next != NULL) {
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (current->size == size) {
|
||||
current->free = false;
|
||||
} else if (current->size > size + sizeof(mallocNode_t)) {
|
||||
mallocSplit(current, size); // Modifies current into the right size and makes it point to the remainder
|
||||
} else { // There's no large enough node -> try to allocate more pages
|
||||
uint8_t pageCount = 1;
|
||||
while (current->size + pageCount * PAGE_SIZE < size + sizeof(mallocNode_t)) {
|
||||
pageCount++;
|
||||
}
|
||||
|
||||
// Allocate and map new pages
|
||||
uint32_t virtualAddr = mallocVirtualAddr + mallocPages * PAGE_SIZE;
|
||||
for (uint32_t i = 0; i < pageCount; i++) {
|
||||
ptEntry_t page = 0;
|
||||
uint32_t* temp = allocPage(&page);
|
||||
|
||||
mapPage((void*)temp, (void*)virtualAddr);
|
||||
SET_ATTR(&page, PTE_READ_WRITE);
|
||||
virtualAddr += PAGE_SIZE;
|
||||
current->size += PAGE_SIZE;
|
||||
mallocPages++;
|
||||
}
|
||||
|
||||
mallocSplit(current, size);
|
||||
}
|
||||
|
||||
return (void*)current + sizeof(mallocNode_t);
|
||||
}
|
||||
|
||||
void mallocMergeFree() {
|
||||
mallocNode_t* current = mallocListHead;
|
||||
|
||||
while (current && current->next != NULL) {
|
||||
if (current->free && current->next->free) {
|
||||
current->size += (current->next->size) + sizeof(mallocNode_t);
|
||||
current->next = current->next->next;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
void mallocFree(void* ptr) {
|
||||
mallocNode_t* current = mallocListHead;
|
||||
|
||||
while (current->next) {
|
||||
if ((void*)current + sizeof(mallocNode_t) == ptr) {
|
||||
current->free = true;
|
||||
mallocMergeFree();
|
||||
break;
|
||||
}
|
||||
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
|
||||
__attribute__ ((section ("entry")))
|
||||
void main() {
|
||||
char msg[8] = { 'H','e','l','l','o','!','\n',0 };
|
||||
print(msg);
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
ENTRY("main");
|
||||
SECTIONS {
|
||||
.text : {
|
||||
*(entry);
|
||||
*(.text*);
|
||||
}
|
||||
.data : {
|
||||
@@ -13,3 +13,4 @@ SECTIONS {
|
||||
*(.bss*);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-1
@@ -16,6 +16,7 @@
|
||||
#include <sound/notes.h>
|
||||
#include <memory/virtual.h>
|
||||
#include <memory/addresses.h>
|
||||
#include <memory/malloc.h>
|
||||
|
||||
#define PROMPT "#> "
|
||||
|
||||
@@ -303,8 +304,29 @@ void main() {
|
||||
|
||||
diskRead(sector, size, entryPoint);
|
||||
|
||||
if (strcmp(fileType, "bin") == 0) { // TODO: Improve this
|
||||
if (strcmp(fileType, "bin") == 0) {
|
||||
// Reset malloc
|
||||
mallocListHead = NULL;
|
||||
mallocVirtualAddr = (uint32_t)entryPoint + neededPages * PAGE_SIZE;
|
||||
mallocPhysicalAddr = 0;
|
||||
mallocPages = 0;
|
||||
|
||||
((void(*)(void))entryPoint)(); // Call program
|
||||
|
||||
for (uint32_t i = 0, virtualAddr = mallocVirtualAddr; i < mallocPages; i++, virtualAddr += PAGE_SIZE) {
|
||||
ptEntry_t* page = getPage(virtualAddr);
|
||||
|
||||
if (PAGE_PHYS_ADDRESS(page) && TEST_ATTR(page, PTE_PRESENT)) {
|
||||
freePage(page);
|
||||
unmapPage((void*)virtualAddr);
|
||||
flushTlbEntry(virtualAddr);
|
||||
}
|
||||
}
|
||||
|
||||
mallocListHead = NULL;
|
||||
mallocVirtualAddr = 0;
|
||||
mallocPhysicalAddr = 0;
|
||||
mallocPages = 0;
|
||||
} else if (strcmp(fileType, "tab") == 0) {
|
||||
printFiletable(entryPoint);
|
||||
} else if (strcmp(fileType, "fnt") == 0) {
|
||||
|
||||
@@ -89,13 +89,12 @@ Legend:
|
||||
- [ ] Hard
|
||||
- [ ] System Calls
|
||||
- [x] Sleep()
|
||||
- [x] Print() - Temporary for printing before we get Write(stdout) :)
|
||||
- [ ] Write()
|
||||
- [ ] Read()
|
||||
- [ ] Write() (temporarly puts())
|
||||
- [ ] Read() (temporarly gets())
|
||||
- [ ] Open()
|
||||
- [ ] Close()
|
||||
- [ ] Malloc()
|
||||
- [ ] Free()
|
||||
- [x] Malloc()
|
||||
- [x] Free()
|
||||
- [ ] Seek()
|
||||
- [ ] Shell
|
||||
- [ ] Separate file/program
|
||||
@@ -126,10 +125,13 @@ Legend:
|
||||
- [x] Loading them
|
||||
- [x] Running them
|
||||
- [x] Exit back to kernel/shell
|
||||
- [ ] Let them use libs
|
||||
- [x] Let them use libs
|
||||
- [ ] Proper include files (LibC?)
|
||||
- [ ] argc, argv[]
|
||||
- [ ] Standalone shell program
|
||||
- [ ] Userspace programs
|
||||
- [ ] Calculator
|
||||
- [ ] Caledar
|
||||
- [ ] Code Editor
|
||||
- [ ] Text editor
|
||||
- [ ] Syntax highlighting
|
||||
@@ -145,4 +147,5 @@ Legend:
|
||||
- [ ] Games
|
||||
- [ ] Minesweeper
|
||||
- [ ] Solitaire
|
||||
- [ ] Tetris
|
||||
|
||||
|
||||
Reference in New Issue
Block a user