Commit Diff


commit - 7b1f1314a4618908b79db56b86bae5c9306dc65f
commit + 4d7c062fbfa6373e41c75637079dd1a72c57f150
blob - 328bcaa3fc244f7ebb9b149b20ea0db74ae89291
blob + 47b91394c55e97eb3f122110d63b1915f8c86dcc
--- README
+++ README
@@ -27,10 +27,10 @@ memory (FDM) the program needs. The fake memory is add
 runtime. Hence, memory allocation is based on that memory
 chunk and not a syscall to request pages from the kernel.
 This will force you to tell how much RAM your program
-really needs instead of pretending to be lightweight. Hence,
-when a program does a `malloc` it takes a seat with the
-allocation server which reads the FDM and returns either the
-part needed or and error to say that there is no memory left.
+really needs instead of pretending to be lightweight. The
+memory block is handed at the entry point and the programs,
+thread has to manage it. There is no malloc, there is no
+free, you are on your own.
 
 The layout of the operating system image is :
 
@@ -68,6 +68,55 @@ threads. I call this the seat protocol.
 The Root Task (alpha) goal is to strip away the header and load
 executable in memory. Essentialy the root task is the loader.
 
+Opening a file: A text editor reserves a set amount of memory in
+its contract for viewport. A policy is made so he can request
+a driver to read the part needed from file and another file is
+opened to save history at a maximum amount of bytes.
+
+Tasks spawning other task is not done like unix fork. The way
+a task spawns another is is by cutting a part of its memory and
+requesting the root task to use it to create another one. For
+example, a windom manager could request a memory chunk of 512MB
+and use that 512 MB to spawn other tasks. This way resource
+exhaustion is impossible as the only resources used by the a
+task are his own.
+
+Filesystem: The filesystem is tag based, meaning that there are
+no directories, sub-directories, etc. Files are layout through
+tags and adding a file adds it to the tag. Doing something like
+tags in chell will give you a list. i.e:
+
+> #
+#home
+#games
+#system
+
+Accessing a file is done with for instance home:record.mkv
+
+Files can also have multiple tags. For instance
+
+> ::record.mkv
+
+#home
+#system
+
+Permissions are managed via groups and users just like in Unix.
+That was actually a good design so we keep it. You can do something
+like.
+
+> #home useradd nanga rwx
+> #home groupadd mygroup rwx
+
+When doing this it adds these to all objects with this tag. There
+are no directories, only tags and files.
+
+Basically
+
+#[Tags]:[Group/User]:[File]
+
+The file system server when started is fed by the root task the
+offset before reading the boot drive files.
+
 Features:
 
 - Buggy
blob - 2f9e39b4b18e87434300955e12d385bf415864ec
blob + f1b07c8fdf60905a2aaecad352ca1ff7f0c9d782
--- TODO
+++ TODO
@@ -1,14 +1,5 @@
-- kalloc and ualloc which checks if memory P_USER is set before
-  giving frames.
+- File System (tag based)
 
-- Add bss to module size for real binary sizes
-
-- Syscalls
-
-- IPC
-
-- File System
-
 - a.out executable format
 
 - PIC
@@ -16,6 +7,3 @@
 - Lua C449 compiler, assembler and linker
 
 - Rewrite in C449
-
-- Create ring buffer to allow asynchronous requests but drop on
-  full (no blocking or overwritting)
blob - 6574b6b771e87848e935b310dd24595b5227bcd1
blob + 2de5594659a2333bdff30deac6500e8780a602e7
--- alpha/libc.c
+++ alpha/libc.c
@@ -39,3 +39,32 @@ outputh(u64 i)
 	sysc.echo.number = i;
 	sys_send(&sysc);
 }
+
+void
+yield()
+{
+	struct sysc sysc;
+	sysc.type = SYSC_YIELD;
+	sys_send(&sysc);
+}
+
+u8*
+listen(u8 *block)
+{
+	struct sysc sysc;
+	sysc.type = SYSC_LISTEN;
+	sysc.listen.shared_block = block;
+	sys_send(&sysc);
+	return nil;
+}
+
+u8*
+seat(u64 threadid)
+{
+	struct sysc sysc;
+	sysc.type = SYSC_SEAT;
+	sysc.seat.threadid = threadid;
+	sysc.seat.ret_block = nil;
+	sys_send(&sysc);
+	return sysc.seat.ret_block;
+}
blob - e3c44299d8e2701bebb331312b659d8ccf0b5a63
blob + 84979facb56c87769474f78b410905a831d50d5b
--- alpha/libc.h
+++ alpha/libc.h
@@ -2,13 +2,17 @@
 
 #include "types.h"
 
-// Resources given to a thread on initialization
+#define MAX_SHARED_BUFFERS		24
+
+// Resources given to a thread on initialization. Dynamic memory allocation
+// does not exist hence don't expect malloc/calloc/realloc/free/etc. The
+// kernel hands your memory and you're on your own.
 struct contract {
 	u8 *memBlock; // This is guaranteed to be zero'd at entry point
 	u64 memSize;
 
-	u8 *sharedBlock; // Guaranteed to be zero'd at entry point as well
 	u64 sharedCount;
+	u8 *sharedBlocks[MAX_SHARED_BUFFERS];
 };
 
 // If you come from Unix-like this is kinda
@@ -20,4 +24,19 @@ void outputi(u64);
 
 void outputh(u64);
 
-// Memory allocation
+void yield(void); // Tells the OS to pause the thread until something wakes it up
+
+// Shared Blocks syscalls
+//
+// This sets of functions including yield() allows for communication between threads.
+// doing listen opens a seat for a sender and using yield after tells the kernel to
+// pause the thread and wakes it up if its buffer was written to. This allows for
+// non-blocking and blocking to be implemented without flags.
+
+u8 *seat(u64 thread_id);
+
+void getup(u64 seat_id);
+
+u64 speak(u8 *msg);
+
+u8 *listen(u8 *block); // Tells the OS to open the seat for a sender.
blob - 1a2e9694bafd83253434326ace1ffd76de2b7ae1
blob + d4a5bc809b1263c230055cff194d0832934ecd6b
--- alpha/main.c
+++ alpha/main.c
@@ -24,6 +24,7 @@ void
 alpha_main(struct mmap *km)
 {
 	struct task *t;
+	u8 *block = nil;
 	pci_init();
 
 	t = task_new((void *)XHCI_ENTRY);
@@ -32,6 +33,9 @@ alpha_main(struct mmap *km)
 		output("alpha: failed to create task!\n");
 
 	output("alpha: running\n");
+	while ((block = seat(t->thread)) == nil);
+	output("alpha: found a seat\n");
+	block[0] = 0x55;
 
 	for (;;);
 }
@@ -44,7 +48,7 @@ task_new(void *entry)
 	sysc.type = SYSC_NEW_THREAD;
 	sysc.new_thread.entry = entry;
 	sysc.new_thread.memsize = PAGE_SIZE;
-	sysc.new_thread.seats = 0;
+	sysc.new_thread.nseats = 1;
 
 	for (int i = 0; i < MAX_TASKS; i++) {
 		if (tasks[i].assigned == 0) {
blob - 4bbea456c1fc5e1c47816117ea97cf496fac0d68
blob + b1f53ded69a92ac0773586058d6d5b0783e71569
--- c449
+++ c449
@@ -52,6 +52,7 @@ defines a thread right away and that the root task can
 properly:
 
 thread 0;
+core 0;
 
 static u8 *name="First";
 
@@ -62,6 +63,7 @@ main()
 }
 
 thread 1;
+core 0;
 
 void
 main()
blob - 15ee22e44c08b1d58a85ee5ed5ae33d5294522ee
blob + 42b61e061e1a2e50515816aba016e6ecc8b18f25
--- kernel/idt.c
+++ kernel/idt.c
@@ -2,6 +2,7 @@
 #include "types.h"
 #include "kpic.h"
 #include "kthreads.h"
+#include "syscalls.h"
 
 #define APIC_EOI_REG ((volatile u32*)0xFEE000B0)
 
@@ -119,6 +120,8 @@ timer_handler_c()
 {
 	struct thread *next;
 
+	syscall_check_seats();
+
 	next = thread_next();
 
 	if (next != nil) {
blob - 5b711f5a26c269a6ec68fd7615236c460ef62d09
blob + 47337eab319ec3977f8806b72a51a4c7508e41f1
--- kernel/kpic.c
+++ kernel/kpic.c
@@ -67,7 +67,7 @@ static void
 apic_setup_timer()
 {
 	// Clock divider
-	*APIC_TIMER_DIV = 0x03;
+	*APIC_TIMER_DIV = 0x01;
 
 	// Setup register
 	*APIC_TIMER_LVT = APIC_LVT_PERIODIC | TIMER_VECTOR;
blob - f6fa1af4a7b0b7ba0d65afb136dece90e87f1654
blob + b6ffdf4fe737cc85c7e1aa463b2b93a93f7081fd
--- kernel/kthreads.c
+++ kernel/kthreads.c
@@ -3,6 +3,7 @@
 #include "kmmap.h"
 #include "kdebug.h"
 #include "kthreads.h"
+#include "syscalls.h"
 #include "libc.h"
 
 #define MAX_USER_THREADS	64
@@ -15,6 +16,7 @@ thread_create(void (*entry)(void), struct sysc_new_thr
 {
 	struct thread *thread = nil;
 	u64 *sp, usp;
+	u64 tid;
 
 	for (int i = 0; i < MAX_USER_THREADS; i++) {
 		struct thread *th = &uthreads[i];
@@ -22,6 +24,7 @@ thread_create(void (*entry)(void), struct sysc_new_thr
 		if (th->assigned == 0) {
 			th->assigned = 1;
 			thread = th;
+			tid = i;
 			break;
 		}
 	}
@@ -32,8 +35,12 @@ thread_create(void (*entry)(void), struct sysc_new_thr
 
 	thread->base = allocate_memory(PAGE_SIZE * 2);
 	thread->con->memBlock = nil;
+	thread->con->sharedCount = 0;
 	thread->con->memSize = 0;
 
+	for (int i = 0; i < MAX_SHARED_BUFFERS; i++)
+		thread->con->sharedBlocks[i] = nil;
+
 	if (thread->base == nil) {
 		thread->assigned = 0;
 		return nil;
@@ -43,8 +50,16 @@ thread_create(void (*entry)(void), struct sysc_new_thr
 		thread->con->memBlock = (u8 *)allocate_memory(nthread->memsize);
 		thread->con->memSize = nthread->memsize;
 
-		for (int i = 0; i < thread->con->memSize; i++)
-			thread->con->memBlock[i] = 0;
+		// Zero everything
+		if (nthread->memsize > 0) {
+			for (int i = 0; i < thread->con->memSize; i++)
+				thread->con->memBlock[i] = 0;
+		}
+
+		if (nthread->nseats > 0) {
+			for (int i = 0; i < nthread->nseats; i++)
+				seat_new(tid);
+		}
 	}
 
 	sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 2);
blob - 19fbabd1b9e9124fcbbe564306ffed98b5414247
blob + 237e566703ea9144a6cec990175303c4f4c6641f
--- kernel/kthreads.h
+++ kernel/kthreads.h
@@ -7,6 +7,7 @@
 enum thread_state {
 	THREAD_READY,
 	THREAD_RUNNING,
+	THREAD_YIELDING,
 };
 
 struct thread {
blob - af6e2abed99462469afc6841fd8300cd54b9c97c
blob + 1aee040fdee868f814c9300a4f6431f44d9c08ad
--- kernel/syscalls.c
+++ kernel/syscalls.c
@@ -4,13 +4,15 @@
 #include "kthreads.h"
 #include "syscalls/syscalls.h"
 
-#define MAX_SEATS	256
+#define MAX_SEATS	24
 #define MAX_SYSC_QUEUE	64
 #define THREADID_NONE	-1
 
 struct seatmap {
 	s64 send; // Sender Thread
 	s64 recv; // Receiver Thread
+	u8 *buff;
+	u8 open;
 };
 
 static struct seatmap seatmaps[MAX_SEATS];
@@ -19,9 +21,18 @@ static u8 *sbuffers;
 s8
 seat_new(u64 threadid)
 {
+	struct thread *thread = thread_get_uthread(threadid);
+
 	for (int i = 0; i < MAX_SEATS; i++) {
 		if (seatmaps[i].recv == THREADID_NONE) {
+			thread->con->sharedBlocks[thread->con->sharedCount++] = seatmaps[i].buff;
 			seatmaps[i].recv = threadid;
+
+			// Zero'd
+			for (int j = 0; j < PAGE_SIZE; j++)
+				seatmaps[i].buff[j] = 0;
+
+			kprint("Shared block mapped to thread(id="); kprinti(threadid); kprint(")\n");
 			return 0;
 		}
 	}
@@ -47,6 +58,7 @@ void syscall_init()
 	for (int i = 0; i < MAX_SEATS; i++) {
 		seatmaps[i].send = THREADID_NONE;
 		seatmaps[i].recv = THREADID_NONE;
+		seatmaps[i].buff = sbuffers + (i * PAGE_SIZE);
 	}
 
 	// movabs rax, addr
@@ -91,14 +103,6 @@ syscall_new_thread_h(struct sysc *call)
 	if (th == nil)
 		kprint("failed to create thread from syscall!\n");
 
-	/*
-	if (seat_new(threadid) == -1) {
-		kprint("Failed to create new seat\n");
-		repeat:
-			goto repeat;
-	}
-	*/
-
 	threadid = thread_getuid(th);
 	nthread->ret_id = threadid;
 	th->state = THREAD_RUNNING;
@@ -107,6 +111,29 @@ syscall_new_thread_h(struct sysc *call)
 }
 
 void
+sysc_listen_h(struct sysc_listen *listen)
+{
+	for (int i = 0; i < MAX_SEATS; i++) {
+		if (listen->shared_block == seatmaps[i].buff) {
+			seatmaps[i].open = 1;
+			return;
+		}
+	}
+}
+
+void
+sysc_seat_h(struct sysc_seat *sysc_seat)
+{
+	for (int i = 0; i < MAX_SEATS; i++) {
+		if (sysc_seat->threadid == seatmaps[i].recv && seatmaps[i].open == 1) {
+			sysc_seat->ret_block = seatmaps[i].buff;
+			seatmaps[i].send = thread_getuid(cthread);
+			break;
+		}
+	}
+}
+
+void
 syscall_handler(struct sysc *call)
 {
 	switch (call->type) {
@@ -116,7 +143,32 @@ syscall_handler(struct sysc *call)
 	case SYSC_NEW_THREAD:
 		syscall_new_thread_h(call);
 		break;
+	case SYSC_YIELD:
+		cthread->state = THREAD_YIELDING;
+		while (cthread->state != THREAD_RUNNING);
+		break;
+	case SYSC_LISTEN:
+		sysc_listen_h(&call->listen);
+		break;
+	case SYSC_SEAT:
+		sysc_seat_h(&call->seat);
+		break;
 	default:
 		break;
 	}
 }
+
+
+void
+syscall_check_seats()
+{
+	for (int i = 0; i < MAX_SEATS; i++) {
+		struct seatmap *map = &seatmaps[i];
+
+		if (map->open == 1 && map->recv != THREADID_NONE && map->send != THREADID_NONE) {
+			struct thread *th = thread_get_uthread(map->recv);
+
+			if (map->buff[0] != 0) th->state = THREAD_RUNNING;
+		}
+	}
+}
blob - 95ffef1019aeafa48a48857106ea098ee698ec70
blob + 79963268d0622d014efb9531ad3f6aaee5af8213
--- kernel/syscalls.h
+++ kernel/syscalls.h
@@ -1,3 +1,5 @@
 #pragma once
 
 void syscall_init(void);
+s8 seat_new(u64 threadid);
+void syscall_check_seats(void);
blob - 355b272393886987af96ba873b5cab4a4589205e
blob + 9b5e3be626986c9a9b0d22f5a4d9aaeaebfb8046
--- servers/xhci/main.c
+++ servers/xhci/main.c
@@ -10,10 +10,12 @@ xhci_main(struct contract *con)
 {
 	output("xhci: running\n");
 
-	output("xhci: memory size is "); outputi(con->memSize);
-	output(" bytes\n");
+	output("xhci: listening\n");
+	listen(con->sharedBlocks[0]);
+	yield();
 
-	output("Memory block location is : "); outputh((u64)con->memBlock[0]); output("\n");
+	output("xhci: listen stop\n");
+	output("xhci: first byte of shared block is "); outputh(con->sharedBlocks[0][0]); output("\n");
 
 	for (;;);
 }
blob - 4814d52593d770131e8ced32171fbab5cca710de
blob + e8ba6f6be4b57f7df4b5a9b831a5e2d68e19acd0
--- syscalls/syscalls.h
+++ syscalls/syscalls.h
@@ -5,6 +5,9 @@
 
 enum sysc_type {
 	SYSC_ECHO,
+	SYSC_SEAT,
+	SYSC_YIELD,
+	SYSC_LISTEN,
 	SYSC_NEW_THREAD,
 	SYSC_FREE_THREAD,
 };
@@ -27,16 +30,28 @@ struct sysc_echo {
 struct sysc_new_thread {
 	void *entry; // Entry point
 	u64 memsize;
-	u64 seats;
+	u64 nseats;
 
 	s64 ret_id;
 };
 
+struct sysc_listen {
+	u8 *shared_block;
+};
+
+struct sysc_seat {
+	u64 threadid;
+
+	u8 *ret_block;
+};
+
 struct sysc {
 	enum sysc_type type;
 	union {
 		struct sysc_echo echo;
 		struct sysc_new_thread new_thread;
+		struct sysc_listen listen;
+		struct sysc_seat seat;
 	};
 };