summaryrefslogtreecommitdiff
path: root/user
diff options
context:
space:
mode:
authorIan McFarlane <i.mcfarlane2002@gmail.com>2025-05-02 00:37:08 -0400
committerIan McFarlane <i.mcfarlane2002@gmail.com>2025-05-02 00:37:08 -0400
commit74c2b180769ef14ad42fe666207271bf344b11b9 (patch)
tree1957f4cdccc46b440898032f79350dfb113b19e4 /user
parentfmt (diff)
downloadcomus-74c2b180769ef14ad42fe666207271bf344b11b9.tar.gz
comus-74c2b180769ef14ad42fe666207271bf344b11b9.tar.bz2
comus-74c2b180769ef14ad42fe666207271bf344b11b9.zip
Add allocshared() and popsharedmem() syscalls
Diffstat (limited to 'user')
-rw-r--r--user/forkman.c121
-rw-r--r--user/include/unistd.h23
-rw-r--r--user/lib/syscall.S2
3 files changed, 146 insertions, 0 deletions
diff --git a/user/forkman.c b/user/forkman.c
new file mode 100644
index 0000000..fb5ae5f
--- /dev/null
+++ b/user/forkman.c
@@ -0,0 +1,121 @@
+/*
+ * FORKMAN: a platformer game with IPC
+ *
+ * This executable will fork. One process is responsible for writing to the
+ * screen and getting user input, the other is responsible for game logic.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define GAME_WIDTH 480
+#define GAME_HEIGHT 360
+#define SHARED_PAGES 10
+#define PAGE_SIZE 4096
+
+typedef struct {
+ uint32_t *mapped_memory;
+ int width;
+ int height;
+ int bpp;
+ int scale;
+ size_t size;
+} framebuffer;
+
+typedef struct {
+ volatile size_t frame;
+ volatile size_t dummy_counter;
+ volatile int lock;
+ volatile uint8_t mem[PAGE_SIZE * (SHARED_PAGES - 1)];
+} sharedmem;
+
+static int display_server_entry(sharedmem *);
+static int client_entry(sharedmem *);
+
+int main(void)
+{
+ uint8_t *current_break = sbrk(0);
+ if (!current_break) {
+ fprintf(stderr, "sbrk failure\n");
+ return 1;
+ }
+
+ printf("ABOUT TO FORK\n");
+
+ int child = fork();
+ if (child < 0) {
+ fprintf(stderr, "fork failed!\n");
+ return 1;
+ }
+
+ if (child) {
+ printf("FORK GOOD, CHILD IS %d\n", child);
+ sharedmem *shared = allocshared(SHARED_PAGES, child);
+ if (!shared) {
+ fprintf(stderr, "memory share failure\n");
+ return 1;
+ }
+
+ return display_server_entry(shared);
+ } else {
+ printf("FORK GOOD, WE ARE CHILD\n");
+
+ sharedmem *shared;
+
+ while (!(shared = popsharedmem()))
+ sleep(1);
+
+ return client_entry(shared);
+ }
+}
+
+static void set_pixel(framebuffer *fb, size_t x, size_t y,
+ int state) // state is 0 or 1
+{
+ fb->mapped_memory[x + y * fb->width] = state * (0x00010101);
+}
+
+static int display_server_entry(sharedmem *shared)
+{
+ framebuffer fb;
+ if (drm((void **)&fb.mapped_memory, &fb.width, &fb.height, &fb.bpp)) {
+ fprintf(stderr, "Unable to map framebuffer, display server failing\n");
+ return 1;
+ }
+
+ fb.size = (fb.width * fb.height * fb.bpp) / 8;
+
+ size_t last_frame = 1;
+
+ while (1) {
+ if (shared->frame == last_frame) {
+ continue;
+ }
+
+ printf("server writing frame %zu\n", last_frame);
+
+ last_frame += 1;
+ shared->frame = last_frame;
+ }
+
+ return 0;
+}
+
+static int client_entry(sharedmem *shared)
+{
+ size_t last_frame = shared->frame;
+ do {
+ if (last_frame == shared->frame)
+ continue;
+
+ printf("client writing frame %zu\n", last_frame);
+
+ last_frame += 1;
+ shared->frame = last_frame;
+ } while (1);
+
+ return 0;
+}
diff --git a/user/include/unistd.h b/user/include/unistd.h
index cad3a81..27b6d31 100644
--- a/user/include/unistd.h
+++ b/user/include/unistd.h
@@ -187,6 +187,29 @@ extern void *brk(const void *addr);
extern void *sbrk(intptr_t increment);
/**
+ * Allocate a number of pages shared with another PID. Does not map the pages
+ * into the other process's vtable until the other process calls popsharedmem().
+ *
+ * @param num_pages number of pages to allocate
+ * @param other_pid pid of other process
+ * @return pointer to the virtual address which will be accessible by both,
+ * after popsharedmem() is called.
+ */
+extern void* allocshared(size_t num_pages, int other_pid);
+
+/**
+ * Checks if another process has tried to share memory with us, and return it.
+ * No size information is returned, it is only guaranteed that there is at least
+ * one page in the shared allocation. To get around this, the sharer can write
+ * a size number to the start of the first page.
+ *
+ * @return page aligned pointer to the start of the shared pages, or NULL if no
+ * process has tried to share with us, or NULL if we the shared virtual address
+ * space is already occupied in the caller's pagetable.
+ */
+extern void* popsharedmem(void);
+
+/**
* Poweroff the system.
*
* @return 1 on failure
diff --git a/user/lib/syscall.S b/user/lib/syscall.S
index 2ba4dc0..9e050bc 100644
--- a/user/lib/syscall.S
+++ b/user/lib/syscall.S
@@ -27,3 +27,5 @@ SYSCALL sbrk SYS_sbrk
SYSCALL poweroff SYS_poweroff
SYSCALL drm SYS_drm
SYSCALL ticks SYS_ticks
+SYSCALL allocshared SYS_allocshared
+SYSCALL popsharedmem SYS_popsharedmem