Fixes nasty memory leaks. Adds memory tracing. Adds serial console for advanced debugging. Implements malloc correctly.
This commit is contained in:
parent
5002d8728c
commit
e69a342b29
18 changed files with 516 additions and 117 deletions
2
Depfile
2
Depfile
|
@ -36,4 +36,4 @@ obj/main.o: scripts/main.ts
|
|||
|
||||
.PHONY: run
|
||||
run:
|
||||
qemu-system-i386 -kernel kernel kernel
|
||||
qemu-system-i386 -serial stdio -kernel kernel
|
||||
|
|
70
Makefile
70
Makefile
|
@ -11,9 +11,9 @@ YACC = bison
|
|||
|
||||
# File Lists
|
||||
SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S
|
||||
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/stdlib.c src/timer.c src/vmm.c
|
||||
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/serial.c src/stdlib.c src/timer.c src/vmm.c
|
||||
SRCS_CXX = trainscript/tsvm.cpp src/cplusplus.cpp src/vm.cpp obj/trainscript.yy.cpp obj/trainscript.tab.cpp
|
||||
OBJS = obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
OBJS = obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
|
||||
# Flags
|
||||
FLAGS = -m32 -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx
|
||||
|
@ -27,40 +27,47 @@ all: kernel
|
|||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
$(RM) obj/trainscript.yy.cpp obj/trainscript.tab.cpp obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
|
||||
kernel: obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
kernel: obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/tsvm.o obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/trainscript.yy.o obj/trainscript.tab.o obj/main.o
|
||||
|
||||
# src/console.c
|
||||
obj/console.o: src/console.c include/console.h include/stdlib.h \
|
||||
include/varargs.h
|
||||
include/varargs.h include/config.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/console.c
|
||||
|
||||
# src/init.c
|
||||
obj/init.o: src/init.c include/kernel.h include/stdlib.h include/varargs.h \
|
||||
include/console.h include/interrupts.h include/cpustate.h include/pmm.h \
|
||||
include/multiboot.h include/vmm.h include/config.h include/timer.h
|
||||
include/config.h include/console.h include/interrupts.h \
|
||||
include/cpustate.h include/pmm.h include/multiboot.h include/vmm.h \
|
||||
include/timer.h include/serial.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/init.c
|
||||
|
||||
# src/interrupts.c
|
||||
obj/interrupts.o: src/interrupts.c include/interrupts.h include/cpustate.h \
|
||||
include/console.h include/stdlib.h include/varargs.h include/io.h \
|
||||
src/intr_stubs.h
|
||||
include/console.h include/stdlib.h include/varargs.h include/config.h \
|
||||
include/io.h src/intr_stubs.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/interrupts.c
|
||||
|
||||
# src/malloc.c
|
||||
obj/malloc.o: src/malloc.c include/stdlib.h include/varargs.h
|
||||
obj/malloc.o: src/malloc.c include/kernel.h include/stdlib.h \
|
||||
include/varargs.h include/config.h include/console.h include/serial.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/malloc.c
|
||||
|
||||
# src/pmm.c
|
||||
obj/pmm.o: src/pmm.c include/pmm.h include/multiboot.h include/kernel.h \
|
||||
include/stdlib.h include/varargs.h include/console.h
|
||||
include/stdlib.h include/varargs.h include/config.h include/console.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/pmm.c
|
||||
|
||||
# src/serial.c
|
||||
obj/serial.o: src/serial.c include/io.h include/serial.h include/stdlib.h \
|
||||
include/varargs.h include/config.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/serial.c
|
||||
|
||||
# src/stdlib.c
|
||||
obj/stdlib.o: src/stdlib.c include/stdlib.h include/varargs.h \
|
||||
include/kernel.h
|
||||
include/config.h include/kernel.h
|
||||
$(CC) $(FLAGS) $(CCFLAGS) -o $@ -c src/stdlib.c
|
||||
|
||||
# src/timer.c
|
||||
|
@ -76,29 +83,30 @@ obj/vmm.o: src/vmm.c include/config.h include/vmm.h include/pmm.h \
|
|||
|
||||
# trainscript/tsvm.cpp
|
||||
obj/tsvm.o: trainscript/tsvm.cpp include/stdlib.h include/varargs.h \
|
||||
include/console.h trainscript/common.h trainscript/tsvm.hpp \
|
||||
include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \
|
||||
include/ker/dictionary.hpp include/kernel.h include/ker/pair.hpp \
|
||||
trainscript/typeid.hpp trainscript/trainscript.tab.hpp \
|
||||
trainscript/trainscript.l.h include/string.h
|
||||
include/config.h include/console.h trainscript/common.h \
|
||||
trainscript/tsvm.hpp include/ker/string.hpp include/ker/vector.hpp \
|
||||
include/ker/new.hpp include/ker/dictionary.hpp include/kernel.h \
|
||||
include/ker/pair.hpp trainscript/typeid.hpp \
|
||||
trainscript/trainscript.tab.hpp trainscript/trainscript.l.h \
|
||||
include/string.h
|
||||
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c trainscript/tsvm.cpp
|
||||
|
||||
# src/cplusplus.cpp
|
||||
obj/cplusplus.o: src/cplusplus.cpp include/stdlib.h include/varargs.h \
|
||||
include/console.h include/ker/new.hpp
|
||||
include/config.h include/console.h include/ker/new.hpp
|
||||
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/cplusplus.cpp
|
||||
|
||||
# src/vm.cpp
|
||||
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h include/timer.h \
|
||||
include/dynamic.h src/../trainscript/tsvm.hpp include/console.h \
|
||||
include/ker/string.hpp include/ker/vector.hpp include/ker/new.hpp \
|
||||
include/ker/dictionary.hpp include/kernel.h include/ker/pair.hpp \
|
||||
src/../trainscript/typeid.hpp
|
||||
obj/vm.o: src/vm.cpp include/stdlib.h include/varargs.h include/config.h \
|
||||
include/timer.h include/dynamic.h src/../trainscript/tsvm.hpp \
|
||||
include/console.h include/ker/string.hpp include/ker/vector.hpp \
|
||||
include/ker/new.hpp include/ker/dictionary.hpp include/kernel.h \
|
||||
include/ker/pair.hpp src/../trainscript/typeid.hpp
|
||||
$(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
|
||||
|
||||
# obj/trainscript.yy.cpp
|
||||
obj/trainscript.yy.o: obj/trainscript.yy.cpp include/string.h \
|
||||
include/stdlib.h include/varargs.h trainscript/common.h \
|
||||
include/stdlib.h include/varargs.h include/config.h trainscript/common.h \
|
||||
trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
|
||||
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
|
||||
include/kernel.h include/ker/pair.hpp trainscript/typeid.hpp \
|
||||
|
@ -107,11 +115,11 @@ obj/trainscript.yy.o: obj/trainscript.yy.cpp include/string.h \
|
|||
|
||||
# obj/trainscript.tab.cpp
|
||||
obj/trainscript.tab.o: obj/trainscript.tab.cpp include/stdlib.h \
|
||||
include/varargs.h trainscript/common.h trainscript/tsvm.hpp \
|
||||
include/console.h include/ker/string.hpp include/ker/vector.hpp \
|
||||
include/ker/new.hpp include/ker/dictionary.hpp include/kernel.h \
|
||||
include/ker/pair.hpp trainscript/typeid.hpp trainscript/trainscript.l.h \
|
||||
include/string.h
|
||||
include/varargs.h include/config.h trainscript/common.h \
|
||||
trainscript/tsvm.hpp include/console.h include/ker/string.hpp \
|
||||
include/ker/vector.hpp include/ker/new.hpp include/ker/dictionary.hpp \
|
||||
include/kernel.h include/ker/pair.hpp trainscript/typeid.hpp \
|
||||
trainscript/trainscript.l.h include/string.h
|
||||
$(CXX) -iquotetrainscript $(FLAGS) $(CXXFLAGS) -o $@ -c obj/trainscript.tab.cpp
|
||||
|
||||
# asm/dynamic.S
|
||||
|
@ -149,4 +157,4 @@ obj/main.o: scripts/main.ts
|
|||
|
||||
.PHONY: run
|
||||
run:
|
||||
qemu-system-i386 -kernel kernel kernel
|
||||
qemu-system-i386 -serial stdio -kernel kernel
|
||||
|
|
|
@ -15,3 +15,5 @@ Also it leaks memory. A lot of memory.
|
|||
- Adding support for String Type
|
||||
- Implement custom malloc that does what it should
|
||||
|
||||
## Guidlines
|
||||
- Calls to `die` or `die_extra` should follow the following scheme: `ContextName.ErrorName`
|
||||
|
|
|
@ -3,3 +3,11 @@
|
|||
/*
|
||||
#define USE_VIRTUAL_MEMORY_MANAGEMENT
|
||||
//*/
|
||||
|
||||
/*
|
||||
#define USE_VERBOSE_MALLOC
|
||||
//*/
|
||||
|
||||
/*
|
||||
#define USE_VERBOSE_FREE
|
||||
//*/
|
||||
|
|
|
@ -17,6 +17,13 @@ static inline void outb(uint16_t port, uint8_t data)
|
|||
__asm__ volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t port)
|
||||
{
|
||||
uint8_t data;
|
||||
__asm__ volatile ("inb %1, %0" : "=a" (data) : "d" (port));
|
||||
return data;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace ker
|
|||
void copyFrom(const uint8_t *bytes, size_t length)
|
||||
{
|
||||
if(this->mText != nullptr) {
|
||||
free(this->mText);
|
||||
// free(this->mText);
|
||||
}
|
||||
this->mText = (uint8_t*)malloc(length + 1);
|
||||
memcpy(this->mText, bytes, length);
|
||||
|
|
51
include/serial.h
Normal file
51
include/serial.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define SERIAL_IER 1
|
||||
#define SERIAL_IIR 2
|
||||
#define SERIAL_FCR 2
|
||||
#define SERIAL_LCR 3
|
||||
#define SERIAL_MCR 4
|
||||
#define SERIAL_LSR 5
|
||||
#define SERIAL_MSR 6
|
||||
|
||||
#define SERIAL_COM1 0x3F8
|
||||
#define SERIAL_COM2 0x2F8
|
||||
#define SERIAL_COM3 0x3E8
|
||||
#define SERIAL_COM4 0x2E8
|
||||
|
||||
#define SERIAL_PARITY_NONE 0b000
|
||||
#define SERIAL_PARITY_ODD 0b100
|
||||
#define SERIAL_PARITY_EVEN 0b110
|
||||
#define SERIAL_PARITY_HIGH 0b101
|
||||
#define SERIAL_PARITY_LOW 0b111
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void serial_init(uint16_t port, uint32_t baud, uint8_t parity, uint8_t bits);
|
||||
|
||||
int serial_can_read(uint16_t port);
|
||||
|
||||
int serial_can_write(uint16_t port);
|
||||
|
||||
void serial_write(uint16_t port, const uint8_t *data, size_t length);
|
||||
|
||||
void serial_read(uint16_t port, uint8_t *data, size_t length);
|
||||
|
||||
void serial_printf(uint16_t port, const char *format, ...);
|
||||
|
||||
static inline void serial_write_str(uint16_t port, const char *text)
|
||||
{
|
||||
while(*text) {
|
||||
serial_write(port, (uint8_t*)text, 1);
|
||||
text++;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
|
@ -3,6 +3,7 @@
|
|||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
#include "varargs.h"
|
||||
#include "config.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
|
@ -12,6 +13,14 @@ char *itoa(int value, char *str, int base);
|
|||
int atoi(const char *str);
|
||||
float atof(const char *str);
|
||||
|
||||
#if defined(USE_VERBOSE_MALLOC)
|
||||
void *malloc_d(size_t,const char *,int);
|
||||
#endif
|
||||
|
||||
#if defined(USE_VERBOSE_FREE)
|
||||
void free_d(void *,const char*, int);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Allocates a block of memory
|
||||
* @param size Minimum size of the memory block
|
||||
|
@ -132,6 +141,20 @@ static inline char * strdup(const char *str)
|
|||
return n;
|
||||
}
|
||||
|
||||
int sprintf(char *target, const char *format, ...);
|
||||
|
||||
int vsprintf(char *target, const char *format, va_list vl);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(USE_VERBOSE_MALLOC)
|
||||
#define malloc(size) malloc_d((size), __FILE__, __LINE__)
|
||||
#endif
|
||||
|
||||
#if defined(USE_VERBOSE_FREE)
|
||||
#define free(ptr) free_d((ptr), __FILE__, __LINE__)
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@ BEGIN
|
|||
0 -> i;
|
||||
WHILE ((i + 1) -> i) <= 50 DO
|
||||
BEGIN
|
||||
printInt(i);
|
||||
print2Int(50 - i, i);
|
||||
sleep(2);
|
||||
END
|
||||
END
|
||||
|
|
|
@ -188,50 +188,12 @@ void kputs(const char *str)
|
|||
|
||||
void kprintf(const char *format, ...)
|
||||
{
|
||||
char buffer[32];
|
||||
static char buffer[1024];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
while(*format != 0)
|
||||
{
|
||||
char c = *(format++);
|
||||
if(c == '%')
|
||||
{
|
||||
c = *(format++);
|
||||
int i;
|
||||
char *str;
|
||||
switch(c)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
i = va_arg(vl, int);
|
||||
kputs(itoa(i, buffer, 10));
|
||||
break;
|
||||
case 'b':
|
||||
i = va_arg(vl, int);
|
||||
kputs(itoa(i, buffer, 2));
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
i = va_arg(vl, int);
|
||||
kputs(itoa(i, buffer, 16));
|
||||
break;
|
||||
case 'c':
|
||||
c = va_arg(vl, int);
|
||||
kputc(c);
|
||||
break;
|
||||
case 's':
|
||||
str = va_arg(vl, char*);
|
||||
kputs(str);
|
||||
break;
|
||||
default:
|
||||
kputc(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kputc(c);
|
||||
}
|
||||
}
|
||||
vsprintf(buffer, format, vl);
|
||||
va_end(vl);
|
||||
kputs(buffer);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <vmm.h>
|
||||
#include <timer.h>
|
||||
#include <config.h>
|
||||
#include <serial.h>
|
||||
|
||||
void die(const char *msg)
|
||||
{
|
||||
|
@ -160,6 +161,9 @@ void init(const MultibootStructure *mbHeader)
|
|||
kclear();
|
||||
kputs("Welcome to \x12\x05trainOS\x12\x07!\n");
|
||||
|
||||
serial_init(SERIAL_COM1, 9600, SERIAL_PARITY_NONE, 8);
|
||||
serial_write_str(SERIAL_COM1, "Debug Console Ready\n");
|
||||
|
||||
//dumpMB(mbHeader);
|
||||
|
||||
kputs("Initialize physical memory management: ");
|
||||
|
|
185
src/malloc.c
185
src/malloc.c
|
@ -1,37 +1,194 @@
|
|||
#include <kernel.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <console.h>
|
||||
#include <serial.h>
|
||||
|
||||
#undef malloc
|
||||
#undef free
|
||||
|
||||
typedef struct List
|
||||
{
|
||||
size_t magic;
|
||||
size_t length;
|
||||
size_t used;
|
||||
struct List *next;
|
||||
} List;
|
||||
|
||||
size_t mallocCount = 0, freeCount = 0;
|
||||
size_t allocatedMemory = 0;
|
||||
|
||||
static const size_t minimumAllocSize = 2 * sizeof(List);
|
||||
static char * const malloc_heap_start = (char *)0x400000;
|
||||
static char * const malloc_heap_end = (char *)0x800000;
|
||||
static char * const malloc_heap_end = (char *)0x10000000;
|
||||
|
||||
static char * current = nullptr;
|
||||
List *listBegin = nullptr;
|
||||
|
||||
static void print_list()
|
||||
{
|
||||
List *list = listBegin;
|
||||
serial_printf(SERIAL_COM1, "malloc list: \n");
|
||||
while(list != nullptr)
|
||||
{
|
||||
if(list->magic != 0xDEADBEEF) {
|
||||
die("malloc::print_list.InvalidMagicNumber");
|
||||
}
|
||||
serial_printf(SERIAL_COM1, "[%x -> %x] %d %d\n", list, list->next, list->used, list->length);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void defragment()
|
||||
{
|
||||
List *list = listBegin;
|
||||
if(list == nullptr) {
|
||||
return;
|
||||
}
|
||||
for(; list->next != nullptr; list = list->next)
|
||||
{
|
||||
if(list->used != 0) {
|
||||
continue;
|
||||
}
|
||||
while(list->next->used == 0) {
|
||||
List *n = list->next->next;
|
||||
list->length += list->next->length + sizeof(List);
|
||||
list->next = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *malloc(size_t len)
|
||||
{
|
||||
// Prevent fragmentation, sacrifice memory
|
||||
if(len < minimumAllocSize) {
|
||||
len = minimumAllocSize;
|
||||
}
|
||||
|
||||
if(listBegin == nullptr) {
|
||||
listBegin = (List*)malloc_heap_start;
|
||||
listBegin->length = (intptr_t)malloc_heap_end - (intptr_t)malloc_heap_start - sizeof(List);
|
||||
listBegin->used = 0;
|
||||
listBegin->next = nullptr;
|
||||
listBegin->magic = 0xDEADBEEF;
|
||||
|
||||
print_list();
|
||||
}
|
||||
|
||||
List *cursor = listBegin;
|
||||
|
||||
// Find the first non-used List entry
|
||||
while((cursor != nullptr) && ((cursor->used != 0) || (cursor->length < (len + sizeof(List))))) {
|
||||
cursor = cursor->next;
|
||||
}
|
||||
if(cursor == nullptr) {
|
||||
print_list();
|
||||
die_extra("malloc.OutOfMemory", itoa(len, nullptr, 10));
|
||||
}
|
||||
|
||||
if(cursor->length < (sizeof(List) + len)) {
|
||||
die("malloc.FragmentationFailure");
|
||||
}
|
||||
|
||||
if(cursor->length == len)
|
||||
{
|
||||
cursor->used = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Store total length
|
||||
size_t newLength = cursor->length - sizeof(List) - len;
|
||||
|
||||
// Allocate the memory
|
||||
cursor->used = 1;
|
||||
cursor->length = len;
|
||||
|
||||
// Fragment list
|
||||
List *newl = (List*)((char*)cursor + (sizeof(List) + cursor->length));
|
||||
newl->length = newLength;
|
||||
newl->used = 0;
|
||||
newl->next = cursor->next;
|
||||
newl->magic = 0xDEADBEEF;
|
||||
|
||||
cursor->next = newl;
|
||||
}
|
||||
|
||||
allocatedMemory += len;
|
||||
mallocCount++;
|
||||
|
||||
if(current == nullptr) {
|
||||
current = malloc_heap_start;
|
||||
return (void*)((char*)cursor + sizeof(List));
|
||||
}
|
||||
|
||||
void *ptr = current;
|
||||
current += len;
|
||||
|
||||
if((uintptr_t)current >= (uintptr_t)malloc_heap_end) {
|
||||
die("malloc.OutOfMemory");
|
||||
void* realloc (void* ptr, size_t size)
|
||||
{
|
||||
void *n = malloc(size);
|
||||
memcpy(n, ptr, size);
|
||||
free(ptr);
|
||||
return n;
|
||||
}
|
||||
|
||||
void free(void *ptr)
|
||||
{
|
||||
if(ptr == nullptr) {
|
||||
// Valid behaviour!
|
||||
return;
|
||||
}
|
||||
if((uintptr_t)ptr < (uintptr_t)malloc_heap_start) {
|
||||
die_extra("free.InvalidFree", itoa(ptr, nullptr, 16));
|
||||
}
|
||||
freeCount++;
|
||||
|
||||
List *entry = (List*)((char*)ptr - sizeof(List));
|
||||
if(entry->used == 0) {
|
||||
die_extra("free.InvalidBlock", itoa(ptr, nullptr, 16));
|
||||
}
|
||||
if(entry->magic != 0xDEADBEEF) {
|
||||
die_extra("free.InvalidBlockMagic: ", itoa(entry->magic, nullptr, 16));
|
||||
}
|
||||
|
||||
if(entry->length > 0x5000) {
|
||||
die_extra("free.InvalidSizedBlock: ", itoa(entry->length, nullptr, 10));
|
||||
}
|
||||
|
||||
allocatedMemory -= entry->length;
|
||||
entry->used = 0;
|
||||
|
||||
defragment();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void *malloc_d(size_t len, const char *file, int line)
|
||||
{
|
||||
serial_write_str(SERIAL_COM1, "Allocate ");
|
||||
serial_write_str(SERIAL_COM1, itoa(len, nullptr, 10));
|
||||
serial_write_str(SERIAL_COM1, " bytes at ");
|
||||
serial_write_str(SERIAL_COM1, file);
|
||||
serial_write_str(SERIAL_COM1, ":");
|
||||
serial_write_str(SERIAL_COM1, itoa(line, nullptr, 10));
|
||||
serial_write_str(SERIAL_COM1, ": ");
|
||||
|
||||
void *ptr = malloc(len);
|
||||
serial_write_str(SERIAL_COM1, itoa(ptr, nullptr, 16));
|
||||
serial_write_str(SERIAL_COM1, "\n");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void free(void *__ptr)
|
||||
void free_d(void *ptr, const char *file, int line)
|
||||
{
|
||||
freeCount++;
|
||||
if(ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
List *entry = (List*)((char*)ptr - sizeof(List));
|
||||
|
||||
serial_write_str(SERIAL_COM1, "Free ");
|
||||
serial_write_str(SERIAL_COM1, itoa(entry->length, nullptr, 10));
|
||||
serial_write_str(SERIAL_COM1, " bytes at ");
|
||||
serial_write_str(SERIAL_COM1, itoa(ptr, nullptr, 16));
|
||||
serial_write_str(SERIAL_COM1, " in ");
|
||||
serial_write_str(SERIAL_COM1, file);
|
||||
serial_write_str(SERIAL_COM1, ":");
|
||||
serial_write_str(SERIAL_COM1, itoa(line, nullptr, 10));
|
||||
serial_write_str(SERIAL_COM1, ".\n");
|
||||
free(ptr);
|
||||
}
|
||||
|
|
85
src/serial.c
Normal file
85
src/serial.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include <io.h>
|
||||
#include <serial.h>
|
||||
#include <stdlib.h>
|
||||
#include <varargs.h>
|
||||
|
||||
// Funktion zum initialisieren eines COM-Ports
|
||||
void serial_init(uint16_t base, uint32_t baud, uint8_t parity, uint8_t bits)
|
||||
{
|
||||
// Teiler berechnen
|
||||
union {
|
||||
uint8_t b[2];
|
||||
uint16_t w;
|
||||
} divisor;
|
||||
divisor.w = 115200/baud;
|
||||
|
||||
// Interrupt ausschalten
|
||||
outb(base+SERIAL_IER,0x00);
|
||||
|
||||
// DLAB-Bit setzen
|
||||
outb(base+SERIAL_LCR,0x80);
|
||||
|
||||
// Teiler (low) setzen
|
||||
outb(base+0,divisor.b[0]);
|
||||
|
||||
// Teiler (high) setzen
|
||||
outb(base+1,divisor.b[1]);
|
||||
|
||||
// Anzahl Bits, Parität, usw setzen (DLAB zurücksetzen)
|
||||
outb(base+SERIAL_LCR,((parity&0x7)<<3)|((bits-5)&0x3));
|
||||
|
||||
// Initialisierung abschließen
|
||||
outb(base+SERIAL_FCR,0xC7);
|
||||
outb(base+SERIAL_MCR,0x0B);
|
||||
}
|
||||
|
||||
int serial_can_write(uint16_t base)
|
||||
{
|
||||
return inb(base+SERIAL_LSR)&0x20;
|
||||
}
|
||||
|
||||
// Byte senden
|
||||
void write_com(uint16_t base, uint8_t chr) {
|
||||
while (serial_can_write(base)==0);
|
||||
outb(base,chr);
|
||||
}
|
||||
|
||||
void serial_write(uint16_t port, const uint8_t *data, size_t length)
|
||||
{
|
||||
while(length--) {
|
||||
write_com(port, *data++);
|
||||
}
|
||||
}
|
||||
|
||||
// Prüft, ob man bereits lesen kann
|
||||
int serial_can_read(uint16_t base)
|
||||
{
|
||||
return inb(base+SERIAL_LSR)&1;
|
||||
}
|
||||
|
||||
// Byte empfangen
|
||||
static uint8_t read_serial(uint16_t base)
|
||||
{
|
||||
while (!serial_can_read(base));
|
||||
return inb(base);
|
||||
}
|
||||
|
||||
void serial_read(uint16_t port, uint8_t *data, size_t length)
|
||||
{
|
||||
while(length--) {
|
||||
*data++ = read_serial(port);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_printf(uint16_t port, const char *format, ...)
|
||||
{
|
||||
static char buffer[1024];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
vsprintf(buffer, format, vl);
|
||||
va_end(vl);
|
||||
|
||||
serial_write_str(port, buffer);
|
||||
}
|
101
src/stdlib.c
101
src/stdlib.c
|
@ -1,14 +1,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <kernel.h>
|
||||
|
||||
void* realloc (void* ptr, size_t size)
|
||||
{
|
||||
void *n = malloc(size);
|
||||
memcpy(n, ptr, size);
|
||||
free(ptr);
|
||||
return n;
|
||||
}
|
||||
|
||||
void exit(int errorCode)
|
||||
{
|
||||
static char buffer[128];
|
||||
|
@ -38,6 +30,11 @@ char *itoa(int num, char *str, int base)
|
|||
int i = 0;
|
||||
int isNegative = 0;
|
||||
|
||||
if(str == nullptr) {
|
||||
static char tmp[64];
|
||||
str = tmp;
|
||||
}
|
||||
|
||||
/* Handle 0 explicitely, otherwise empty string is printed for 0 */
|
||||
if (num == 0)
|
||||
{
|
||||
|
@ -102,3 +99,91 @@ void *memmove( void *destination, const void *source, size_t num)
|
|||
// TODO: Implement memmove
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int sprintf(char *target, const char *format, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
int len = vsprintf(target, format, vl);
|
||||
va_end(vl);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int vsprintf(char *target, const char *format, va_list vl)
|
||||
{
|
||||
int length = 0;
|
||||
char buffer[32];
|
||||
while(*format != 0)
|
||||
{
|
||||
char c = *(format++);
|
||||
if(c == '%')
|
||||
{
|
||||
c = *(format++);
|
||||
int i;
|
||||
char *tmp;
|
||||
size_t len;
|
||||
switch(c)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
i = va_arg(vl, int);
|
||||
tmp = itoa(i, buffer, 10);
|
||||
len = strlen(tmp);
|
||||
if(target != nullptr) {
|
||||
strcat(target, tmp);
|
||||
target += len;
|
||||
}
|
||||
length += len;
|
||||
break;
|
||||
case 'b':
|
||||
i = va_arg(vl, int);
|
||||
tmp = itoa(i, buffer, 2);
|
||||
len = strlen(tmp);
|
||||
if(target != nullptr) {
|
||||
strcat(target, tmp);
|
||||
target += len;
|
||||
}
|
||||
length += len;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
i = va_arg(vl, int);
|
||||
tmp = itoa(i, buffer, 16);
|
||||
len = strlen(tmp);
|
||||
if(target != nullptr) {
|
||||
strcat(target, tmp);
|
||||
target += len;
|
||||
}
|
||||
length += len;
|
||||
break;
|
||||
case 's':
|
||||
tmp = va_arg(vl, char*);
|
||||
len = strlen(tmp);
|
||||
if(target != nullptr) {
|
||||
strcat(target, tmp);
|
||||
target += len;
|
||||
}
|
||||
length += len;
|
||||
break;
|
||||
case 'c':
|
||||
c = va_arg(vl, int);
|
||||
default:
|
||||
if(target != nullptr) {
|
||||
*target++ = c;
|
||||
}
|
||||
length += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(target != nullptr) *target++ = c;
|
||||
length += 1;
|
||||
}
|
||||
}
|
||||
if(target != nullptr) {
|
||||
target[length] = 0;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
|
20
src/vm.cpp
20
src/vm.cpp
|
@ -93,24 +93,25 @@ Variable NativeMethod::invoke(Vector<Variable> arguments)
|
|||
}
|
||||
|
||||
uint8_t *stack = (uint8_t*)malloc(stackSize);
|
||||
uint8_t *stackPtr = stack;
|
||||
for(int i = arguments.length() - 1; i >= 0; i--) {
|
||||
switch(arguments[i].type.id) {
|
||||
case TypeID::Bool:
|
||||
*reinterpret_cast<Int*>(stack) = arguments[i].boolean ? 1 : 0;
|
||||
stack += sizeof(Int);
|
||||
*reinterpret_cast<Int*>(stackPtr) = arguments[i].boolean ? 1 : 0;
|
||||
stackPtr += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Int:
|
||||
*reinterpret_cast<Int*>(stack) = arguments[i].integer;
|
||||
stack += sizeof(Int);
|
||||
*reinterpret_cast<Int*>(stackPtr) = arguments[i].integer;
|
||||
stackPtr += sizeof(Int);
|
||||
break;
|
||||
case TypeID::Real:
|
||||
*reinterpret_cast<Real*>(stack) = arguments[i].real;
|
||||
stack += sizeof(Real);
|
||||
*reinterpret_cast<Real*>(stackPtr) = arguments[i].real;
|
||||
stackPtr += sizeof(Real);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dynamic_call(this->function, stack-stackSize, stackSize);
|
||||
dynamic_call(this->function, stack, stackSize);
|
||||
|
||||
free(stack);
|
||||
|
||||
|
@ -121,6 +122,10 @@ extern "C" void __cdecl printInt(int i) {
|
|||
kprintf("{%d}\n", i);
|
||||
}
|
||||
|
||||
extern "C" void __cdecl print2Int(int a, int b) {
|
||||
kprintf("{%d;%d}\n", a, b);
|
||||
}
|
||||
|
||||
struct NativeModuleDef
|
||||
{
|
||||
const char *name;
|
||||
|
@ -133,6 +138,7 @@ NativeModuleDef methods[] = {
|
|||
{ "timer_get", "", (void*)timer_get },
|
||||
{ "timer_set", "i", (void*)timer_set },
|
||||
{ "printInt", "i", (void*)printInt },
|
||||
{ "print2Int", "ii", (void*)print2Int },
|
||||
{ nullptr, nullptr, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ SOURCES += \
|
|||
trainscript/main.cpp \
|
||||
src/timer.c \
|
||||
src/cplusplus.cpp \
|
||||
src/vm.cpp
|
||||
src/vm.cpp \
|
||||
src/serial.c
|
||||
|
||||
HEADERS += \
|
||||
include/console.h \
|
||||
|
@ -40,7 +41,8 @@ HEADERS += \
|
|||
include/string.h \
|
||||
include/ker/new.hpp \
|
||||
include/dynamic.h \
|
||||
include/config.h
|
||||
include/config.h \
|
||||
include/serial.h
|
||||
|
||||
DISTFILES += \
|
||||
asm/intr_common_handler.S \
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
extern "C" {
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
}
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
@ -41,21 +39,22 @@ namespace trainscript
|
|||
|
||||
Module *VM::load(const void *buffer, size_t length)
|
||||
{
|
||||
void *internalStorage = malloc(length);
|
||||
char *internalStorage = (char*)malloc(length);
|
||||
memcpy(internalStorage, buffer, length);
|
||||
|
||||
Module *module = new Module();
|
||||
|
||||
ParserData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.buffer = reinterpret_cast<char*>(internalStorage);
|
||||
data.index = 0;
|
||||
data.length = length;
|
||||
data.module = module;
|
||||
|
||||
yylex_init_extra(&data, &data.scanner);
|
||||
|
||||
bool valid = yyparse(&data) == 0;
|
||||
|
||||
yylex_destroy(data.scanner);
|
||||
|
||||
free(internalStorage);
|
||||
|
||||
for(size_t i = 0; i < 256; i++) {
|
||||
|
|
Loading…
Reference in a new issue