summaryrefslogtreecommitdiff
path: root/stage3/fut
diff options
context:
space:
mode:
authorLizzy Fleckenstein <eliasfleckenstein@web.de>2022-10-06 16:45:17 +0200
committerLizzy Fleckenstein <eliasfleckenstein@web.de>2022-10-06 16:45:17 +0200
commitf8397815545adb7d0da36614e0065aa68453a2e4 (patch)
treea771f526970c6724b2511577dceece8783450a49 /stage3/fut
downloadcuddles-f8397815545adb7d0da36614e0065aa68453a2e4.tar.xz
Initial commit
Diffstat (limited to 'stage3/fut')
-rwxr-xr-xstage3/fut/linkgen.lua101
-rw-r--r--stage3/fut/os161
-rw-r--r--stage3/fut/process.c77
-rw-r--r--stage3/fut/sys_kern.c21
-rw-r--r--stage3/fut/sys_kern.h91
-rw-r--r--stage3/fut/sys_user.c36
-rw-r--r--stage3/fut/sys_user.h91
-rw-r--r--stage3/fut/yield.asm49
8 files changed, 627 insertions, 0 deletions
diff --git a/stage3/fut/linkgen.lua b/stage3/fut/linkgen.lua
new file mode 100755
index 0000000..f7a6d21
--- /dev/null
+++ b/stage3/fut/linkgen.lua
@@ -0,0 +1,101 @@
+#!/usr/bin/env lua
+--[[
+
+--- trigger warning: brain damage ---
+
+BOGUS DYNAMIC LINKING v69.420 by LIZZY FLECKENSTEIN
+
+How this works:
+⠀⠀⠀⠀⠀⢰⡿⠋⠁⠀⠀⠈⠉⠙⠻⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⢀⣿⠇⠀⢀⣴⣶⡾⠿⠿⠿⢿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⣀⣀⣸⡿⠀⠀⢸⣿⣇⠀⠀⠀⠀⠀⠀⠙⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⣾⡟⠛⣿⡇⠀⠀⢸⣿⣿⣷⣤⣤⣤⣤⣶⣶⣿⠇⠀⠀⠀⠀⠀⠀⠀⣀⠀⠀
+⢀⣿⠀⢀⣿⡇⠀⠀⠀⠻⢿⣿⣿⣿⣿⣿⠿⣿⡏⠀⠀⠀⠀⢴⣶⣶⣿⣿⣿⣆
+⢸⣿⠀⢸⣿⡇⠀⠀⠀⠀⠀⠈⠉⠁⠀⠀⠀⣿⡇⣀⣠⣴⣾⣮⣝⠿⠿⠿⣻⡟
+⢸⣿⠀⠘⣿⡇⠀⠀⠀⠀⠀⠀⠀⣠⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠉⠀
+⠸⣿⠀⠀⣿⡇⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠉⠀⠀⠀⠀
+⠀⠻⣷⣶⣿⣇⠀⠀⠀⢠⣼⣿⣿⣿⣿⣿⣿⣿⣛⣛⣻⠉⠁⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⢸⣿⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀
+⠀⠀⠀⠀⢸⣿⣀⣀⣀⣼⡿⢿⣿⣿⣿⣿⣿⡿⣿⣿⡿
+
+Amogus sus 😳 ((impassta))
+
+I FUCKING HATE TEH ANTICRIST!!!!
+WE GOT YOU SURROUNDEND, USE DYNAMIC LINKING
+
+:trollface:
+
+]]
+
+-- in
+local hdr_kern = io.open("sys_kern.h", "r")
+-- out
+local hdr_user = io.open("sys_user.h", "w")
+local src_kern = io.open("sys_kern.c", "w")
+local src_user = io.open("sys_user.c", "w")
+
+local count = 0
+local calltable = "0x500"
+
+local body_kern = ""
+local body_user = ""
+
+src_kern:write("#include <sys_kern.h>\n")
+src_user:write("#include <sys_user.h>\n\n")
+
+local function process_line(line)
+ if line == "" or line:sub(1, 1) == "\t" then
+ return
+ end
+
+ local f, t = line:find("[%w_]+%(")
+
+ if not f then
+ return
+ end
+
+ local start, mid, fin = line:sub(1, f-1), line:sub(f, t-1), line:sub(t)
+
+ if mid == "__attribute__" or mid == "link" then
+ return
+ end
+
+ local decl = start .. "(*" .. mid .. ")" .. fin .. "\n"
+
+ hdr_user:write("extern " .. decl)
+ src_user:write(decl)
+
+ body_kern = body_kern .. "\tcalltable[" .. count .. "] = &" .. mid .. ";\n"
+ body_user = body_user .. "\t" .. mid .. " = calltable[" .. count .. "];\n"
+
+ count = count + 1
+
+ return true
+end
+
+while true do
+ local line = hdr_kern:read()
+
+ if not line then
+ break
+ end
+
+ if not process_line(line) then
+ hdr_user:write(line .. "\n")
+ end
+end
+
+local function write_link(f, content)
+ f:write("\nvoid link()\n{\n")
+ f:write("\tvoid **calltable = " .. calltable .. ";\n\n")
+ f:write(content)
+ f:write("}\n")
+end
+
+write_link(src_kern, body_kern)
+write_link(src_user, body_user)
+
+hdr_kern:close()
+hdr_user:close()
+src_kern:close()
+src_user:close()
diff --git a/stage3/fut/os b/stage3/fut/os
new file mode 100644
index 0000000..64d627f
--- /dev/null
+++ b/stage3/fut/os
@@ -0,0 +1,161 @@
+gfx
+ - modes text, pixel
+ - different buffers
+ - switch between them manually or thingily
+
+- similar to tmux
+- hierarchy
+
+- text input channel
+- keyboard input channel
+- mouse input channel
+
+- text output channel
+ -
+- graphics output channel
+
+- add text?
+- scrollback?
+
+init
+
+copy
+remove
+move
+list
+edit
+directory
+
+shell
+terminal
+
+mouse
+keyboard
+text
+
+tiler
+desktop
+
+--
+
+process, display, channel
+
+--
+
+display.x
+display.y
+display.width
+display.height
+display.index
+display.parent
+
+display = current_display()
+display = create_display(x, y, width, height)
+
+add_display(parent, child, -1)
+remove_display(parent, child)
+
+display.set_char(pos, color, text)
+display.set_pixel(pos, color)
+display.flush()
+
+channel = create_channel()
+add_channel(display, channel, name)
+channel = get_channel(display, name)
+
+--
+
+process = create_process(path, display)
+
+add_channel(process, channel)
+get_channel(process, "signal")
+get_channel(process, "status")
+
+--
+
+current_process()
+ .get_channel("status")
+ .send(finish)
+
+--
+void main()
+{
+ current_display()
+ .get_channel("text")
+ .send("hello, world\n");
+}
+
+--
+
+append(string self, string other)
+{
+ self.grow(other.len())
+ memcpy(self.ptr + self.len() - other.len(), other.ptr, other.len())
+}
+
+--
+string get_line(channel input)
+{
+ string s = "";
+
+ loop {
+ string c = input.recv();
+
+ if (c[0] == '\n')
+ break;
+
+ s.append(c);
+ }
+
+ return s;
+}
+
+--
+void main()
+{
+ channel input = current_display()
+ .get_channel("keyboard");
+
+ loop {
+ string command = get_line(input);
+
+ process proc = create_process(path, current_display());
+
+ receiver status = proc
+ .get_channel("status")
+ .subscribe();
+
+ proc.start();
+
+ while (!status.recv().equal("finish"))
+ yield();
+ }
+}
+
+--
+void main()
+{
+
+}
+
+-- channels
+void send(channel c, value v)
+{
+ listener l = c.listeners.pop();
+
+ if (l) {
+ listener.resume(v)
+ } else {
+ for (s in c.subscribers) {
+ if (s.active)
+ s.active.resume(v)
+ else
+ s.buffer.append(v)
+ }
+ }
+}
+
+-- queue
+
+- runqueue pointer at fixed address
+- processes must free all heap allocated memory before exit
diff --git a/stage3/fut/process.c b/stage3/fut/process.c
new file mode 100644
index 0000000..ea99ccf
--- /dev/null
+++ b/stage3/fut/process.c
@@ -0,0 +1,77 @@
+#define STACK_SIZE 65536
+#define CURRENT *((process *) 0x500)
+
+process process_current()
+{
+ return CURRENT;
+}
+
+static void process_delete(process p)
+{
+ free(p->stack);
+ free(p->code);
+ map_clear(&p->channels);
+}
+
+static void process_push(process p, u64 value)
+{
+ p->stack_ptr -= sizeof value;
+ *p->stack_ptr = value;
+}
+
+void process_exit()
+{
+ if (CURRENT->next == CURRENT)
+ panic("init exited");
+
+ CURRENT->prev->next = CURRENT->next;
+ CURRENT->next->prev = CURRENT->prev;
+ rc_drop(*current);
+
+ process_yield();
+}
+
+process process_create(char *path, display d)
+{
+ process p = rc_create(sizeof *p, &process_delete);
+
+ p->state = PROCESS_CREATED;
+
+ p->stack = malloc(STACK_SIZE);
+ p->stack_ptr = p->stack + STACK_SIZE;
+ p->code = p->code_ptr = file_read(path);
+
+ process_push(p, (u64) &process_exit);
+ // push 6 callee resaved registers - contents dont actually matter.
+ for (int i = 0; i < 6; i++)
+ process_push(p, 0);
+
+ p->displ = d;
+ p->next = p->prev = nil;
+ map_init(&p->channels);
+
+ channel sig = channel_create();
+ process_channel_add(p, "signal", sig);
+ rc_drop(sig);
+
+ channel stat = channel_create();
+ process_channel_add(p, "status", stat);
+ rc_drop(stat);
+
+ return p;
+}
+
+void process_start(process p)
+{
+ if (p->code_ptr == nil)
+ panic("attempt to start invalid process");
+
+ if (p->state != PROCESS_CREATED)
+ panic("attempt to start running or dead process");
+
+ rc_grab(p);
+
+ p->next = CURRENT->next;
+ CURRENT->next = p;
+ p->prev = CURRENT;
+}
diff --git a/stage3/fut/sys_kern.c b/stage3/fut/sys_kern.c
new file mode 100644
index 0000000..c7c5fcc
--- /dev/null
+++ b/stage3/fut/sys_kern.c
@@ -0,0 +1,21 @@
+#include <sys_kern.h>
+
+void link()
+{
+ void **calltable = 0x500;
+
+ calltable[0] = &display_current;
+ calltable[1] = &display_create;
+ calltable[2] = &display_add;
+ calltable[3] = &display_remove;
+ calltable[4] = &display_pixel;
+ calltable[5] = &display_channel_add;
+ calltable[6] = &display_channel_get;
+ calltable[7] = &rc_grab;
+ calltable[8] = &rc_drop;
+ calltable[9] = &rc_create;
+ calltable[10] = &weak_downgrade;
+ calltable[11] = &weak_upgrade;
+ calltable[12] = &weak_drop;
+ calltable[13] = &channel_create;
+}
diff --git a/stage3/fut/sys_kern.h b/stage3/fut/sys_kern.h
new file mode 100644
index 0000000..083fce3
--- /dev/null
+++ b/stage3/fut/sys_kern.h
@@ -0,0 +1,91 @@
+#ifndef _SYS_H_
+#define _SYS_H_
+
+// misc
+
+typedef struct {
+ i32 x, y;
+} pos;
+
+typedef struct {
+ u32 width, height;
+} bounds;
+
+typedef struct {
+ u8 r, g, b
+} color;
+
+// display
+
+typedef struct display {
+ pos p;
+ bounds b;
+ struct display *parent;
+ u64 index;
+} *display;
+
+display display_current();
+display display_create();
+void display_add(display parent, display child, i32 index);
+void display_remove(display child);
+
+void display_pixel(display d, pos p, color c);
+
+void display_channel_add(char *name, channel ch);
+channel display_channel_get(char *name);
+
+// rc
+
+typedef struct __attribute__((packed)) {
+ u32 ref;
+ u32 own;
+ void *data;
+ void (*delete)(void *data);
+} rc_header;
+
+void rc_grab(void *rc);
+void rc_drop(void *rc);
+
+void *rc_create(u64 siz, void *delete);
+void *weak_downgrade(void *rc);
+void *weak_upgrade(void *weak)
+void weak_drop(void *weak);
+
+// channel
+
+typedef struct {
+ array listeners;
+ array subscribers;
+} *channel;
+
+channel channel_create();
+
+// buffered
+
+typedef struct {
+ void *active;
+ array buffer;
+} buffered;
+
+// process
+
+typedef struct process __attribute__((packed)) {
+ void *code;
+ void *stack;
+ u64 *stack_ptr;
+ struct process *next;
+ struct process *prev;
+ map channels;
+ display displ;
+ enum {
+ PROCESS_CREATED,
+ PROCESS_RUNNING,
+ PROCESS_DEAD,
+ } state;
+} *process;
+
+// setup pointers
+
+void link();
+
+#endif
diff --git a/stage3/fut/sys_user.c b/stage3/fut/sys_user.c
new file mode 100644
index 0000000..4490513
--- /dev/null
+++ b/stage3/fut/sys_user.c
@@ -0,0 +1,36 @@
+#include <sys_user.h>
+
+display (*display_current)();
+display (*display_create)();
+void (*display_add)(display parent, display child, i32 index);
+void (*display_remove)(display child);
+void (*display_pixel)(display d, pos p, color c);
+void (*display_channel_add)(char *name, channel ch);
+channel (*display_channel_get)(char *name);
+void (*rc_grab)(void *rc);
+void (*rc_drop)(void *rc);
+void *(*rc_create)(u64 siz, void *delete);
+void *(*weak_downgrade)(void *rc);
+void *(*weak_upgrade)(void *weak)
+void (*weak_drop)(void *weak);
+channel (*channel_create)();
+
+void link()
+{
+ void **calltable = 0x500;
+
+ display_current = calltable[0];
+ display_create = calltable[1];
+ display_add = calltable[2];
+ display_remove = calltable[3];
+ display_pixel = calltable[4];
+ display_channel_add = calltable[5];
+ display_channel_get = calltable[6];
+ rc_grab = calltable[7];
+ rc_drop = calltable[8];
+ rc_create = calltable[9];
+ weak_downgrade = calltable[10];
+ weak_upgrade = calltable[11];
+ weak_drop = calltable[12];
+ channel_create = calltable[13];
+}
diff --git a/stage3/fut/sys_user.h b/stage3/fut/sys_user.h
new file mode 100644
index 0000000..3be3d58
--- /dev/null
+++ b/stage3/fut/sys_user.h
@@ -0,0 +1,91 @@
+#ifndef _SYS_H_
+#define _SYS_H_
+
+// misc
+
+typedef struct {
+ i32 x, y;
+} pos;
+
+typedef struct {
+ u32 width, height;
+} bounds;
+
+typedef struct {
+ u8 r, g, b
+} color;
+
+// display
+
+typedef struct display {
+ pos p;
+ bounds b;
+ struct display *parent;
+ u64 index;
+} *display;
+
+extern display (*display_current)();
+extern display (*display_create)();
+extern void (*display_add)(display parent, display child, i32 index);
+extern void (*display_remove)(display child);
+
+extern void (*display_pixel)(display d, pos p, color c);
+
+extern void (*display_channel_add)(char *name, channel ch);
+extern channel (*display_channel_get)(char *name);
+
+// rc
+
+typedef struct __attribute__((packed)) {
+ u32 ref;
+ u32 own;
+ void *data;
+ void (*delete)(void *data);
+} rc_header;
+
+extern void (*rc_grab)(void *rc);
+extern void (*rc_drop)(void *rc);
+
+extern void *(*rc_create)(u64 siz, void *delete);
+extern void *(*weak_downgrade)(void *rc);
+extern void *(*weak_upgrade)(void *weak)
+extern void (*weak_drop)(void *weak);
+
+// channel
+
+typedef struct {
+ array listeners;
+ array subscribers;
+} *channel;
+
+extern channel (*channel_create)();
+
+// buffered
+
+typedef struct {
+ void *active;
+ array buffer;
+} buffered;
+
+// process
+
+typedef struct process __attribute__((packed)) {
+ void *code;
+ void *stack;
+ u64 *stack_ptr;
+ struct process *next;
+ struct process *prev;
+ map channels;
+ display displ;
+ enum {
+ PROCESS_CREATED,
+ PROCESS_RUNNING,
+ PROCESS_DEAD,
+ } state;
+} *process;
+
+// setup pointers
+
+void link();
+
+#endif
diff --git a/stage3/fut/yield.asm b/stage3/fut/yield.asm
new file mode 100644
index 0000000..0c4a134
--- /dev/null
+++ b/stage3/fut/yield.asm
@@ -0,0 +1,49 @@
+global process_yield
+extern rc_drop
+
+%define CURRENT [0x500]
+
+section .text
+process_yield:
+ ; save callee reserved regs to old stack
+ push rbx
+ push rbp
+ push r12
+ push r13
+ push r14
+ push r15
+
+ ; get CURRENT
+ mov rdi, CURRENT
+
+ ; set CURRENT->stack_ptr
+ mov rax, rdi
+ add rax, 16
+ mov [rax], rsp
+
+ ; switch to new process
+ add rax, 8
+ mov rbx, [rax]
+ mov CURRENT, rbx
+
+ ; activate new stack
+ add rbx, 16
+ mov rsp, [rbx]
+
+ ; drop old process (=rdi)
+ call rc_drop
+
+ ; grab new process
+ mov rdi, CURRENT
+ call rc_grab
+
+ ; restore callee reserved registers
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop rbp
+ pop rbx
+
+ ; jump into new process, with style
+ ret