Made malloc() and free()! They're in header stdlib.h as syscalls 3 & 4.

This commit is contained in:
2024-05-24 18:08:33 +02:00
parent f009bbdac9
commit f879ca122f
7 changed files with 211 additions and 15 deletions
+18
View File
@@ -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
+35 -6
View File
@@ -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)
+124
View File
@@ -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
View File
@@ -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
View File
@@ -1,6 +1,6 @@
ENTRY("main");
SECTIONS {
.text : {
*(entry);
*(.text*);
}
.data : {
@@ -13,3 +13,4 @@ SECTIONS {
*(.bss*);
}
}
+23 -1
View File
@@ -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) {
+9 -6
View File
@@ -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