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
|
#ifndef SYSCALL_H
|
||||||
#define SYSCALL_H
|
#define SYSCALL_H
|
||||||
|
|
||||||
|
#include <interrupt/idt.h>
|
||||||
#include <interrupt/pit.h>
|
#include <interrupt/pit.h>
|
||||||
#include <screen/text.h>
|
#include <screen/text.h>
|
||||||
#include <keyboard/keyboard.h>
|
#include <keyboard/keyboard.h>
|
||||||
|
#include <memory/malloc.h>
|
||||||
|
|
||||||
// System call count
|
// System call count
|
||||||
#define MAX_SYSCALLS 3
|
#define MAX_SYSCALLS 5
|
||||||
|
|
||||||
// Args: ebx - number of miliseconds
|
// Args: ebx - number of miliseconds
|
||||||
void sys_sleep() {
|
void sys_sleep() {
|
||||||
@@ -35,22 +37,48 @@ void sys_gets() {
|
|||||||
read(s);
|
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
|
// System call table
|
||||||
void* syscalls[MAX_SYSCALLS] = {
|
void* syscalls[MAX_SYSCALLS] = {
|
||||||
sys_sleep, // Syscall(0)
|
sys_sleep, // Syscall(0)
|
||||||
sys_puts, // Syscall(1)
|
sys_puts, // Syscall(1)
|
||||||
sys_gets, // Syscall(2)
|
sys_gets, // Syscall(2)
|
||||||
|
sys_malloc, // Syscall(3)
|
||||||
|
sys_free, // Syscall(4)
|
||||||
};
|
};
|
||||||
|
|
||||||
// int 0x80 - Syscall interrupt, handled by this function
|
// int 0x80 - Syscall interrupt, handled by this function
|
||||||
// eax : Syscall number
|
// eax : Syscall number
|
||||||
__attribute__ ((naked)) // No prologue or epilogue, just assembly
|
__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
|
// 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
|
// We should also push these regs: ax, gs, fs, es, ds, bp, di, si, dx, cx, bx
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
".intel_syntax noprefix\n" // We use intel syntax
|
".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
|
// Check if syscall exists
|
||||||
"cmp eax, MAX_SYSCALLS - 1\n"
|
"cmp eax, MAX_SYSCALLS - 1\n"
|
||||||
@@ -86,6 +114,7 @@ void syscallHandler(void) {
|
|||||||
|
|
||||||
// TODO: Send an error or something here
|
// TODO: Send an error or something here
|
||||||
"invalidSyscall:\n"
|
"invalidSyscall:\n"
|
||||||
|
"mov eax, -1\n" // Current error thing
|
||||||
"iretd\n"
|
"iretd\n"
|
||||||
|
|
||||||
".att_syntax" // Switch back to Att Syntax (Just in case)
|
".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>
|
#include <stdio.h>
|
||||||
|
|
||||||
__attribute__ ((section ("entry")))
|
|
||||||
void main() {
|
void main() {
|
||||||
char msg[8] = { 'H','e','l','l','o','!','\n',0 };
|
char msg[8] = { 'H','e','l','l','o','!','\n',0 };
|
||||||
print(msg);
|
print(msg);
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
|
ENTRY("main");
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
.text : {
|
.text : {
|
||||||
*(entry);
|
|
||||||
*(.text*);
|
*(.text*);
|
||||||
}
|
}
|
||||||
.data : {
|
.data : {
|
||||||
@@ -13,3 +13,4 @@ SECTIONS {
|
|||||||
*(.bss*);
|
*(.bss*);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-1
@@ -16,6 +16,7 @@
|
|||||||
#include <sound/notes.h>
|
#include <sound/notes.h>
|
||||||
#include <memory/virtual.h>
|
#include <memory/virtual.h>
|
||||||
#include <memory/addresses.h>
|
#include <memory/addresses.h>
|
||||||
|
#include <memory/malloc.h>
|
||||||
|
|
||||||
#define PROMPT "#> "
|
#define PROMPT "#> "
|
||||||
|
|
||||||
@@ -303,8 +304,29 @@ void main() {
|
|||||||
|
|
||||||
diskRead(sector, size, entryPoint);
|
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
|
((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) {
|
} else if (strcmp(fileType, "tab") == 0) {
|
||||||
printFiletable(entryPoint);
|
printFiletable(entryPoint);
|
||||||
} else if (strcmp(fileType, "fnt") == 0) {
|
} else if (strcmp(fileType, "fnt") == 0) {
|
||||||
|
|||||||
@@ -89,13 +89,12 @@ Legend:
|
|||||||
- [ ] Hard
|
- [ ] Hard
|
||||||
- [ ] System Calls
|
- [ ] System Calls
|
||||||
- [x] Sleep()
|
- [x] Sleep()
|
||||||
- [x] Print() - Temporary for printing before we get Write(stdout) :)
|
- [ ] Write() (temporarly puts())
|
||||||
- [ ] Write()
|
- [ ] Read() (temporarly gets())
|
||||||
- [ ] Read()
|
|
||||||
- [ ] Open()
|
- [ ] Open()
|
||||||
- [ ] Close()
|
- [ ] Close()
|
||||||
- [ ] Malloc()
|
- [x] Malloc()
|
||||||
- [ ] Free()
|
- [x] Free()
|
||||||
- [ ] Seek()
|
- [ ] Seek()
|
||||||
- [ ] Shell
|
- [ ] Shell
|
||||||
- [ ] Separate file/program
|
- [ ] Separate file/program
|
||||||
@@ -126,10 +125,13 @@ Legend:
|
|||||||
- [x] Loading them
|
- [x] Loading them
|
||||||
- [x] Running them
|
- [x] Running them
|
||||||
- [x] Exit back to kernel/shell
|
- [x] Exit back to kernel/shell
|
||||||
- [ ] Let them use libs
|
- [x] Let them use libs
|
||||||
- [ ] Proper include files (LibC?)
|
- [ ] Proper include files (LibC?)
|
||||||
- [ ] argc, argv[]
|
- [ ] argc, argv[]
|
||||||
- [ ] Standalone shell program
|
- [ ] Standalone shell program
|
||||||
|
- [ ] Userspace programs
|
||||||
|
- [ ] Calculator
|
||||||
|
- [ ] Caledar
|
||||||
- [ ] Code Editor
|
- [ ] Code Editor
|
||||||
- [ ] Text editor
|
- [ ] Text editor
|
||||||
- [ ] Syntax highlighting
|
- [ ] Syntax highlighting
|
||||||
@@ -145,4 +147,5 @@ Legend:
|
|||||||
- [ ] Games
|
- [ ] Games
|
||||||
- [ ] Minesweeper
|
- [ ] Minesweeper
|
||||||
- [ ] Solitaire
|
- [ ] Solitaire
|
||||||
|
- [ ] Tetris
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user