summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/directories.txt11
-rw-r--r--doc/objects-requests.txt11
-rw-r--r--doc/syscalls.txt4
-rw-r--r--src/include/gc/syscall.h (renamed from src/library/grapes/syscall.h)5
-rw-r--r--src/kernel/Makefile2
-rw-r--r--src/kernel/ipc/object.c113
-rw-r--r--src/kernel/ipc/object.h29
-rw-r--r--src/kernel/ipc/request.c55
-rw-r--r--src/kernel/ipc/request.h20
-rw-r--r--src/kernel/ipc/shm.c26
-rw-r--r--src/kernel/ipc/shm.h7
-rw-r--r--src/kernel/task/idt.c3
-rw-r--r--src/kernel/task/syscall.c11
-rw-r--r--src/kernel/task/task.c18
-rw-r--r--src/kernel/task/task.h6
-rw-r--r--src/library/Makefile4
-rw-r--r--src/library/gc/syscall.c (renamed from src/library/grapes/syscall.c)14
-rw-r--r--src/library/start.c2
-rw-r--r--src/modules/test/Makefile2
-rw-r--r--src/modules/test/main.c8
20 files changed, 316 insertions, 35 deletions
diff --git a/doc/directories.txt b/doc/directories.txt
new file mode 100644
index 0000000..b0adf7b
--- /dev/null
+++ b/doc/directories.txt
@@ -0,0 +1,11 @@
+This file explains all the directories of the source tree :
+
+doc documentation about the system
+mnt temporary folder for mounting disk images
+src source code
+src/include all includable headers to be used in userland
+src/include/gc Grapes Core (communication with the kernel) headers
+src/include/gm Grapes Modules headers
+src/kernel kernel source
+src/library source and linkable objects to be used by userland applications
+src/modules userland applications
diff --git a/doc/objects-requests.txt b/doc/objects-requests.txt
new file mode 100644
index 0000000..9169552
--- /dev/null
+++ b/doc/objects-requests.txt
@@ -0,0 +1,11 @@
+Requests are identified by a 32bit function number, composed as follows :
+ (8 bit) parameter and return type ; (24bit) function number
+
+the first 8 bits are :
+ 2bit answer type ; 2bit parameter a ; 2bit parameter b ; 2bit parameter c
+
+each two bit couple can be one of the following :
+- 00 : void
+- 01 : object descriptor number (will be copied with a new number to reciever)
+- 10 : integer
+- 11 : long long (replies), or shared memory offset (requests and messages)
diff --git a/doc/syscalls.txt b/doc/syscalls.txt
index baa537e..663618d 100644
--- a/doc/syscalls.txt
+++ b/doc/syscalls.txt
@@ -12,5 +12,9 @@ id=eax Name Parameters Description
5 thread_new ebx: entry point Creates a new thread
ecx: data pointer
6 irq_wait ebx: irq number Waits for an IRQ (requires privilege PL_DRIVER)
+ 7 proc_priv none Returns current process privilege level
+ 8 shm_create ebx: offset Create a shared memory segment at offset (ret = errcode)
+ ecx: length
+ 9 shm_delete ebx: offset Delete a shared memory segment at offset (ret = errcode)
If a processes wishes to exit with an error code, it HAS to use process_exit. thread_exit will do nothing.
diff --git a/src/library/grapes/syscall.h b/src/include/gc/syscall.h
index d2f80e5..4001420 100644
--- a/src/library/grapes/syscall.h
+++ b/src/include/gc/syscall.h
@@ -1,6 +1,8 @@
#ifndef DEF_SYSCALL_H
#define DEF_SYSCALL_H
+typedef unsigned size_t;
+
void thread_exit();
void schedule();
void thread_sleep(int time);
@@ -8,5 +10,8 @@ void process_exit(int retval);
void printk(char* str);
void thread_new(void (*entry)(void*), void *data);
void irq_wait(int number);
+int proc_priv();
+int shm_create(size_t offset, size_t length);
+int shm_delete(size_t offset);
#endif
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 3508bb9..5de25f8 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -14,7 +14,7 @@ OBJECTS = core/loader_.o core/kmain.o core/sys.o \
task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o \
lib/stdlib.o lib/bitset.o lib/mutex.o \
mem/mem.o mem/paging.o mem/gdt.o mem/heap.o mem/seg.o \
- ipc/shm.o \
+ ipc/shm.o ipc/object.o \
linker/elf.o
OUT = kernel.elf
diff --git a/src/kernel/ipc/object.c b/src/kernel/ipc/object.c
new file mode 100644
index 0000000..70c31b2
--- /dev/null
+++ b/src/kernel/ipc/object.c
@@ -0,0 +1,113 @@
+#include "object.h"
+#include <lib/mutex.h>
+#include <mem/mem.h>
+
+struct object* obj_new(struct process* owner) {
+ struct object* ret = kmalloc(sizeof(struct object));
+ ret->owner = owner;
+ ret->descriptors = 0;
+ ret->busyMutex = MUTEX_UNLOCKED;
+ ret->request = 0;
+ return ret;
+}
+
+void obj_delete(struct object* obj) {
+ if (obj->descriptors > 0) return;
+ if (obj->busyMutex != MUTEX_UNLOCKED) return;
+ if (obj->request != 0) return;
+ kfree(obj);
+}
+
+int obj_createP(struct process* p) {
+ return objdesc_add(p, obj_new(p));
+}
+
+void obj_closeP(struct process* p, int id) {
+ struct object* obj = objdesc_read(p, id);
+ if (obj == 0) return;
+ objdesc_rm(p, id);
+ if (obj->owner == p) {
+ if (obj->descriptors > 0) {
+ obj->owner = 0; // set object to be invalid
+ //if a request was being handled, give it a null response
+ } else {
+ obj_delete(obj);
+ }
+ } else {
+ if (obj->descriptors == 0 && obj->owner == 0) {
+ obj_delete(obj);
+ }
+ //future : send message becuz object was closed
+ }
+}
+
+void obj_closeall(struct process* p) {
+ while (p->objects != 0) obj_closeP(p, p->objects->id);
+}
+
+// DESCRIPTORS
+
+int objdesc_add(struct process* proc, struct object* obj) {
+ struct obj_descriptor *ret = kmalloc(sizeof(struct obj_descriptor));
+ ret->obj = obj;
+ ret->id = proc->next_objdesc;
+ ret->next = proc->objects;
+ proc->objects = ret;
+ obj->descriptors++;
+ proc->next_objdesc++;
+ return ret->id;
+}
+
+int objdesc_get(struct process* proc, struct object* obj) {
+ struct obj_descriptor *it = proc->objects;
+ while (it != 0) {
+ if (it->obj == obj) return it->id;
+ it = it->next;
+ }
+ return -1;
+}
+
+struct object* objdesc_read(struct process* proc, int id) {
+ struct obj_descriptor *it = proc->objects;
+ while (it != 0) {
+ if (it->id == id) return it->obj;
+ it = it->next;
+ }
+ return 0;
+}
+
+void objdesc_rm(struct process* proc, int id) {
+ struct obj_descriptor *e = proc->objects;
+ if (e != 0 && e->id == id) {
+ proc->objects = e->next;
+ e->obj->descriptors--;
+ kfree(e);
+ return;
+ }
+ while (e->next != 0) {
+ if (e->next->id == id) {
+ e->next = e->next->next;
+ e->next->obj->descriptors--;
+ kfree(e->next);
+ return;
+ }
+ e = e->next;
+ }
+}
+
+// SYSCALLS
+
+int object_create() {
+ return obj_createP(current_thread->process);
+}
+
+int object_owned(int id) {
+ struct object *obj = objdesc_read(current_thread->process, id);
+ if (obj == 0) return -1;
+ if (obj->owner == current_thread->process) return 1;
+ return 0;
+}
+
+void object_close(int id) {
+ obj_closeP(current_thread->process, id);
+}
diff --git a/src/kernel/ipc/object.h b/src/kernel/ipc/object.h
index ef90a66..9dd3a1e 100644
--- a/src/kernel/ipc/object.h
+++ b/src/kernel/ipc/object.h
@@ -3,24 +3,37 @@
#include <task/task.h>
-#define OS_INACTIVE 0 //No one doing anything on this
-#define OS_LISTENING 1 //A thread is waiting for a request on this object
-#define OS_REQUESTPENDING 2 //A request is waiting for a thread to handle it
-#define OS_BUSY 3 //A thread is currently handling a request
-
struct object {
- struct process *owner;
+ struct process *owner; //when 0, object is invalid and cannot handle requests
int descriptors;
- uint32_t busyMutex;
+ uint32_t busyMutex; //if busy, either a blocking request is being processed, or a sent message is waiting for being recieved
struct request *request;
};
struct obj_descriptor {
struct object *obj;
int id;
- int owned;
struct obj_descriptor *next;
};
+//Objects
+struct object* obj_new(struct process *owner);
+void obj_delete(struct object* obj);
+
+int obj_createP(struct process* p);
+void obj_closeP(struct process* p, int id);
+void obj_closeall(struct process* p);
+
+//Object descriptors
+int objdesc_add(struct process* proc, struct object* obj); // add a descriptor
+int objdesc_get(struct process* proc, struct object* obj); // look in descriptors for the one corresponding to the object
+struct object* objdesc_read(struct process* proc, int id); // get the object correspoinding to the id
+void objdesc_rm(struct process* proc, int id); // remove descriptor for an object
+
+//Syscalls
+int object_create();
+int object_owned(int id); //does current process own object ? 1=yes 0=no
+void object_close(int id); //closes descriptor to specified object. if we are the owner, make all requests to object fail.
+
#endif
diff --git a/src/kernel/ipc/request.c b/src/kernel/ipc/request.c
new file mode 100644
index 0000000..51a0bbc
--- /dev/null
+++ b/src/kernel/ipc/request.c
@@ -0,0 +1,55 @@
+#include "request.h"
+
+int request_get(int obj, uint32_t ptr, int wait) {
+ //check if we own the object, if not return -2
+ //check if a request is pending. if request is being processed, return -3
+ //if not (busymutex unlocked or request==0) && wait, then wait, else return -1
+ //if request pending, write it to ptr
+ // if request is nonblocking and no shm is to be mapped, delete it and unlock objects busymutex
+ //return 0
+}
+
+int request_has(int obj) {
+ //check if we own the object, if not return -2
+ //check if a request is pending.
+ // if being processed, return 2
+ // if waiting for ack, return 1
+ // if none (busymutex unlocked or request==0), return 0
+}
+
+void request_answer(int obj, uint32_t answer) {
+ //check if we own the object, if not return
+ //if no blocking request is being processed (including non-acknowledged waiting requests), return
+ //set blocking request to finished, and set its answer
+ //dereference request from object, unlock objects busymutex
+}
+
+int request_mapShm(int obj, uint32_t pos, int number) {
+ //check if we own the object, if not return -2
+ //if no request is being processes (including non-acknowledged waiting requests), return -3
+ //check if the requests has shm in parameter [number], if not return -4
+ //map shm to position
+ //if request is nonblocking and no more shm is to be mapped, delete request and free object busymutex
+ //return 0
+}
+
+static struct request *mkrequest(int obj, struct thread *requester,
+ uint32_t func, uint32_t a, uint32_t b, uint32_t c) {
+ // get object from descriptor id, if none return 0
+ // waitlock object's busy mutex
+ // if object cannot answer (owner == 0) return 0
+ // create request, fill it up, reference it from object
+ // return request
+}
+
+int request(int obj, uint32_t func, uint32_t a, uint32_t b, uint32_t c, uint32_t answerptr) {
+ //call mkrequest with parameters (requester thread = current thread)
+ //if returned value is 0, return -1
+ //sleep until request is handled
+ //write answer to *answerptr, delete request, return 0
+}
+
+int send_msg(int obj, uint32_t func, uint32_t a, uint32_t b, uint32_t c) {
+ //call mkrequest with parameters (requester thread = 0)
+ //if returned value is 0, return -1 else return 0
+}
diff --git a/src/kernel/ipc/request.h b/src/kernel/ipc/request.h
index bf90c68..4a35dc3 100644
--- a/src/kernel/ipc/request.h
+++ b/src/kernel/ipc/request.h
@@ -10,13 +10,12 @@
struct request {
struct object *obj;
- struct thread *requester;
- uint32_t func, param1, param2, param3;
- struct seg_map *shm_cli, *shm_srv;
- int answerType;
+ struct thread *requester; //0 if nonblocking message
+ uint32_t func, params[3];
+ struct seg_map *shm_srv[3], *shm_cli[3];
union {
- int num;
- struct object* obj;
+ int64_t ll;
+ uint32_t n;
} answer;
};
@@ -25,5 +24,14 @@ struct user_request {
int hasShm;
};
+//syscalls
+int request_get(int obj, uint32_t ptr, int wait);
+int request_has(int obj);
+void request_answer(int obj, uint32_t answer);
+int request_mapShm(int obj, uint32_t pos, int number);
+
+int request(int obj, uint32_t func, uint32_t a, uint32_t b, uint32_t c, uint32_t answerptr);
+int send_msg(int obj, uint32_t func, uint32_t a, uint32_t b, uint32_t c);
+
#endif
diff --git a/src/kernel/ipc/shm.c b/src/kernel/ipc/shm.c
index 0a0d3ee..1cdacfb 100644
--- a/src/kernel/ipc/shm.c
+++ b/src/kernel/ipc/shm.c
@@ -1,6 +1,7 @@
#include "shm.h"
#include <mem/mem.h>
#include <mem/seg.h>
+#include <task/task.h>
struct segment* shmseg_make(size_t len, struct process* owner) {
struct shmseg *ss = kmalloc(sizeof(struct shmseg));
@@ -54,3 +55,28 @@ void shmseg_delete(struct segment *seg) {
}
kfree(ss->frames);
}
+
+struct segment_map* shmseg_getByOff(struct process* pr, size_t offset) {
+ struct segment_map* m = pr->pagedir->mappedSegs;
+ while (m != 0) {
+ if (m->start == offset && m->seg->delete == shmseg_delete) return m;
+ m = m->next;
+ }
+ return 0;
+}
+
+// **** **** SHM syscalls **** ****
+int shm_create(size_t offset, size_t len) {
+ if (offset >= 0xE0000000) return -1;
+ if (len >= 0x10000000) return -1;
+ if (offset+len >= 0xE0000000) return -1;
+ seg_map(shmseg_make(len, current_thread->process), current_thread->process->pagedir, offset);
+ return 0;
+}
+
+int shm_delete(size_t offset) {
+ struct segment_map *s = shmseg_getByOff(current_thread->process, offset);
+ if (s == 0) return -1;
+ seg_unmap(s);
+ return 0;
+}
diff --git a/src/kernel/ipc/shm.h b/src/kernel/ipc/shm.h
index b409955..895a619 100644
--- a/src/kernel/ipc/shm.h
+++ b/src/kernel/ipc/shm.h
@@ -16,9 +16,12 @@ void shmseg_unmap(struct segment_map*);
void shmseg_delete(struct segment *seg);
int shmseg_handleFault(struct segment_map *map, size_t addr, int write);
+ //find a shared memory segment in current address space by its offset
+struct segment_map* shmseg_getByOff(struct process* pr, size_t offset);
+
//Shared memory syscalls
-void shm_create(size_t offset, size_t len);
-void shm_delete(size_t offset);
+int shm_create(size_t offset, size_t len);
+int shm_delete(size_t offset);
#endif
diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c
index cff4ae9..0f3c2f2 100644
--- a/src/kernel/task/idt.c
+++ b/src/kernel/task/idt.c
@@ -198,7 +198,6 @@ void idt_handleIrq(int number, int_callback func) {
void idt_waitIrq(int number) {
if (number < 16 && number >= 0 && proc_priv() <= PL_DRIVER) {
irq_wakeup[number] = current_thread;
- current_thread->state = TS_WAKEWAIT;
- tasking_schedule();
+ thread_goInactive();
}
}
diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c
index 752864c..51c46f1 100644
--- a/src/kernel/task/syscall.c
+++ b/src/kernel/task/syscall.c
@@ -8,6 +8,7 @@
r->eax = name(r->ebx, r->ecx); }
#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); }
CALL0V(thread_exit, thread_exit_sc);
CALL0V(tasking_switch, schedule_sc);
@@ -15,17 +16,23 @@ CALL1V(thread_sleep, thread_sleep_sc);
CALL1V(process_exit, process_exit_sc);
CALL1(monitor_write, printk_sc);
CALL1V(idt_waitIrq, irq_wait_sc);
+CALL0(proc_priv, proc_priv_sc);
+CALL2(shm_create, shm_create_sc);
+CALL1(shm_delete, shm_delete_sc);
static void thread_new_sc(struct registers* r) {
thread_new(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx);
}
int_callback syscalls[] = {
- thread_exit_sc,
+ thread_exit_sc, //0
schedule_sc,
thread_sleep_sc,
process_exit_sc,
printk_sc,
- thread_new_sc,
+ thread_new_sc, //5
irq_wait_sc,
+ proc_priv_sc,
+ shm_create_sc,
+ shm_delete_sc,
0 };
diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c
index 622eaa1..6959676 100644
--- a/src/kernel/task/task.c
+++ b/src/kernel/task/task.c
@@ -88,10 +88,6 @@ void tasking_switch() {
: : "r"(current_thread->ebp), "r"(current_thread->esp), "r"(current_thread->eip));
}
-void tasking_schedule() {
- asm volatile("int $64" : : "a"(1));
-}
-
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablephysical) {
if (idx < 896) return;
struct process* it = processes;
@@ -119,13 +115,19 @@ uint32_t tasking_handleException(struct registers *regs) {
thread_exit_stackJmp(EX_TH_EXCEPTION);
}
PANIC("This should never have happened. Please report this.");
+ return 0;
}
void thread_sleep(uint32_t msecs) {
if (current_thread == 0) return;
current_thread->state = TS_SLEEPING;
current_thread->timeWait = timer_time() + msecs;
- tasking_schedule();
+ tasking_switch();
+}
+
+void thread_goInactive() {
+ current_thread->state = TS_WAKEWAIT;
+ tasking_switch();
}
int proc_priv() {
@@ -271,6 +273,11 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi
p->pagedir = pagedir_new();
p->next = processes;
p->stacksBottom = 0xDF000000;
+
+ p->next_objdesc = 0;
+ p->objects = 0;
+ obj_createP(p); //create process' root object and add descriptor 0 to it
+
processes = p;
return p;
}
@@ -296,6 +303,7 @@ static void process_delete(struct process *pr) {
while (it->next->process == pr) thread_delete(it->next);
it = it->next;
}
+ obj_closeall(pr);
pagedir_delete(pr->pagedir);
if (processes == pr) {
processes = pr->next;
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index dd5461e..b2a5434 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -3,6 +3,7 @@
#include <types.h>
#include <mem/paging.h>
+#include <ipc/object.h>
#include "idt.h"
#define TS_RUNNING 0
@@ -29,6 +30,9 @@ struct process {
struct page_directory *pagedir;
size_t stacksBottom;
+ struct obj_descriptor *objects;
+ uint32_t next_objdesc;
+
struct process *next; //Forms a linked list
};
@@ -48,11 +52,11 @@ extern struct thread *current_thread;
void tasking_init();
void tasking_switch();
-void tasking_schedule();
void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint32_t tablePhysical);
uint32_t tasking_handleException(struct registers *regs);
void thread_sleep(uint32_t msecs);
+void thread_goInactive(); //Blocks the current thread. another one must be there to wake it up at some point.
int proc_priv(); //Returns current privilege level
void thread_exit();
void process_exit(uint32_t retval);
diff --git a/src/library/Makefile b/src/library/Makefile
index c562dec..74eb525 100644
--- a/src/library/Makefile
+++ b/src/library/Makefile
@@ -1,13 +1,13 @@
.PHONY: clean, mrproper
CC = gcc
-CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra
+CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I../include
LD = ld
LDFLAGS = -r
Library = grapes.o
-Objects = grapes/syscall.o \
+Objects = gc/syscall.o \
start.o
all: $(Library)
diff --git a/src/library/grapes/syscall.c b/src/library/gc/syscall.c
index 38adc01..e1ef3cd 100644
--- a/src/library/grapes/syscall.c
+++ b/src/library/gc/syscall.c
@@ -1,4 +1,4 @@
-#include "syscall.h"
+#include <gc/syscall.h>
static int call(unsigned a, unsigned b, unsigned c, unsigned d, unsigned e, unsigned f) {
unsigned ret;
@@ -33,3 +33,15 @@ void thread_new(void (*entry)(void*), void *data) {
void irq_wait(int number) {
call(6, number, 0, 0, 0, 0);
}
+
+int proc_priv() {
+ return call(7, 0, 0, 0, 0, 0);
+}
+
+int shm_create(size_t offset, size_t length) {
+ return call(8, offset, length, 0, 0, 0);
+}
+
+int shm_delete(size_t offset) {
+ return call(9, offset, 0, 0, 0, 0);
+}
diff --git a/src/library/start.c b/src/library/start.c
index 8f83a23..b3c5541 100644
--- a/src/library/start.c
+++ b/src/library/start.c
@@ -1,4 +1,4 @@
-#include "grapes/syscall.h"
+#include <gc/syscall.h>
extern int main();
diff --git a/src/modules/test/Makefile b/src/modules/test/Makefile
index d12e57d..e571da9 100644
--- a/src/modules/test/Makefile
+++ b/src/modules/test/Makefile
@@ -1,7 +1,7 @@
.PHONY: clean, mrproper
CC = gcc
-CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I ../../library
+CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I ../../include
LD = ld
LDFLAGS = -T ../../library/link.ld -L ../../library -Map main.map
diff --git a/src/modules/test/main.c b/src/modules/test/main.c
index 01ab836..9e03ee8 100644
--- a/src/modules/test/main.c
+++ b/src/modules/test/main.c
@@ -1,9 +1,11 @@
-#include <grapes/syscall.h>
+#include <gc/syscall.h>
+
+#define FACTOR 4
void thread2(void* d) {
while (1) {
- thread_sleep(1400);
printk("$");
+ thread_sleep(35*FACTOR);
}
}
@@ -12,8 +14,8 @@ int main() {
printk("[module:test] Creating new thread...\n");
thread_new(thread2, 0);
while (1) {
- thread_sleep(2000);
printk(".");
+ thread_sleep(50*FACTOR);
}
return 0;
}