From 43d0bb8e3997022e5270f7f75f615a47819c929e Mon Sep 17 00:00:00 2001 From: Alex AUVOLAT Date: Tue, 1 May 2012 23:48:56 +0200 Subject: Basic object system - THIS IS STILL A LONG WAY TO GO!! --- src/kernel/Makefile | 3 +- src/kernel/Object/Folder_if.c | 8 ++ src/kernel/Object/Folder_if.h | 15 +++ src/kernel/Object/Object.c | 188 +++++++++++++++++++++++++++++++++++ src/kernel/Object/Object.h | 78 +++++++++++++++ src/kernel/Object/VirtualFolder_cl.c | 96 ++++++++++++++++++ src/kernel/Object/VirtualFolder_cl.h | 30 ++++++ src/kernel/core/kmain.c | 19 ++-- src/kernel/core/monitor.h | 3 +- src/kernel/lib/earray.c | 156 +++++++++++++++++++++++++++++ src/kernel/lib/earray.h | 40 ++++++++ src/kernel/lib/std.c | 8 ++ src/kernel/lib/std.h | 2 + src/kernel/linker/elf.c | 2 +- src/kernel/mem/paging.c | 13 ++- src/kernel/task/idt.c | 12 +-- src/kernel/task/syscall.c | 70 ++++++++++--- src/kernel/task/syscall.h | 2 - src/kernel/task/task.c | 41 ++++---- src/kernel/task/task.h | 4 + 20 files changed, 726 insertions(+), 64 deletions(-) create mode 100644 src/kernel/Object/Folder_if.c create mode 100644 src/kernel/Object/Folder_if.h create mode 100644 src/kernel/Object/Object.c create mode 100644 src/kernel/Object/Object.h create mode 100644 src/kernel/Object/VirtualFolder_cl.c create mode 100644 src/kernel/Object/VirtualFolder_cl.h create mode 100644 src/kernel/lib/earray.c create mode 100644 src/kernel/lib/earray.h (limited to 'src/kernel') diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 6060911..485a02e 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -2,8 +2,9 @@ Out = kernel.elf Obj = core/loader_.o core/kmain.o core/sys.o \ core/monitor.o task/timer.o \ task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o task/sched.o \ - lib/bitset.o lib/std.o \ + lib/bitset.o lib/std.o lib/earray.o \ mem/mem.o mem/paging.o mem/gdt.o mem/_dlmalloc.o mem/seg.o \ + Object/Object.o Object/Folder_if.o Object/VirtualFolder_cl.o \ linker/elf.o ExtObj = $(SrcPath)/common/_common.o diff --git a/src/kernel/Object/Folder_if.c b/src/kernel/Object/Folder_if.c new file mode 100644 index 0000000..81fd6ad --- /dev/null +++ b/src/kernel/Object/Folder_if.c @@ -0,0 +1,8 @@ +#include "Folder_if.h" + +Interface FolderIface = { + "Folder", // name + 2, // method count + 1, // public method count + 0, 0 // internal +}; diff --git a/src/kernel/Object/Folder_if.h b/src/kernel/Object/Folder_if.h new file mode 100644 index 0000000..8f1db11 --- /dev/null +++ b/src/kernel/Object/Folder_if.h @@ -0,0 +1,15 @@ +#ifndef DEF_FOLDER_IF_H +#define DEF_FOLDER_IF_H + +#include "Object.h" +#include + +typedef struct _FolderMethods { + MethodPtr GetChildNameAt; + MethodPtr addChild; +} FolderMethods; + +extern Interface FolderIface; + +#endif + diff --git a/src/kernel/Object/Object.c b/src/kernel/Object/Object.c new file mode 100644 index 0000000..3af8fff --- /dev/null +++ b/src/kernel/Object/Object.c @@ -0,0 +1,188 @@ +#include "Object.h" + +#include "VirtualFolder_cl.h" +#include +#include +#include + +#include + +struct earray numberedMethods; +struct earray interfaces; + +void setup_object_system() { + numberedMethods.ref_vect_init_len = 32; + numberedMethods.vect_len = 256; + numberedMethods.data = 0; + earray_init(&numberedMethods); + + interfaces.ref_vect_init_len = 32; + interfaces.vect_len = 32; + interfaces.data = 0; + earray_init(&interfaces); + + Class_setup(&VirtualFolderClass); + + rootObject = VirtualFolder_new(); + deviceListObject = VirtualFolder_new(); + VirtualFolder_addChild(rootObject, 0, ".dev", deviceListObject, 0, 0); +} + +void Class_setup(Class *_class) { + monitor_write("\n * Setup class '"); + monitor_write(_class->name); + monitor_write("'... "); + + int i; + for (i = 0; _class->interfaces[i].interface != 0; i++) { + Interface_setup(_class->interfaces[i].interface); + } +} + +void Interface_setup(Interface *iface) { + int i; + + monitor_write("\n - Setup interface '"); + monitor_write(iface->name); + monitor_write("' :"); + + if (iface->numberedMethods != 0) return; + + earray_add(&interfaces, iface); + + iface->numberedMethods = kmalloc(iface->method_count * sizeof(NumberedMethod)); + iface->methodNumbers = kmalloc(iface->method_count * sizeof(int)); + + for (i = 0; i < iface->method_count; i++) { + iface->numberedMethods[i].iface = iface; + iface->numberedMethods[i].numberInIface = i; + iface->methodNumbers[i] = earray_add(&numberedMethods, &iface->numberedMethods[i]); + monitor_write(" #"); monitor_writeDec(iface->methodNumbers[i]); + } +} + +MethodPtr *Class_getInterfaceImpl(Class *_class, Interface *iface) { + int i; + for (i = 0; _class->interfaces[i].interface != 0; i++) { + if (_class->interfaces[i].interface == iface) { + return _class->interfaces[i].methods; + } + } + return 0; +} + +Object* Object_get(Object *parent, char *path) { + char* member = path; + Object *object = parent; + + while (*path != 0 && object != 0) { + if (*path == '/') { + if (member == path) { + member++; + path++; + } else { + *path = 0; + if (object->_class->findChild != 0) { + object = object->_class->findChild(object, member); + } else { + object = 0; + } + path++; + member = path; + } + } else { + path++; + } + } + if (object != 0 && member != path) { + if (object->_class->findChild != 0) { + object = object->_class->findChild(object, member); + } else { + object = 0; + } + } + + return object; +} + +// SYSCALLS + +int open(char* name) { + ASSERT(current_process != 0); + + Object *obj = Object_get(rootObject, name); + if (obj == 0) return E_NOT_FOUND; + obj->handles++; + return earray_add(¤t_process->handles, obj); +} + +int open_relative(char* name, int root_handle) { + ASSERT(current_process != 0); + + Object *parent = read_handle(current_process, root_handle); + if (parent == 0) return E_BAD_HANDLE; + Object *obj = Object_get(parent, name); + if (obj == 0) return E_NOT_FOUND; + if (obj->_class->open != 0) { + int r = obj->_class->open(obj, current_process); + if (r != 0) return r; + } + obj->handles++; + return earray_add(¤t_process->handles, obj); +} + +void close(size_t handle) { + ASSERT(current_process != 0); + + Object *obj = read_handle(current_process, handle); + if (obj == 0) return; + obj->handles--; + if (obj->_class->closed != 0) obj->_class->closed(obj); + earray_set(¤t_process->handles, handle, 0); +} + +int get_methods(char* iface_name, int* whereto) { + int i = 0; + Interface *iface = 0, *tmp; + for (i = 0; i < interfaces.elements; i++) { + tmp = earray_at(&interfaces, i); + if (tmp != 0) { + if (strcmp(tmp->name, iface_name) == 0) { + iface = tmp; + break; + } + } + } + if (iface == 0) return E_NOT_FOUND; + for (i = 0; i < iface->public_method_count; i++) { + whereto[i] = iface->methodNumbers[i]; + } + return iface->public_method_count; +} + +Object* read_handle(struct process *proc, size_t handle) { + if (proc == 0) return (Object*)handle; + return earray_at(&proc->handles, handle); +} + +int do_method_call_2(int handle, int method, size_t a, size_t b, size_t c, size_t d) { + ASSERT(current_process != 0) + + Object *obj = read_handle(current_process, handle); + if (obj == 0) return E_BAD_HANDLE; + + NumberedMethod *nm = earray_at(&numberedMethods, method); + if (nm == 0) return E_NOT_IMPLEMENTED; + if (nm->numberInIface >= nm->iface->public_method_count) return E_NOT_PUBLIC; + + MethodPtr* m = Class_getInterfaceImpl(obj->_class, nm->iface); + if (m == 0) return E_NOT_IMPLEMENTED; + MethodPtr p = m[nm->numberInIface]; + ASSERT(p != 0); + + return p(obj, current_process, a, b, c, d); +} + +void do_method_call(struct registers *regs) { + regs->eax = do_method_call_2(regs->eax, regs->ebx, regs->ecx, regs->edx, regs->esi, regs->edi); +} diff --git a/src/kernel/Object/Object.h b/src/kernel/Object/Object.h new file mode 100644 index 0000000..1b0daec --- /dev/null +++ b/src/kernel/Object/Object.h @@ -0,0 +1,78 @@ +#ifndef DEF_INTERFACE_H +#define DEF_INTERFACE_H + +#include +#include + +#include + +struct _Object; +struct _NumberedMethod; + +typedef struct _Interface { + char* name; + int method_count; + int public_method_count; + + struct _NumberedMethod *numberedMethods; + int *methodNumbers; +} Interface; + +typedef struct _NumberedMethod { + Interface *iface; + int numberInIface; +} NumberedMethod; + +typedef int (*MethodPtr)(struct _Object* object, struct process* process, size_t a, size_t b, size_t c, size_t d); +typedef struct _Object* (*FindChildPtr)(struct _Object *object, const char* name); +typedef int (*OpenPtr)(struct _Object *object, struct process *process); +typedef void (*ClosedPtr)(struct _Object *object); +typedef void (*DeletePtr)(struct _Object *object); + +typedef struct _InterfaceImpl { + Interface *interface; + MethodPtr *methods; +} InterfaceImpl; + +// == + +typedef struct _Class { + char *name; + FindChildPtr findChild; + OpenPtr open; // optionnal - if 0, always success + ClosedPtr closed; // optionnal + DeletePtr deleted; // optionnal but should be implemented + InterfaceImpl interfaces[]; // zero-terminated list +} Class; + +typedef struct _Object { + Class *_class; + void *data; + int handles; // reference counter +} Object; + +// + +void setup_object_system(); + +void Class_setup(Class* _class); +void Interface_setup(Interface* iface); + +MethodPtr* Class_getInterfaceImpl(Class *_class, Interface *iface); + +Object* Object_get(Object *parent, char *path); + +Object *rootObject, *deviceListObject; + +// syscalls +int open(char* name); +int open_relative(char* name, int root_handle); +void close(size_t handle); +int get_methods(char* iface_name, int* whereto); + +Object* read_handle(struct process *proc, size_t handle); +void do_method_call(struct registers *regs); + + +#endif + diff --git a/src/kernel/Object/VirtualFolder_cl.c b/src/kernel/Object/VirtualFolder_cl.c new file mode 100644 index 0000000..98641dd --- /dev/null +++ b/src/kernel/Object/VirtualFolder_cl.c @@ -0,0 +1,96 @@ +#include + +#include +#include + +#include "VirtualFolder_cl.h" + +MethodPtr _VirtualFolderMethodsAsFolder[] = { + &VirtualFolder_GetChildNameAt, + &VirtualFolder_addChild, + 0 + }; +Class VirtualFolderClass = { + "VirtualFolder", + VirtualFolder_findChild, 0, 0, VirtualFolder_delete, + { + { &FolderIface, &_VirtualFolderMethodsAsFolder + }, + { 0, { 0 } } + } +}; + +Object *VirtualFolder_new() { + struct _VirtualFolder *f = kmalloc(sizeof(struct _VirtualFolder)); + f->obj.data = f; + f->obj._class = &VirtualFolderClass; + f->obj.handles = 0; + + f->children.ref_vect_init_len = 32; + f->children.vect_len = 64; + f->children.data = 0; + earray_init(&f->children); + + struct _VirtualFolder_child *fc = kmalloc(sizeof(struct _VirtualFolder)); + fc->name = "."; + fc->obj = &f->obj; + + earray_add(&f->children, fc); + f->child_count = 1; + + return &f->obj; +} + +void VirtualFolder_delete(Object *o) { + struct _VirtualFolder *f = o->data; + int i; + for (i = 1; i < f->child_count; i++) { + struct _VirtualFolder_child *child = earray_at(&f->children, i); + if (child->obj->_class->deleted != 0) child->obj->_class->deleted(child->obj); + kfree(child); + } + kfree(earray_at(&f->children, 0)); // self-reference, "." + earray_free(&f->children); + kfree(f); +} + +Object *VirtualFolder_findChild(Object* object, const char* name) { + struct _VirtualFolder *f = object->data; + int i; + for (i = 1; i < f->child_count; i++) { + struct _VirtualFolder_child *child = earray_at(&f->children, i); + if (strcmp(name, child->name) == 0) return child->obj; + } + return 0; +} + + +int VirtualFolder_GetChildNameAt(Object *object, struct process *process, size_t a, size_t b, size_t c, size_t d) { + struct _VirtualFolder *f = object->data; + if (a >= f->child_count) return E_NOT_FOUND; + struct _VirtualFolder_child *child = earray_at(&f->children, a); + strcpy((char*)b, child->name); + return strlen(child->name); +} + +int VirtualFolder_addChild(Object *object, struct process *process, size_t a, size_t b, size_t c, size_t d) { + ASSERT(process == 0); // this is done in kernel land + struct _VirtualFolder *f = object->data; + + if (b == 0) return E_INVALID; + + struct _VirtualFolder_child *fc = kmalloc(sizeof(struct _VirtualFolder)); + fc->name = strdup((char*)a); + fc->obj = (Object*)b; + + if (strlen(fc->name) >= FILENAME_MAX_LEN) { + fc->name[FILENAME_MAX_LEN] = 0; + } + + // THIS SHOULD'NT BE DONE LIKE THIS, IT'S TO CHECK OUR CODE WORKS! + ASSERT(earray_add(&f->children, fc) == f->child_count); + + f->child_count++; + + return 0; +} diff --git a/src/kernel/Object/VirtualFolder_cl.h b/src/kernel/Object/VirtualFolder_cl.h new file mode 100644 index 0000000..fac697d --- /dev/null +++ b/src/kernel/Object/VirtualFolder_cl.h @@ -0,0 +1,30 @@ +#ifndef DEF_VIRTUALFOLDER_CL_H +#define DEF_VIRTUALFOLDER_CL_H + +#include "Folder_if.h" + +#include + +extern Class VirtualFolderClass; + +struct _VirtualFolder { + Object obj; + + int child_count; + struct earray children; +}; + +struct _VirtualFolder_child { + char* name; + Object *obj; +}; + +Object *VirtualFolder_new(); +void VirtualFolder_delete(Object* obj); + +Object* VirtualFolder_findChild(Object* object, const char* name); + +int VirtualFolder_GetChildNameAt(Object *object, struct process* process, size_t a, size_t b, size_t c, size_t d); +int VirtualFolder_addChild(Object *object, struct process* process, size_t a, size_t b, size_t c, size_t d); + +#endif diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c index 8c36b54..3401107 100644 --- a/src/kernel/core/kmain.c +++ b/src/kernel/core/kmain.c @@ -12,6 +12,8 @@ #include #include +#include + /* The kernel's main procedure. This function is called in loader_.asm. This function calls the initializer functions for all system parts. It then loads the modules the kernel was given by the bootloader. @@ -36,12 +38,13 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) { monitor_clear(); + monitor_write(" -> This is "); monitor_write(K_OS_NAME); monitor_write(" version "); monitor_write(K_OS_VER); monitor_write(" codename '"); monitor_write(K_OS_CODENAME); - monitor_write("' starting up :\n"); + monitor_write("', now starting up :\n"); idt_init(); @@ -52,27 +55,27 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) { gdt_init(); paging_cleanup(); - //kheap_init(); timer_init(30); tasking_init(); + + setup_object_system(); - monitor_write("\n\nLoading modules :\n"); for (i = 0; i < mbd->mods_count; i++) { - monitor_write(" * "); + monitor_write("\n * Load multiboot module '"); monitor_write((char*)mods[i].string); if (elf_check((uint8_t*)mods[i].mod_start)) { - monitor_write(" : Invalid ELF file\n"); + monitor_write("' : Invalid ELF file"); } else { struct process *pr = elf_exec((uint8_t*)mods[i].mod_start, PL_USER); if (pr == 0) { - monitor_write(" : Error loading\n"); + monitor_write("' : Error loading"); } else { - monitor_write(" : OK, pid="); monitor_writeDec(pr->pid); monitor_write("\n"); + monitor_write("' : OK, pid="); monitor_writeDec(pr->pid); } } } - monitor_write("Modules now RULE THE WORLD !\n\n"); + monitor_write("\nUserland processes now RULE THE WORLD !\n\n"); sti(); schedule(); PANIC("Should never happen. Something probably went wrong with multitasking."); diff --git a/src/kernel/core/monitor.h b/src/kernel/core/monitor.h index bb8e16e..f7ca453 100644 --- a/src/kernel/core/monitor.h +++ b/src/kernel/core/monitor.h @@ -11,11 +11,12 @@ void monitor_writeDec(uint32_t v); #define NL monitor_put('\n'); #define TAB monitor_put('\t'); +#define WS monitor_put(' '); #define WHERE { monitor_write("(kernel:"); \ monitor_write(__FILE__); \ monitor_write(":"); \ monitor_writeDec(__LINE__); \ - monitor_write(")\t"); } + monitor_write(") "); } #endif diff --git a/src/kernel/lib/earray.c b/src/kernel/lib/earray.c new file mode 100644 index 0000000..a17e823 --- /dev/null +++ b/src/kernel/lib/earray.c @@ -0,0 +1,156 @@ +#include "earray.h" + +#include +#include + +void earray_init(struct earray *array) { + int i; + + if (array->data != 0) return; + + array->ref_vect_len = array->ref_vect_init_len; + array->elements = 0; + array->mutex = MUTEX_UNLOCKED; + + array->data = kmalloc(array->ref_vect_len * sizeof(void***)); + + for (i = 0; i < array->ref_vect_len; i++) { + array->data[i] = 0; + } +} + +void earray_free(struct earray *array) { + int i; + + mutex_lock(&array->mutex); + + for (i = 0; i < array->ref_vect_len; i++) { + if (array->data[i] != 0) kfree(array->data[i]); + } + kfree(array->data); + array->data = 0; + + //no need to unlock, the structure is never to be used again +} + +int earray_add(struct earray *array, void *ptr) { + if (ptr == 0) return -1; + + mutex_lock(&array->mutex); + + int i, j; + + for (i = 0; i < array->ref_vect_len; i++) { + if (array->data[i] == 0) { + // Allocate here + array->data[i] = kmalloc(array->vect_len * sizeof(void**)); + array->data[i][0] = ptr; + for (j = 1; j < array->vect_len; j++) array->data[i][j] = 0; + + j = i * array->vect_len; //ret val + + if (array->elements <= j) array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + } else { + // Look for free space + for (j = 0; j < array->vect_len; j++) { + if (array->data[i][j] == 0) { + array->data[i][j] = ptr; + + j = i * array->vect_len + j; // ret val + if (array->elements <= j) array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + } + } + } + } + // Nothing was allocated, we need MORE SPACE + void ***new_data = kmalloc(array->ref_vect_len + array->ref_vect_init_len); + for (i = 0; i < array->ref_vect_len; i++) { + new_data[i] = array->data[i]; + } + new_data[array->ref_vect_len] = kmalloc(array->vect_len * sizeof(void**)); + new_data[array->ref_vect_len][0] = ptr; + j = array->ref_vect_len * array->vect_len; // j = return value + for (i = 1; i < array->vect_len; i++) { + new_data[array->ref_vect_len][i] = 0; + } + for (i = array->ref_vect_len + 1; i < array->ref_vect_len + array->ref_vect_init_len; i++) { + new_data[i] = 0; + } + kfree(array->data); + array->data = new_data; + array->ref_vect_len += array->ref_vect_init_len; + + ASSERT(j >= array->elements); + array->elements = j + 1; + + mutex_unlock(&array->mutex); + return j; + +} + +void *earray_at(struct earray *array, int num) { + mutex_lock(&array->mutex); + + int i = num / array->vect_len, j = num % array->vect_len; + if (i >= array->ref_vect_len || array->data[i] == 0) return 0; + void* ret = array->data[i][j]; + + mutex_unlock(&array->mutex); + return ret; +} + +void earray_set(struct earray *array, int num, void* ptr) { + mutex_lock(&array->mutex); + + int a = num / array->vect_len, b = num % array->vect_len, i, j; + if (a >= array->ref_vect_len) { + if (ptr == 0) { + mutex_unlock(&array->mutex); + return; + } + int new_vect_len = array->ref_vect_len; + while (a >= array->ref_vect_len) new_vect_len += array->ref_vect_init_len; + + void ***new_data = kmalloc(new_vect_len * sizeof(void***)); + for (i = 0; i < array->ref_vect_len; i++) { + new_data[i] = array->data[i]; + } + for (i = array->ref_vect_len; i < new_vect_len; i++) { + new_data[i] = 0; + } + kfree(array->data); + array->data = new_data; + array->ref_vect_len = new_vect_len; + } + if (ptr == 0) { + if (array->data[a] != 0) { + if (array->data[a][b] != 0) { + array->data[a][b] = 0; + j = 1; + for (i = 0; i < array->vect_len; i++) { + if (array->data[a][i] != 0) j = 0; + } + if (j == 1) { + kfree(array->data[a]); + array->data[a] = 0; + } + } + } + } else { + if (array->data[a] = 0) { + array->data[a] = kmalloc(array->vect_len * sizeof(void**)); + for (i = 0; i < array->vect_len; i++) array->data[a][i] = 0; + } + array->data[a][b] = ptr; + + if (num >= array->elements) array->elements = num + 1; + } + + mutex_unlock(&array->mutex); +} diff --git a/src/kernel/lib/earray.h b/src/kernel/lib/earray.h new file mode 100644 index 0000000..69849c9 --- /dev/null +++ b/src/kernel/lib/earray.h @@ -0,0 +1,40 @@ +#ifndef DEF_EARRAY_H +#define DEF_EARRAY_H + +#include + +/* + * This class implements a simple extensible array structure. + * An entry with a 0 value is considered free and can be allocated. + * The array will free as much space when elements are removed. + * The array will ALWAYS have array->data = 0 when uninitialized, !=0 when initialized and in use + * To initialize an earray: + * - allocate the struct earray + * - set its ref_vect_init_len and vect_len to desired values + * - set its data to 0 + * - all the rest doesn't matter + * - call earray_init + * Freeing an array does not free the struct earray, only the data it references. + */ + +struct earray { + int ref_vect_init_len; + int vect_len; // NEVER CHANGE THIS AFTER INITIALISATION!!!! + + int ref_vect_len; + int elements; + void ***data; + + mutex_t mutex; +}; + +void earray_init(struct earray *array); +void earray_free(struct earray *earray); // frees everything + +int earray_add(struct earray *array, void* ptr); // return element number or -1 if fail +void *earray_at(struct earray *array, int num); // returns 0 when nothing +void earray_set(struct earray *earray, int num, void* ptr); + + +#endif + diff --git a/src/kernel/lib/std.c b/src/kernel/lib/std.c index 316dfa3..85dff1a 100644 --- a/src/kernel/lib/std.c +++ b/src/kernel/lib/std.c @@ -1,5 +1,6 @@ #include "std.h" #include "core/sys.h" +#include int errno = 0; @@ -9,3 +10,10 @@ void abort() { monitor_write("\n"); PANIC("abort() called, probably a memory manager failure."); } + +char *strdup(const char *src) { + char* ret = kmalloc(strlen(src) + 1); + if (ret == NULL) return ret; + strcpy(ret, src); + return ret; +} diff --git a/src/kernel/lib/std.h b/src/kernel/lib/std.h index 51e0435..7aaf1b9 100644 --- a/src/kernel/lib/std.h +++ b/src/kernel/lib/std.h @@ -11,4 +11,6 @@ void abort(); extern int errno; +char *strdup(const char *src); // uses malloc, so needs to be here + #endif diff --git a/src/kernel/linker/elf.c b/src/kernel/linker/elf.c index af6d057..fa8d179 100644 --- a/src/kernel/linker/elf.c +++ b/src/kernel/linker/elf.c @@ -27,7 +27,7 @@ thread_entry elf_load(uint8_t *data, struct process* process) { seg_map(simpleseg_make(phdr[i].p_vaddr, phdr[i].p_memsz, (phdr[i].p_flags & PF_W) != 0), process->pagedir, 0); memcpy((uint8_t*)phdr[i].p_vaddr, data + phdr[i].p_offset, phdr[i].p_filesz); if (phdr[i].p_memsz > phdr[i].p_filesz) { - memset((uint8_t*)phdr[i].p_vaddr + phdr[i].p_memsz, 0, phdr[i].p_memsz - phdr[i].p_filesz); + memset((uint8_t*)phdr[i].p_vaddr + phdr[i].p_filesz, 0, phdr[i].p_memsz - phdr[i].p_filesz); } if (phdr[i].p_vaddr + phdr[i].p_memsz > dataseg) { dataseg = phdr[i].p_vaddr + phdr[i].p_memsz; diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c index 0527f06..8a1e2db 100644 --- a/src/kernel/mem/paging.c +++ b/src/kernel/mem/paging.c @@ -137,14 +137,13 @@ uint32_t paging_fault(struct registers *regs) { } if (seg == 0) { - NL; WHERE; monitor_write("Unhandled Page Fault\t"); + NL; WHERE; monitor_write("Unhandled Page Fault - "); monitor_write("cr2:"); monitor_writeHex(addr); - NL; TAB; - if (regs->err_code & 0x1) monitor_write("present"); TAB; - if (regs->err_code & 0x2) monitor_write("write"); TAB; - if (regs->err_code & 0x4) monitor_write("user"); TAB; - if (regs->err_code & 0x8) monitor_write("rsvd"); TAB; - if (regs->err_code & 0x10) monitor_write("opfetch"); + if (regs->err_code & 0x1) monitor_write(" present"); + if (regs->err_code & 0x2) monitor_write(" write"); + if (regs->err_code & 0x4) monitor_write(" user"); + if (regs->err_code & 0x8) monitor_write(" rsvd"); + if (regs->err_code & 0x10) monitor_write(" opfetch"); return 1; } return 0; diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c index aed5ea8..e6105d5 100644 --- a/src/kernel/task/idt.c +++ b/src/kernel/task/idt.c @@ -76,9 +76,9 @@ static struct irq_waiter { void idt_isrHandler(struct registers regs) { if ((regs.int_no == 14 && paging_fault(®s) != 0) || regs.int_no != 14) { if (tasking_handleException(®s) == 0) { - monitor_write("\nREALLY BAD THIS TIME\t\tUnhandled exception\t#"); + monitor_write("\nREALLY BAD THIS TIME : Unhandled exception #"); monitor_writeDec(regs.int_no); - monitor_write("\t@"); monitor_writeHex(regs.eip); + monitor_write(" @ eip:"); monitor_writeHex(regs.eip); PANIC("Unhandled Exception"); } } @@ -105,14 +105,6 @@ void idt_irqHandler(struct registers regs) { if (doSwitch) schedule(); } -/* Called in idt_.asm on a system call (interrupt 64). - Calls the correct syscall handler (if any). */ -void idt_syscallHandler(struct registers regs) { - if (regs.eax < NUMBER_OF_SYSCALLS && syscalls[regs.eax] != 0) { - syscalls[regs.eax](®s); - } -} - /* For internal use only. Sets up an entry of the IDT with given parameters. */ static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) { idt_entries[num].base_lo = base & 0xFFFF; diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c index bd27eba..8e1005c 100644 --- a/src/kernel/task/syscall.c +++ b/src/kernel/task/syscall.c @@ -2,18 +2,22 @@ #include "task.h" #include +#include + +#define NUMBER_OF_SYSCALLS 32 + #define CALL0(name, scname) static void scname(struct registers* r) { r->eax = name(); } #define CALL1(name, scname) static void scname(struct registers* r) { \ - r->eax = name(r->ebx); } + r->eax = name(r->ecx); } #define CALL2(name, scname) static void scname(struct registers* r) { \ - r->eax = name(r->ebx, r->ecx); } + r->eax = name(r->ecx, r->edx); } #define CALL3(name, scname) static void scname(struct registers* r) { \ - r->eax = name(r->ebx, r->ecx, r->edx); } + r->eax = name(r->ecx, r->edx, r->esi); } #define CALL0V(name, scname) static void scname(struct registers* r) { name(); } -#define CALL1V(name, scname) static void scname(struct registers* r) { name(r->ebx); } -#define CALL2V(name, scname) static void scname(struct registers* r) { name(r->ebx, r->ecx); } -#define CALL3V(name, scname) static void scname(struct registers* r) { name(r->ebx, r->ecx, r->edx); } -#define CALL4V(name, scname) static void scname(struct registers* r) { name(r->ebx, r->ecx, r->edx, r->esi); } +#define CALL1V(name, scname) static void scname(struct registers* r) { name(r->ecx); } +#define CALL2V(name, scname) static void scname(struct registers* r) { name(r->ecx, r->edx); } +#define CALL3V(name, scname) static void scname(struct registers* r) { name(r->ecx, r->edx, r->esi); } +#define CALL4V(name, scname) static void scname(struct registers* r) { name(r->ecx, r->edx, r->esi, r->edi); } CALL0V(thread_exit, thread_exit_sc); CALL0V(schedule, schedule_sc); @@ -25,21 +29,61 @@ CALL0(proc_priv, proc_priv_sc); CALL1(process_sbrk, proc_sbrk_sc); CALL1V(process_brk, proc_brk_sc); +CALL1(open, open_sc); +CALL2(open_relative, open_relative_sc); +CALL1V(close, close_sc); +CALL2(get_methods, get_methods_sc); + static void thread_new_sc(struct registers* r) { cli(); - thread_new(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx, (void*)r->edx); + thread_new(current_thread->process, (thread_entry)r->ecx, (void*)r->edx, (void*)r->esi); sti(); } int_callback syscalls[NUMBER_OF_SYSCALLS] = { - thread_exit_sc, //0 + 0, //0 + thread_exit_sc, schedule_sc, thread_sleep_sc, process_exit_sc, - printk_sc, - thread_new_sc, //5 + printk_sc, //5 + thread_new_sc, irq_wait_sc, proc_priv_sc, proc_sbrk_sc, - proc_brk_sc, - 0 }; + proc_brk_sc, //10 + 0, + 0, + 0, + 0, + 0, //15 + 0, + 0, + 0, + 0, + open_sc, //20 + open_relative_sc, + close_sc, + get_methods_sc, + 0, + 0, //25 + 0, + 0, + 0, + 0, + 0, //30 + 0, //31 + + }; + +/* Called in idt_.asm on a system call (interrupt 64). + Calls the correct syscall handler (if any). */ +void idt_syscallHandler(struct registers regs) { + if (regs.eax == 0) { + if (regs.ebx < NUMBER_OF_SYSCALLS && syscalls[regs.ebx] != 0) { + syscalls[regs.ebx](®s); + } + } else { + do_method_call(®s); + } +} diff --git a/src/kernel/task/syscall.h b/src/kernel/task/syscall.h index f03be55..54af108 100644 --- a/src/kernel/task/syscall.h +++ b/src/kernel/task/syscall.h @@ -3,8 +3,6 @@ #include "idt.h" -#define NUMBER_OF_SYSCALLS 32 - extern int_callback syscalls[]; #endif diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index 9d98165..4c99bf7 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -7,6 +7,8 @@ #include #include "timer.h" +#include + #define KSTACKSIZE 0x8000 //Static routines for handling threads exiting and all cleanup @@ -286,6 +288,13 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi p->data = 0; p->dataseg = 0; + p->handles.ref_vect_init_len = 32; + p->handles.vect_len = 128; + p->handles.data = 0; + earray_init(&p->handles); + ASSERT(earray_add(&p->handles, 0xFFFFFFF0) == 0); + ASSERT(earray_add(&p->handles, 0xFFFFFFF0) == 1); + p->stack = 0; if (p->privilege >= PL_USER) { //We are running in user mode size_t stacksBottom = K_HIGHHALF_ADDR - 0x01000000; @@ -319,6 +328,8 @@ static void thread_delete(struct thread *th) { /* Deletes a process. First, deletes all its threads. Also deletes the corresponding page directory. */ static void process_delete(struct process *pr) { + int i; + struct thread *it = pr->threads; while (it != 0) { thread_delete(it); @@ -336,31 +347,19 @@ static void process_delete(struct process *pr) { it = it->next; } } + for (i = 1; i < pr->handles.elements; i++) { + Object* obj = earray_at(&pr->handles, i); + if (obj != 0) { + obj->handles--; + if (obj->_class->closed != 0) obj->_class->closed(obj); + } + } + earray_free(&pr->handles); + pagedir_delete(pr->pagedir); kfree(pr); } -/* System call. Called by the app to define the place for the heap. */ -/*int process_setheapseg(size_t start, size_t end) { //syscall - struct process *p = current_thread->process; - if (start >= K_HIGHHALF_ADDR || end >= K_HIGHHALF_ADDR) return -1; - if (p->heapseg == 0) { - struct segment *s = simpleseg_make(start, end - start, 1); - if (s == 0) return -5; - p->heapseg = seg_map(s, p->pagedir, 0); - if (p->heapseg == 0) return -1; - return 0; - } else if (p->heapseg->start != start) { - seg_unmap(p->heapseg); - struct segment *s = simpleseg_make(start, end - start, 1); - if (s == 0) return -5; - p->heapseg = seg_map(s, p->pagedir, 0); - if (p->heapseg == 0) return -1; - return 0; - } else { - return simpleseg_resize(p->heapseg, end - start); - } -}*/ size_t process_sbrk(size_t size) { struct process *p = current_thread->process; diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h index 63cb35a..dbeb638 100644 --- a/src/kernel/task/task.h +++ b/src/kernel/task/task.h @@ -3,6 +3,7 @@ #include #include +#include #include "idt.h" #define TS_RUNNING 0 @@ -28,6 +29,8 @@ struct process { struct segment_map *dataseg; + struct earray handles; + struct process *next; //Forms a linked list struct thread *threads; }; @@ -44,6 +47,7 @@ struct thread { }; extern struct thread *current_thread; +#define current_process (current_thread != 0 ? current_thread->process : 0) void tasking_init(); void schedule(); -- cgit v1.2.3