summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2021-11-07 14:33:18 -0500
committerJon Santmyer <jon@jonsantmyer.com>2021-11-07 14:33:18 -0500
commit7991b36c56f4361fee92a4a03c3b3d640c8e7f98 (patch)
tree9b5adfaeeb1bd388ce16c8a135ee404ab2bc64d0
parenteab94d413c3202d2e21a7b5ca2e6ada9a8d85a94 (diff)
downloadmodit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.tar.gz
modit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.tar.bz2
modit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.zip
theoretical model for rpc communication
-rw-r--r--Makefile2
-rw-r--r--app/init/Makefile2
-rw-r--r--app/init/main.c7
-rw-r--r--app/init/rpcsrv.c73
-rw-r--r--app/init/rpcsrv.h6
-rw-r--r--app/init/scheduler.c2
-rw-r--r--lib/c/Makefile (renamed from lib/mocksl/Makefile)0
-rw-r--r--lib/c/libc.c (renamed from lib/mocksl/mocksl.c)0
-rw-r--r--lib/c/stdlib/exit.c (renamed from lib/mocksl/stdlib/exit.c)0
-rw-r--r--lib/c/stdlib/heap.c (renamed from lib/mocksl/stdlib/heap.c)13
-rw-r--r--lib/c/stdlib/memcpy.c (renamed from lib/mocksl/stdlib/memcpy.c)0
-rw-r--r--lib/c/stdlib/memset.c (renamed from lib/mocksl/stdlib/memset.c)0
-rw-r--r--lib/c/string/strcmp.c11
-rw-r--r--lib/c/string/strcpy.c10
-rw-r--r--lib/c/string/strlen.c9
-rw-r--r--lib/c/sys/alloc.c (renamed from lib/mocksl/sys/alloc.c)0
-rw-r--r--lib/c/sys/fork.c (renamed from lib/mocksl/sys/fork.c)2
-rw-r--r--lib/c/sys/getcid.c10
-rw-r--r--lib/c/sys/msg_get.c19
-rw-r--r--lib/c/sys/msg_recv.c23
-rw-r--r--lib/c/sys/msg_send.c11
-rw-r--r--lib/c/sys/port.c54
-rw-r--r--lib/c/sys/settimer.c (renamed from lib/mocksl/sys/settimer.c)0
-rw-r--r--lib/c/sys/swapto.c (renamed from lib/mocksl/sys/swapto.c)0
-rw-r--r--lib/crt/x86/64/crt0.s19
-rw-r--r--lib/rpc/Makefile17
-rw-r--r--lib/rpc/call.c112
-rw-r--r--lib/rpc/define.c17
-rw-r--r--lib/rpc/export.c39
-rw-r--r--lib/rpc/getarg.c27
-rw-r--r--lib/rpc/handle.c58
-rw-r--r--lib/rpc/rpc.c16
-rw-r--r--root/usr/include/rpc/api.h32
-rw-r--r--root/usr/include/rpc/rpc.h63
-rw-r--r--root/usr/include/string.h9
-rw-r--r--root/usr/include/sys/cid.h3
-rw-r--r--root/usr/include/sys/ipc.h31
-rw-r--r--root/usr/include/sys/port.h6
-rw-r--r--tools/patches/gcc.patch2
39 files changed, 691 insertions, 14 deletions
diff --git a/Makefile b/Makefile
index f9ee698..b1e1d21 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,7 @@ initrd: tools/$(ARCH)_$(BITS) apps Makefile
.PHONY: apps
apps: libs
@for app in ${APPS} ; do \
- $(MAKE) -C $$app ARCH=$(ARCH) BITS=$(BITS) CC=$(CC) LD=$(LD) AS=$(AS) AR=$(AR) INCDIR=$(PWD)/root/usr/include OUTDIR=$(PWD)/initrd ; \
+ $(MAKE) -C $$app ARCH=$(ARCH) BITS=$(BITS) CC=$(CC) LD=$(LD) AS=$(AS) AR=$(AR) INCDIR=$(PWD)/root/usr/include LIBDIR=$(PWD)/root/lib OUTDIR=$(PWD)/initrd ; \
done
.PHONY: libs
diff --git a/app/init/Makefile b/app/init/Makefile
index c5afb94..f7345f1 100644
--- a/app/init/Makefile
+++ b/app/init/Makefile
@@ -9,4 +9,4 @@ OUT := init
.PHONY: all
all: $(CFILES)
- $(CC) $(CFLAGS) $(CFILES) -o $(OUTDIR)/init
+ $(CC) $(CFLAGS) $(CFILES) $(LIBDIR)/librpc.a -o $(OUTDIR)/init
diff --git a/app/init/main.c b/app/init/main.c
index 527a8a3..fde73c0 100644
--- a/app/init/main.c
+++ b/app/init/main.c
@@ -1,7 +1,12 @@
#include "scheduler.h"
+#include "rpcsrv.h"
+
#include "sys/cid.h"
+#include "sys/ipc.h"
#include "modit/syscall.h"
+#include <string.h>
+
DEFN_SYSCALL(print, SYSCALL_PRINT);
void prints(const char *msg) {
struct syscall_print_data data = { .msg = msg };
@@ -13,8 +18,8 @@ main(int argc, char **argv)
{
(void)argc;
(void)argv;
-
scheduler_setup();
+ rpcsrv_start();
while(1);
}
diff --git a/app/init/rpcsrv.c b/app/init/rpcsrv.c
new file mode 100644
index 0000000..4b3422b
--- /dev/null
+++ b/app/init/rpcsrv.c
@@ -0,0 +1,73 @@
+#include "rpcsrv.h"
+#include "rpc/rpc.h"
+#include <stdlib.h>
+#include <string.h>
+
+struct rpcsrv_entry {
+ char *name;
+ RPCFUNC *func;
+};
+
+static struct rpcsrv_entry *srv_entries;
+static size_t srv_entc;
+
+RPCFUNC*
+rpcs_find(const char *name)
+{
+ for(size_t i = 0; i < srv_entc; i++){
+ if(!strcmp(name, srv_entries[i].name)) {
+ return srv_entries[i].func;
+ }
+ }
+ return NULL;
+}
+
+intmax_t
+rpcs_import(struct rpc_args *args)
+{
+ char *name = rpc_getarg(args, char*);
+ RPCFUNC *func = rpcs_find(name);
+
+ if(func != NULL) {
+ rpc_returnvlv(func, sizeof(RPCFUNC) + strlen(func->expects));
+ }
+ rpc_returnvlv(NULL, 0);
+}
+
+intmax_t
+rpcs_export(struct rpc_args *args)
+{
+ char *name = rpc_getarg(args, char*);
+ struct rpc_vlvpack *funcpk = rpc_getarg(args, struct rpc_vlvpack*);
+
+ //Make sure rpcs aren't overwritten
+ RPCFUNC *exists = rpcs_find(name);
+ if(exists) return -1;
+
+ //Expand srv_entries list, adding copy to list
+ struct rpcsrv_entry *tmp = malloc(sizeof(struct rpcsrv_entry) * (rpcc + 1));
+ memcpy(tmp, srv_entries, sizeof(struct rpcsrv_entry) * rpcc);
+ free(srv_entries);
+ srv_entries = tmp;
+
+ exists = malloc(funcpk->len);
+ memcpy(exists, funcpk->data, funcpk->len);
+
+ srv_entries[rpcc].func = exists;
+ srv_entries[rpcc].name = malloc(strlen(name));
+ strcpy(srv_entries[rpcc].name, name);
+ rpcc++;
+
+ return rpcc - 1;
+}
+
+void
+rpcsrv_start(void)
+{
+ srv_entries = NULL;
+ srv_entc = 0;
+
+ rpc_export_internal(rpc_define(0, 0, "s", 'v'), rpcs_import);
+ rpc_export_internal(rpc_define(0, 1, "sv", 'i'), rpcs_export);
+ rpc_handle(false);
+}
diff --git a/app/init/rpcsrv.h b/app/init/rpcsrv.h
new file mode 100644
index 0000000..8e3ce2d
--- /dev/null
+++ b/app/init/rpcsrv.h
@@ -0,0 +1,6 @@
+#ifndef INIT_RPCSRV_H
+#define INIT_RPCSRV_H 1
+
+void rpcsrv_start(void);
+
+#endif
diff --git a/app/init/scheduler.c b/app/init/scheduler.c
index f4f2f2c..f573c99 100644
--- a/app/init/scheduler.c
+++ b/app/init/scheduler.c
@@ -49,7 +49,7 @@ scheduler_loop(void)
void
scheduler_setup(void)
{
- cid_t forked = fork();
+ cid_t forked = fork_ghost();
if(forked != 0) {
swapto(forked);
return;
diff --git a/lib/mocksl/Makefile b/lib/c/Makefile
index a81e0e7..a81e0e7 100644
--- a/lib/mocksl/Makefile
+++ b/lib/c/Makefile
diff --git a/lib/mocksl/mocksl.c b/lib/c/libc.c
index 4da0ca1..4da0ca1 100644
--- a/lib/mocksl/mocksl.c
+++ b/lib/c/libc.c
diff --git a/lib/mocksl/stdlib/exit.c b/lib/c/stdlib/exit.c
index e52518b..e52518b 100644
--- a/lib/mocksl/stdlib/exit.c
+++ b/lib/c/stdlib/exit.c
diff --git a/lib/mocksl/stdlib/heap.c b/lib/c/stdlib/heap.c
index 56de88c..a535e40 100644
--- a/lib/mocksl/stdlib/heap.c
+++ b/lib/c/stdlib/heap.c
@@ -150,6 +150,19 @@ malloc(size_t size)
}
void
+free(void *ptr)
+{
+ if(ptr == NULL) return;
+ //Search blocklist for address at token
+ for(struct bucket *bucket = bucket_tail; bucket; bucket = bucket->next) {
+ if(bucket->addr == (uintptr_t)ptr) {
+ bucket->flags &= (~1);
+ return;
+ }
+ }
+}
+
+void
__stdlib_heap_init(void)
{
//Match pbrk to page boundary (so it's cleaner for granularity sake)
diff --git a/lib/mocksl/stdlib/memcpy.c b/lib/c/stdlib/memcpy.c
index 877f51b..877f51b 100644
--- a/lib/mocksl/stdlib/memcpy.c
+++ b/lib/c/stdlib/memcpy.c
diff --git a/lib/mocksl/stdlib/memset.c b/lib/c/stdlib/memset.c
index d0a7b5b..d0a7b5b 100644
--- a/lib/mocksl/stdlib/memset.c
+++ b/lib/c/stdlib/memset.c
diff --git a/lib/c/string/strcmp.c b/lib/c/string/strcmp.c
new file mode 100644
index 0000000..8eba631
--- /dev/null
+++ b/lib/c/string/strcmp.c
@@ -0,0 +1,11 @@
+#include <string.h>
+
+int
+strcmp(const char *s1, const char *s2)
+{
+ size_t i;
+ for(i = 0; s1[i]; i++) {
+ if(s1[i] != s2[i]) return s1[i] - s2[i];
+ }
+ return s1[i] - s2[i];
+}
diff --git a/lib/c/string/strcpy.c b/lib/c/string/strcpy.c
new file mode 100644
index 0000000..696c332
--- /dev/null
+++ b/lib/c/string/strcpy.c
@@ -0,0 +1,10 @@
+#include "string.h"
+
+char *
+strcpy(char *restrict dest, const char *src)
+{
+ size_t i = 0;
+ for(; src[i]; i++) dest[i] = src[i];
+ dest[i] = 0;
+ return dest;
+}
diff --git a/lib/c/string/strlen.c b/lib/c/string/strlen.c
new file mode 100644
index 0000000..646f080
--- /dev/null
+++ b/lib/c/string/strlen.c
@@ -0,0 +1,9 @@
+#include <string.h>
+
+size_t
+strlen(const char *s)
+{
+ size_t l = 0;
+ while(s[l++]);
+ return l;
+}
diff --git a/lib/mocksl/sys/alloc.c b/lib/c/sys/alloc.c
index 4212026..4212026 100644
--- a/lib/mocksl/sys/alloc.c
+++ b/lib/c/sys/alloc.c
diff --git a/lib/mocksl/sys/fork.c b/lib/c/sys/fork.c
index 8e68051..6792fe7 100644
--- a/lib/mocksl/sys/fork.c
+++ b/lib/c/sys/fork.c
@@ -6,7 +6,7 @@
DEFN_SYSCALL(fork, SYSCALL_FORK)
cid_t
-fork(void)
+fork_ghost(void)
{
return _syscall_fork(NULL);
}
diff --git a/lib/c/sys/getcid.c b/lib/c/sys/getcid.c
new file mode 100644
index 0000000..8650504
--- /dev/null
+++ b/lib/c/sys/getcid.c
@@ -0,0 +1,10 @@
+#include "sys/cid.h"
+#include "modit/syscall.h"
+
+DEFN_SYSCALL(cid, SYSCALL_CID)
+
+cid_t
+getcid(void)
+{
+ return _syscall_cid(NULL);
+}
diff --git a/lib/c/sys/msg_get.c b/lib/c/sys/msg_get.c
new file mode 100644
index 0000000..6410293
--- /dev/null
+++ b/lib/c/sys/msg_get.c
@@ -0,0 +1,19 @@
+#include "sys/ipc.h"
+
+cid_t
+msg_getsender(MESSAGE *msg)
+{
+ return msg->sender;
+}
+
+size_t
+msg_getlen(MESSAGE *msg)
+{
+ return msg->len;
+}
+
+unsigned char *
+msg_getdata(MESSAGE *msg)
+{
+ return msg->data;
+}
diff --git a/lib/c/sys/msg_recv.c b/lib/c/sys/msg_recv.c
new file mode 100644
index 0000000..27dcf55
--- /dev/null
+++ b/lib/c/sys/msg_recv.c
@@ -0,0 +1,23 @@
+#include "sys/ipc.h"
+#include "modit/syscall.h"
+
+#include <stdlib.h>
+
+DEFN_SYSCALL(message_recv, SYSCALL_MESSAGE_RECV)
+
+MESSAGE *
+msg_recv(void)
+{
+ struct syscall_message_data data = { .buffer = NULL };
+ size_t len = _syscall_message_recv(&data);
+ int r = 0;
+
+ MESSAGE *msg = malloc(sizeof(MESSAGE) + len);
+ data.buffer = msg->data;
+ r = _syscall_message_recv(&data);
+
+ msg->sender = data.tgt;
+ msg->len = len;
+
+ return msg;
+}
diff --git a/lib/c/sys/msg_send.c b/lib/c/sys/msg_send.c
new file mode 100644
index 0000000..65b5336
--- /dev/null
+++ b/lib/c/sys/msg_send.c
@@ -0,0 +1,11 @@
+#include "sys/ipc.h"
+#include "modit/syscall.h"
+
+DEFN_SYSCALL(message_send, SYSCALL_MESSAGE_SEND)
+
+int
+msg_send(cid_t target, const void *data, size_t len)
+{
+ struct syscall_message_data msgd = {.tgt = target, .buffer = data, .len = len };
+ return _syscall_message_send(&msgd);
+}
diff --git a/lib/c/sys/port.c b/lib/c/sys/port.c
new file mode 100644
index 0000000..8fe5cc6
--- /dev/null
+++ b/lib/c/sys/port.c
@@ -0,0 +1,54 @@
+#include "sys/ipc.h"
+#include "modit/syscall.h"
+#include <stdlib.h>
+
+DEFN_SYSCALL(port_open, SYSCALL_PORT_OPEN)
+DEFN_SYSCALL(port_close, SYSCALL_PORT_CLOSE)
+DEFN_SYSCALL(port_clear, SYSCALL_PORT_CLEAR)
+DEFN_SYSCALL(port_read, SYSCALL_PORT_READ)
+DEFN_SYSCALL(port_write, SYSCALL_PORT_WRITE)
+
+PORT *
+port_open(cid_t target)
+{
+ PORT *port = NULL;
+ struct syscall_port_data data = { .tgt = target };
+ int id = _syscall_port_open(&data);
+
+ if(id < 0) return NULL;
+ port = malloc(sizeof(struct port));
+ port->target = target;
+ port->id = id;
+ return port;
+}
+
+void
+port_close(PORT *port)
+{
+ struct syscall_port_data data = { .id = port->id };
+ _syscall_port_close(&data);
+ free(port);
+}
+
+int
+port_write(PORT *port, const void *data, size_t len)
+{
+ struct syscall_port_data pd = { .id = port->id, .buffer = data, .len = len };
+ return _syscall_port_write(&pd);
+}
+
+int
+port_peek(PORT *port, void *buffer, size_t len)
+{
+ struct syscall_port_data pd = { .id = port->id, .buffer = buffer, .len = len };
+ return _syscall_port_read(&pd);
+}
+
+int
+port_read(PORT *port, void *buffer, size_t len)
+{
+ struct syscall_port_data pd = { .id = port->id, .buffer = buffer, .len = len };
+ int r = _syscall_port_read(&pd);
+ _syscall_port_clear(&pd);
+ return r;
+}
diff --git a/lib/mocksl/sys/settimer.c b/lib/c/sys/settimer.c
index 5dbb853..5dbb853 100644
--- a/lib/mocksl/sys/settimer.c
+++ b/lib/c/sys/settimer.c
diff --git a/lib/mocksl/sys/swapto.c b/lib/c/sys/swapto.c
index a0b4181..a0b4181 100644
--- a/lib/mocksl/sys/swapto.c
+++ b/lib/c/sys/swapto.c
diff --git a/lib/crt/x86/64/crt0.s b/lib/crt/x86/64/crt0.s
index cf6cbec..dbba387 100644
--- a/lib/crt/x86/64/crt0.s
+++ b/lib/crt/x86/64/crt0.s
@@ -2,27 +2,32 @@
.global _start
_start:
+ //Setup stack frame linked list
xor %rbp, %rbp
- #Save argc, argv
+ pushq %rbp
+ pushq %rbp
+ movq %rsp, %rbp
+
+ //Save argc, argv
pushq %rsi
pushq %rdi
- #Setup mocksl (argc=rdi, argv=rsi, envp=rdx)
+ //Setup mocksl (argc=rdi, argv=rsi, envp=rdx)
call __init_mocksl
- #Call constructors
+ //Call constructors
call _init
- #Restore args for main
+ //Restore args for main
popq %rdi
popq %rsi
- #Start program (argc=rdi, argv=rsi)
+ //Start program (argc=rdi, argv=rsi)
call main
- #Move result to argument
+ //Move result to argument
movq %rax, %rdi
- #Exit program (state=rdi)
+ //Exit program (state=rdi)
call exit
.size _start, . - _start
diff --git a/lib/rpc/Makefile b/lib/rpc/Makefile
new file mode 100644
index 0000000..76df3d1
--- /dev/null
+++ b/lib/rpc/Makefile
@@ -0,0 +1,17 @@
+CFILES := $(wildcard *.c)
+CFILES += $(wildcard */*.c)
+
+OBJFILES := $(patsubst %.c,%.o,$(CFILES))
+
+CC ?= gcc
+AR ?= ar
+
+WARNS := -Wall -Wextra -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -Wnull-dereference -Wdouble-promotion -Wshadow -Wcast-align
+CFLAGS := $(WARNS) -I$(INCDIR)
+
+.PHONY: all
+all: ${OBJFILES}
+ $(AR) rcs $(LIBDIR)/librpc.a ${OBJFILES}
+
+%.o:%.c
+ $(CC) $(CFLAGS) -c $< -o $@
diff --git a/lib/rpc/call.c b/lib/rpc/call.c
new file mode 100644
index 0000000..a1407f8
--- /dev/null
+++ b/lib/rpc/call.c
@@ -0,0 +1,112 @@
+#include "rpc/rpc.h"
+#include "rpc/api.h"
+#include "sys/ipc.h"
+#include <stdlib.h>
+#include <string.h>
+
+int
+marshall(const char *fmt, char *buffer, va_list ap)
+{
+ int size = 0;
+ for(const char *c = fmt; *c; c++) {
+ intmax_t val;
+ intmax_t vallen;
+ switch(*c) {
+ case 'b':
+ val = va_arg(ap, char);
+ vallen = 1;
+ break;
+ case 'w':
+ val = va_arg(ap, short);
+ vallen = 2;
+ break;
+ case 'i':
+ val = va_arg(ap, int);
+ vallen = 4;
+ break;
+ case 'l':
+ val = va_arg(ap, long);
+ vallen = 8;
+ break;
+ }
+ if(*c == 's') {
+ val = (intmax_t)va_arg(ap, char*);
+ vallen = strlen((const char*)val);
+ if(buffer != NULL) strcpy(&buffer[size], (char*)val);
+ size += vallen;
+ }else if(*c == 'v') {
+ vallen = va_arg(ap, size_t);
+ val = (intmax_t)va_arg(ap, unsigned char*);
+ if(buffer != NULL) {
+ memcpy(&buffer[size], &vallen, sizeof(size_t));
+ memcpy(&buffer[size + sizeof(size_t)], (void*)val, vallen);
+ }
+ size += vallen + sizeof(size_t);
+ }else{
+ if(buffer != NULL) memcpy(&buffer[size], &val, vallen);
+ size += vallen;
+ }
+ }
+ return size;
+}
+
+intmax_t
+rpc_call(RPCFUNC *func, ...)
+{
+ va_list ap;
+ va_start(ap, func);
+ intmax_t r = rpc_vcall(func, ap);
+ va_end(ap);
+ return r;
+}
+
+intmax_t
+rpc_vcall(RPCFUNC *func, va_list ap)
+{
+ //Marshall the arguments
+ va_list dummy;
+ va_copy(dummy, ap);
+ size_t marshalled_size = marshall(func->expects, NULL, dummy);
+
+ char *buffer = malloc(marshalled_size + sizeof(rpcid_t));
+ marshall(func->expects, buffer + sizeof(rpcid_t), ap);
+ memcpy(buffer, &func->id, sizeof(rpcid_t));
+
+ //Message reciever with id and arguments
+ msg_send(func->handler, buffer, marshalled_size + sizeof(rpcid_t));
+ free(buffer);
+
+ //Open port for result
+ PORT *resultport = port_open(func->handler);
+
+ //Read result
+ while(port_peek(resultport, NULL, 0) == 0);
+ size_t retsize = port_peek(resultport, NULL, 0);
+ buffer = malloc(retsize);
+ port_read(resultport, buffer, retsize);
+ port_close(resultport);
+
+ //Return result
+ intmax_t r = 0;
+ int rlen = 0;
+ switch(func->returns) {
+ case 'b': rlen = 1; break;
+ case 'w': rlen = 2; break;
+ case 'i': rlen = 4; break;
+ case 'q': rlen = 8; break;
+ }
+ if(func->returns == 's'){
+ return buffer;
+ }else if(func->returns == 'v') {
+ memcpy(&rlen, buffer, sizeof(size_t));
+ struct rpc_vlvpack *pack = malloc(sizeof(struct rpc_vlvpack) + rlen);
+ pack->len = rlen;
+ memcpy(pack->data, buffer + sizeof(size_t), rlen);
+ free(buffer);
+ return (intmax_t)pack;
+ }else {
+ memcpy(&r, buffer, rlen);
+ free(buffer);
+ return r;
+ }
+}
diff --git a/lib/rpc/define.c b/lib/rpc/define.c
new file mode 100644
index 0000000..a5df6ef
--- /dev/null
+++ b/lib/rpc/define.c
@@ -0,0 +1,17 @@
+#include "rpc/rpc.h"
+#include <stdlib.h>
+#include <string.h>
+#include "sys/cid.h"
+
+RPCFUNC*
+rpc_define(cid_t handler, rpcid_t id, const char *argtypes, char rettype)
+{
+ RPCFUNC *func = malloc(sizeof(RPCFUNC) + strlen(argtypes));
+ strcpy(func->expects, argtypes);
+
+ if(handler == 0) handler = getcid();
+ func->handler = handler;
+ func->returns = rettype;
+ func->id = id;
+ return func;
+}
diff --git a/lib/rpc/export.c b/lib/rpc/export.c
new file mode 100644
index 0000000..9cd8170
--- /dev/null
+++ b/lib/rpc/export.c
@@ -0,0 +1,39 @@
+#include "rpc/rpc.h"
+#include "rpc/api.h"
+#include "sys/cid.h"
+
+#include <stdlib.h>
+
+void
+rpc_export(RPCFUNC *func, const char *name, intmax_t (*handler)(struct rpc_args*))
+{
+ //Expand rpc handlers to fit new functions
+ struct rpc_handle *tmp = malloc(sizeof(struct rpc_handle) * (rpcc + 1));
+ memcpy(tmp, rpc_handles, sizeof(struct rpc_handle) * (rpcc));
+ free(rpc_handles);
+ rpc_handles = tmp;
+
+ //Add new RPCFUNC to handle
+ rpc_handles[rpcc].func = func;
+ rpc_handles[rpcc].handler = handler;
+ func->id = rpcc;
+
+ //Call init export RPC
+ rpc_call(rpc_init_export, name, sizeof(RPCFUNC), func);
+ rpcc++;
+}
+
+void
+rpc_export_internal(RPCFUNC *func, intmax_t (*handler)(struct rpc_args*))
+{
+ //Expand rpc handlers to fit new functions
+ struct rpc_handle *tmp = malloc(sizeof(struct rpc_handle) * (rpcc + 1));
+ memcpy(tmp, rpc_handles, sizeof(struct rpc_handle) * (rpcc));
+ free(rpc_handles);
+ rpc_handles = tmp;
+
+ //Add new RPCFUNC to handle
+ rpc_handles[rpcc].func = func;
+ rpc_handles[rpcc].handler = handler;
+ func->id = rpcc++;
+}
diff --git a/lib/rpc/getarg.c b/lib/rpc/getarg.c
new file mode 100644
index 0000000..3704e10
--- /dev/null
+++ b/lib/rpc/getarg.c
@@ -0,0 +1,27 @@
+#include "rpc/rpc.h"
+#include <stdlib.h>
+#include <string.h>
+
+uintptr_t
+__rpc_getarg(struct rpc_args *args)
+{
+ char type = args->func->expects[args->arg++];
+ int typelen = 1;
+ void *data = args->data;
+
+ switch(type) {
+ case 'w': typelen = 2; break;
+ case 'i': typelen = 4; break;
+ case 'q': typelen = 8; break;
+ }
+ if(type == 's') {
+ args->data = (void*)((uintptr_t)args->data + strlen((char*)data));
+ return (uintptr_t)data;
+ }else if(type == 'v') {
+ typelen = *((uintptr_t*)data) + sizeof(size_t);
+ args->data = (void*)((uintptr_t)args->data + typelen);
+ return (uintptr_t)data;
+ }
+ args->data = (void*)((uintptr_t)args->data + typelen);
+ return *((uintptr_t*)data);
+}
diff --git a/lib/rpc/handle.c b/lib/rpc/handle.c
new file mode 100644
index 0000000..57a85cd
--- /dev/null
+++ b/lib/rpc/handle.c
@@ -0,0 +1,58 @@
+#include "rpc/rpc.h"
+#include "sys/cid.h"
+#include "sys/ipc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct rpc_message_packet
+{
+ rpcid_t id;
+ unsigned char data[];
+};
+
+static void
+rpc_handle_return(MESSAGE *msg, RPCFUNC *func, intmax_t r)
+{
+ PORT *retport = port_open(msg_getsender(msg));
+ switch(func->returns) {
+ case 'b': port_write(retport, &r, 1); return;
+ case 'w': port_write(retport, &r, 2); return;
+ case 'i': port_write(retport, &r, 4); return;
+ case 'q': port_write(retport, &r, 8); return;
+ }
+ if(func->returns == 's') {
+ port_write(retport, (char*)r, strlen((char*)r));
+ return;
+ }
+ struct rpc_vlvpack *pk = (struct rpc_vlvpack*)r;
+ port_write(retport, pk, pk->len + sizeof(size_t));
+ free(pk);
+}
+
+void
+rpc_handle(bool async)
+{
+ if(async) {
+ //TODO: Create un-ghost fork and call that to make call async
+ }
+
+ struct rpc_args *args = malloc(sizeof(struct rpc_args));
+ while(1) {
+ MESSAGE *msg = msg_recv();
+ struct rpc_message_packet *pkt = (struct rpc_message_packet*)msg_getdata(msg);
+
+ for(rpcid_t i = 0; i < rpcc; i++) {
+ struct rpc_handle *handle = &rpc_handles[i];
+ if(handle->func->id == pkt->id) {
+ args->func = handle->func;
+ args->arg = 0;
+ args->data = pkt->data;
+
+ rpc_handle_return(msg, handle->func, handle->handler(args));
+ break;
+ }
+ }
+ free(msg);
+ }
+}
diff --git a/lib/rpc/rpc.c b/lib/rpc/rpc.c
new file mode 100644
index 0000000..e637d64
--- /dev/null
+++ b/lib/rpc/rpc.c
@@ -0,0 +1,16 @@
+#include "stdlib.h"
+#include "rpc/rpc.h"
+#include "rpc/api.h"
+
+struct rpc_handle *rpc_handles = NULL;
+rpcid_t rpcc = 0;
+
+RPCFUNC *rpc_init_import;
+RPCFUNC *rpc_init_export;
+
+__attribute__((constructor))
+void rpc_constructor(void)
+{
+ rpc_init_import = rpc_define(1, RPC_INIT_IMPORT, "s", 'v');
+ rpc_init_export = rpc_define(1, RPC_INIT_EXPORT, "sv", 'i');
+}
diff --git a/root/usr/include/rpc/api.h b/root/usr/include/rpc/api.h
new file mode 100644
index 0000000..5b511e4
--- /dev/null
+++ b/root/usr/include/rpc/api.h
@@ -0,0 +1,32 @@
+#ifndef RPC_API_H
+#define RPC_API_H 1
+
+#include "rpc/rpc.h"
+#include <stdarg.h>
+
+#define RPC_INIT_IMPORT 0
+#define RPC_INIT_EXPORT 1
+
+#define RPC_IMPORT(name) \
+RPCFUNC *rpc_##name = NULL; \
+intmax_t rpc_func_##name (bool wait, ...) { \
+ if(rpc_##name == 0) { \
+ /*Get RPC data from init server*/ \
+ struct rpc_vlvpack *pack = (struct rpc_vlvpack*)rpc_call(rpc_init_import, #name); \
+ rpc_##name = (RPCFUNC*)pack->data; \
+ } \
+ va_list ap; \
+ va_start(ap, wait); \
+ /*TODO: Ignore result if wait is false */ \
+ intmax_t r = rpc_call(rpc_##name, ap); \
+ va_end(ap); \
+ return r; \
+}
+
+#define RPC_CALL(name, ...) \
+ rpc_func_##name(false, __VA_ARGS__);
+
+extern RPCFUNC *rpc_init_import;
+extern RPCFUNC *rpc_init_export;
+
+#endif
diff --git a/root/usr/include/rpc/rpc.h b/root/usr/include/rpc/rpc.h
new file mode 100644
index 0000000..509b243
--- /dev/null
+++ b/root/usr/include/rpc/rpc.h
@@ -0,0 +1,63 @@
+#ifndef RPC_H
+#define RPC_H 1
+
+#include "sys/cid.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#define RPC_TYPE_8 'b'
+#define RPC_TYPE_16 's'
+#define RPC_TYPE_32 'i'
+#define RPC_TYPE_64 'q'
+#define RPC_TYPE_STR 's'
+#define RPC_TYPE_VLV 'v'
+
+typedef intmax_t rpcid_t;
+
+struct rpc_vlvpack {
+ size_t len;
+ unsigned char data[];
+};
+
+typedef struct rpc_function {
+ rpcid_t id;
+ cid_t handler;
+ char returns;
+ char expects[];
+} RPCFUNC;
+
+struct rpc_args {
+ RPCFUNC *func;
+ int arg;
+ void *data;
+};
+
+struct rpc_handle {
+ RPCFUNC *func;
+ intmax_t (*handler)(struct rpc_args*);
+};
+
+extern rpcid_t rpcc;
+extern struct rpc_handle *rpc_handles;
+
+RPCFUNC *rpc_define(cid_t handler, rpcid_t id, const char *argtypes, char rettype);
+void rpc_export(RPCFUNC *func, const char *name, intmax_t (*handler)(struct rpc_args*));
+void rpc_export_internal(RPCFUNC *func, intmax_t (*handler)(struct rpc_args*));
+
+intmax_t rpc_call(RPCFUNC *func, ...);
+intmax_t rpc_vcall(RPCFUNC *func, va_list ap);
+
+uintptr_t __rpc_getarg(struct rpc_args *args);
+#define rpc_getarg(al, T) (T)__rpc_getarg(al)
+
+void rpc_handle(bool async);
+
+#define rpc_returnvlv(vlvdata, vlvlen) \
+ struct rpc_vlvpack *vlvpack = malloc((vlvlen) + sizeof(struct rpc_vlvpack)); \
+ vlvpack->len = vlvlen; \
+ if(vlvdata != NULL) memcpy(vlvpack->data, vlvdata, (vlvlen)); \
+ return (intmax_t)vlvpack
+
+#endif
diff --git a/root/usr/include/string.h b/root/usr/include/string.h
new file mode 100644
index 0000000..2e7f763
--- /dev/null
+++ b/root/usr/include/string.h
@@ -0,0 +1,9 @@
+#ifndef STRING_H
+#define STRING_H 1
+
+#include <stddef.h>
+
+size_t strlen(const char *s);
+char *strcpy(char *restrict dest, const char *src);
+
+#endif
diff --git a/root/usr/include/sys/cid.h b/root/usr/include/sys/cid.h
index 7d45277..af7899e 100644
--- a/root/usr/include/sys/cid.h
+++ b/root/usr/include/sys/cid.h
@@ -3,8 +3,9 @@
typedef int cid_t;
-cid_t fork(void);
+cid_t fork_ghost(void);
+cid_t getcid(void);
void settimer(int ms);
int swapto(cid_t target);
diff --git a/root/usr/include/sys/ipc.h b/root/usr/include/sys/ipc.h
new file mode 100644
index 0000000..981b83e
--- /dev/null
+++ b/root/usr/include/sys/ipc.h
@@ -0,0 +1,31 @@
+#ifndef SYS_IPC_H
+#define SYS_IPC_H 1
+
+#include "sys/cid.h"
+#include <stddef.h>
+
+typedef struct message {
+ cid_t sender;
+ size_t len;
+ unsigned char data[];
+} MESSAGE;
+
+typedef struct port {
+ cid_t target;
+ int id;
+} PORT;
+
+int msg_send(cid_t target, const void *data, size_t len);
+MESSAGE *msg_recv(void); //User is supposed to free resulting message
+
+cid_t msg_getsender(MESSAGE *msg);
+size_t msg_getlen(MESSAGE *msg);
+unsigned char *msg_getdata(MESSAGE *msg);
+
+PORT *port_open(cid_t target);
+void port_close(PORT *port);
+int port_write(PORT *port, const void *data, size_t len);
+int port_peek(PORT *port, void *buffer, size_t len);
+int port_read(PORT *port, void *buffer, size_t len);
+
+#endif
diff --git a/root/usr/include/sys/port.h b/root/usr/include/sys/port.h
new file mode 100644
index 0000000..45ee787
--- /dev/null
+++ b/root/usr/include/sys/port.h
@@ -0,0 +1,6 @@
+#ifndef SYS_PORT_H
+#define SYS_PORT_H 1
+
+
+
+#endif
diff --git a/tools/patches/gcc.patch b/tools/patches/gcc.patch
index 3bbfb4e..8ddf6b2 100644
--- a/tools/patches/gcc.patch
+++ b/tools/patches/gcc.patch
@@ -43,7 +43,7 @@ diff -rcN gcc/gcc/config/modit.h gcc-modified/gcc/config/modit.h
+ /* Default arguments you want when running your
+ * i686-modit-gcc/x86_64-modit-gcc toolchain */
+ #undef LIB_SPEC
-+ #define LIB_SPEC "-lc" /* link against c library */
++ #define LIB_SPEC "-lc -lrpc" /* link against c and rpc library */
+
+ #undef STARTFILE_SPEC
+ #define STARTFILE_SPEC "crt0.o%s crti.o%s %{!shared:crtbegin.o%s}"