diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2021-11-07 14:33:18 -0500 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2021-11-07 14:33:18 -0500 |
commit | 7991b36c56f4361fee92a4a03c3b3d640c8e7f98 (patch) | |
tree | 9b5adfaeeb1bd388ce16c8a135ee404ab2bc64d0 | |
parent | eab94d413c3202d2e21a7b5ca2e6ada9a8d85a94 (diff) | |
download | modit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.tar.gz modit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.tar.bz2 modit-slim-7991b36c56f4361fee92a4a03c3b3d640c8e7f98.zip |
theoretical model for rpc communication
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | app/init/Makefile | 2 | ||||
-rw-r--r-- | app/init/main.c | 7 | ||||
-rw-r--r-- | app/init/rpcsrv.c | 73 | ||||
-rw-r--r-- | app/init/rpcsrv.h | 6 | ||||
-rw-r--r-- | app/init/scheduler.c | 2 | ||||
-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.c | 11 | ||||
-rw-r--r-- | lib/c/string/strcpy.c | 10 | ||||
-rw-r--r-- | lib/c/string/strlen.c | 9 | ||||
-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.c | 10 | ||||
-rw-r--r-- | lib/c/sys/msg_get.c | 19 | ||||
-rw-r--r-- | lib/c/sys/msg_recv.c | 23 | ||||
-rw-r--r-- | lib/c/sys/msg_send.c | 11 | ||||
-rw-r--r-- | lib/c/sys/port.c | 54 | ||||
-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.s | 19 | ||||
-rw-r--r-- | lib/rpc/Makefile | 17 | ||||
-rw-r--r-- | lib/rpc/call.c | 112 | ||||
-rw-r--r-- | lib/rpc/define.c | 17 | ||||
-rw-r--r-- | lib/rpc/export.c | 39 | ||||
-rw-r--r-- | lib/rpc/getarg.c | 27 | ||||
-rw-r--r-- | lib/rpc/handle.c | 58 | ||||
-rw-r--r-- | lib/rpc/rpc.c | 16 | ||||
-rw-r--r-- | root/usr/include/rpc/api.h | 32 | ||||
-rw-r--r-- | root/usr/include/rpc/rpc.h | 63 | ||||
-rw-r--r-- | root/usr/include/string.h | 9 | ||||
-rw-r--r-- | root/usr/include/sys/cid.h | 3 | ||||
-rw-r--r-- | root/usr/include/sys/ipc.h | 31 | ||||
-rw-r--r-- | root/usr/include/sys/port.h | 6 | ||||
-rw-r--r-- | tools/patches/gcc.patch | 2 |
39 files changed, 691 insertions, 14 deletions
@@ -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}" |