summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/roadmap.txt5
-rw-r--r--src/include/gc/shm.h16
-rw-r--r--src/include/gc/syscall.h2
-rw-r--r--src/include/mutex.h15
-rw-r--r--src/kernel/ipc/request.c6
-rw-r--r--src/kernel/ipc/request.h2
-rw-r--r--src/library/Makefile6
-rw-r--r--src/library/gc/object.c25
-rw-r--r--src/library/gc/shm.c100
-rw-r--r--src/library/mutex.c22
10 files changed, 187 insertions, 12 deletions
diff --git a/doc/roadmap.txt b/doc/roadmap.txt
index 7304e4b..de4b3cb 100644
--- a/doc/roadmap.txt
+++ b/doc/roadmap.txt
@@ -1,8 +1,7 @@
** 0.0.4 'Cat in my heart' **
- [OK] Userland heap (meaning kernel can give memory to processes)
-- Userland helper functions for objects (server and client)
-- Basic object method for knowing if object handles another method (list methods in src/include/gm)
-- Userland library for writing numbers and other stuff
+- Userland helper functions for objects (server and client, shared memory segment manager)
+- [OK] Basic object method for knowing if object handles another method (list methods in src/include/gm)
- A manager module that manages all other running modules (the privilege of manager is given by the kernel to the first module loaded)
** 0.0.5 'Truth is better cold' **
diff --git a/src/include/gc/shm.h b/src/include/gc/shm.h
new file mode 100644
index 0000000..1a3f0a1
--- /dev/null
+++ b/src/include/gc/shm.h
@@ -0,0 +1,16 @@
+#ifndef DEF_SHM_H
+#define DEF_SHM_H
+
+#include <gc/syscall.h>
+
+/*
+ * This file contains headers for the shared segment mapping manager.
+ */
+
+void* shm_alloc(size_t size); //allocates a spot in shared memory space
+void shm_free(void* p); //frees a spot
+
+void* shm_allocNew(size_t size); //calls shm_alloc, and maps a new segment there
+void shm_freeDel(void* p); //unmaps segment and calls shm_free
+
+#endif
diff --git a/src/include/gc/syscall.h b/src/include/gc/syscall.h
index f731e10..c93a523 100644
--- a/src/include/gc/syscall.h
+++ b/src/include/gc/syscall.h
@@ -13,7 +13,7 @@ typedef char int8_t;
typedef unsigned size_t;
struct user_request {
- uint32_t func, params[3];
+ uint32_t func, params[3], shmsize[3];
int isBlocking; // 1 : blocking request, 0 : nonblocking request (message)
};
diff --git a/src/include/mutex.h b/src/include/mutex.h
new file mode 100644
index 0000000..50b5606
--- /dev/null
+++ b/src/include/mutex.h
@@ -0,0 +1,15 @@
+#ifndef DEF_MUTEX_H
+#define DEF_MUTEX_H
+
+#include <gc/syscall.h>
+
+#define MUTEX_LOCKED 1
+#define MUTEX_UNLOCKED 0
+
+//A mutex is just an uint32_t
+
+void mutex_lock(uint32_t* mutex); //wait for mutex to be free
+int mutex_lockE(uint32_t* mutex); //lock mutex only if free, returns !0 if locked, 0 if was busy
+void mutex_unlock(uint32_t* mutex);
+
+#endif
diff --git a/src/kernel/ipc/request.c b/src/kernel/ipc/request.c
index e59a66c..4e8b407 100644
--- a/src/kernel/ipc/request.c
+++ b/src/kernel/ipc/request.c
@@ -20,7 +20,11 @@ int request_get(int id, uint32_t ptr, int wait) {
//when request pending (wait finished), write it to ptr
struct user_request *p = (struct user_request*)ptr;
p->func = obj->request->func;
- for (i = 0; i < 3; i++) p->params[i] = obj->request->params[i];
+ for (i = 0; i < 3; i++) {
+ p->params[i] = obj->request->params[i];
+ if (obj->request->shm_sndr[i] != 0) p->shmsize[i] = obj->request->shm_sndr[i]->len;
+ else p->shmsize[i] = 0;
+ }
p->isBlocking = (obj->request->requester != 0);
//if request is nonblocking and no shm is to be mapped, delete request and unlock objects busymutex, else set it to acknowledged
if (p->isBlocking) return 0;
diff --git a/src/kernel/ipc/request.h b/src/kernel/ipc/request.h
index 0afc48b..b08264f 100644
--- a/src/kernel/ipc/request.h
+++ b/src/kernel/ipc/request.h
@@ -28,7 +28,7 @@ struct request {
};
struct user_request {
- uint32_t func, params[3];
+ uint32_t func, params[3], shmsize[3];
int isBlocking; // 1 : blocking request, 0 : nonblocking request (message)
};
diff --git a/src/library/Makefile b/src/library/Makefile
index be5a76d..b0dac11 100644
--- a/src/library/Makefile
+++ b/src/library/Makefile
@@ -7,9 +7,9 @@ LD = ld
LDFLAGS = -r
Library = grapes.o
-Objects = gc/syscall.o \
- gc/mem.o \
- gc/object.o \
+Objects = gc/syscall.o gc/object.o \
+ gc/mem.o gc/shm.o \
+ mutex.o \
start.o
all: $(Library)
diff --git a/src/library/gc/object.c b/src/library/gc/object.c
index 59b986b..87dafd8 100644
--- a/src/library/gc/object.c
+++ b/src/library/gc/object.c
@@ -1,12 +1,14 @@
#include <gc/server.h>
#include <gm/method.h>
#include <gc/mem.h>
+#include <gc/shm.h>
Server procServer;
static Server* servers = 0;
static method_handler getHandler(Server *o, uint32_t m);
static struct method_ret checkIfHandles(struct method_data *d);
+static struct method_ret checkIfHandlesMany(struct method_data *d);
void objsrv_init() {
procServer.id = 0;
@@ -15,6 +17,7 @@ void objsrv_init() {
procServer.data = 0;
servers = &procServer;
srv_addHandler(&procServer, M_HANDLECHECK_BIVV, checkIfHandles);
+ srv_addHandler(&procServer, M_HANDLECHECK_BMIV, checkIfHandlesMany);
}
void srv_handleAll() {
@@ -55,8 +58,12 @@ void srv_handle(Server *o, int act) {
case PT_SHM: //all the fuss about keepShm only applies to messages.
md.parameters[i].keepShm = 1; //if local memory or if nothing, do not unmap it
if (rq.params[i] == 0) { //TODO : map shm (shm manager) !!!
- md.parameters[i].val.p = 0;
- //md.parameters[i].keepShm = 0; //we had to map it, so mark it to be unmapped
+ void* p = shm_alloc(rq.shmsize[i]);
+ md.parameters[i].val.p = p;
+ if (p != 0) {
+ request_mapShm(o->id, (size_t)p, i);
+ md.parameters[i].keepShm = 0; //we had to map it, so mark it to be unmapped
+ }
} else {
md.parameters[i].val.p = (void*)rq.params[i];
}
@@ -73,7 +80,7 @@ void srv_handle(Server *o, int act) {
} else {
for (i = 0; i < 3; i++) {
if (md.parameters[i].type == PT_SHM && md.parameters[i].keepShm == 0) {
- //TODO : unmap shm
+ shm_freeDel(md.parameters[i].val.p);
}
}
}
@@ -97,6 +104,7 @@ Server *srv_create() {
s->data = 0;
s->next = servers;
srv_addHandler(s, M_HANDLECHECK_BIVV, checkIfHandles);
+ srv_addHandler(s, M_HANDLECHECK_BMIV, checkIfHandlesMany);
servers = s;
return s;
}
@@ -145,6 +153,17 @@ struct method_ret checkIfHandles(struct method_data *d) {
return mr_long(1);
}
+struct method_ret checkIfHandlesMany(struct method_data *d) {
+ if (d->parameters[0].type != PT_SHM) return mr_err(-1);
+ if (d->parameters[1].type != PT_LONG) return mr_err(-1);
+ uint32_t *data = d->parameters[0].val.p, i;
+ if (data == 0) return mr_long(0);
+ for (i = 0; i < d->parameters[1].val.i; i++) {
+ if (getHandler(d->obj, data[i]) == 0) return mr_long(0);
+ }
+ return mr_long(1);
+}
+
// ***************************** HELPER FUNCTIONS FOR RETRUN VALUES
struct method_ret mr_long(int val) {
diff --git a/src/library/gc/shm.c b/src/library/gc/shm.c
new file mode 100644
index 0000000..9e19533
--- /dev/null
+++ b/src/library/gc/shm.c
@@ -0,0 +1,100 @@
+#include <gc/shm.h>
+#include <gc/mem.h>
+#include <mutex.h>
+
+struct shm_block {
+ size_t start, size;
+ int is_hole; //1 : hole, 0 : used block
+ struct shm_block *prev, *next;
+};
+
+struct shm_block *blocks = 0;
+
+static uint32_t tMutex = MUTEX_UNLOCKED;
+
+static void shm_init() {
+ struct shm_block *b = malloc(sizeof(struct shm_block));
+ b->start = 0x80000000;
+ b->size = 0xD0000000 - 0x80000000;
+ b->is_hole = 1;
+ b->prev = b->next = 0;
+ blocks = b;
+}
+
+void* shm_alloc(size_t size) {
+ mutex_lock(&tMutex);
+ if (blocks == 0) shm_init();
+ if (size & 0xFFF) size = (size & 0xFFFFF000) + 0x1000;
+ //go through all blocks, get the one with the closest size
+ struct shm_block *block = blocks;
+ while (block) {
+ if (block->size >= size) break;
+ block = block->next;
+ }
+ if (block == 0) {
+ mutex_unlock(&tMutex);
+ return 0;
+ }
+ //if the block's size is bigger, reduce it and create a new one after
+ if (block->size > size) {
+ struct shm_block *newb = malloc(sizeof(struct shm_block));
+ newb->start = block->start + size;
+ newb->size = block->size - size;
+ newb->is_hole = 1;
+ newb->prev = block; newb->next = block->next;
+ block->size = size;
+ if (block->next != 0) block->next->prev = newb;
+ block->next = newb;
+ }
+ //mark block as used
+ block->is_hole = 0;
+ //return block's address
+ mutex_unlock(&tMutex);
+ return (void*)block->start;
+}
+
+static void unify (struct shm_block *b) {
+ if (b->next == 0 || b->is_hole == 0 || b->next->is_hole == 0) return;
+ struct shm_block *n = b->next;
+ b->size += n->size;
+ n->next->prev = b;
+ b->next = n->next;
+ free(n);
+}
+
+void shm_free(void* p) {
+ mutex_lock(&tMutex);
+ //find block
+ struct shm_block *bl = blocks;
+ while (bl) {
+ if (bl->start == (size_t)p) break;
+ bl = bl->next;
+ }
+ if (bl == 0) {
+ mutex_unlock(&tMutex);
+ return;
+ }
+ //mark it as a hole
+ bl->is_hole = 1;
+ //unify after if possible
+ if (bl->next != 0 && bl->next->is_hole == 1) unify(bl);
+ //unify before if possible
+ if (bl->prev != 0 && bl->prev->is_hole == 1) unify(bl->prev);
+ mutex_unlock(&tMutex);
+}
+
+void* shm_allocNew(size_t size) {
+ if (size & 0xFFF) size = (size & 0xFFFFF000) + 0x1000;
+
+ void* p = shm_alloc(size);
+ if (shm_create((size_t)p, size) != 0) {
+ shm_free(p);
+ return 0;
+ }
+ return p;
+}
+
+void shm_freeDel(void *p) {
+ shm_delete((size_t)p);
+ shm_free(p);
+}
diff --git a/src/library/mutex.c b/src/library/mutex.c
new file mode 100644
index 0000000..ac0ee8f
--- /dev/null
+++ b/src/library/mutex.c
@@ -0,0 +1,22 @@
+#include <mutex.h>
+
+static uint32_t atomic_exchange(uint32_t* ptr, uint32_t newval) {
+ uint32_t r;
+ asm volatile("xchg (%%ecx), %%eax" : "=a"(r) : "c"(ptr), "a"(newval));
+ return r;
+}
+
+void mutex_lock(uint32_t* mutex) {
+ while (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) {
+ thread_sleep(1);
+ }
+}
+
+int mutex_lockE(uint32_t* mutex) {
+ if (atomic_exchange(mutex, MUTEX_LOCKED) == MUTEX_LOCKED) return 0;
+ return 1;
+}
+
+void mutex_unlock(uint32_t* mutex) {
+ *mutex = MUTEX_UNLOCKED;
+}