diff --git a/kernel/Makefile b/kernel/Makefile index f33dd8d..9dd1361 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -60,6 +60,8 @@ SRCFILES += $(call GRABSRC, \ flanterm/src/flanterm_backends \ syscall \ path \ + rbuf \ + ipc/pipe \ ) ifeq ($(ARCH),x86_64) diff --git a/kernel/ipc/pipe/pipe.c b/kernel/ipc/pipe/pipe.c new file mode 100644 index 0000000..b18a0dc --- /dev/null +++ b/kernel/ipc/pipe/pipe.c @@ -0,0 +1,47 @@ +#include +#include +#include "rbuf/rbuf.h" +#include "spinlock/spinlock.h" +#include "hal/hal.h" +#include "dlmalloc/malloc.h" +#include "errors.h" +#include "pipe.h" + +int32_t ipc_pipeinit(IpcPipe *pipe) { + hal_memset(pipe, 0, sizeof(*pipe)); + spinlock_init(&pipe->spinlock); + pipe->rbuf.buffer = dlmalloc(IPC_PIPE_MAX); + if (pipe->rbuf.buffer == NULL) { + return E_NOMEMORY; + } + pipe->rbuf.cap = IPC_PIPE_MAX; + return E_OK; +} + +void ipc_pipefree(IpcPipe *pipe) { + dlfree(pipe->rbuf.buffer); +} + +int32_t ipc_pipewrite(IpcPipe *pipe, const uint8_t *const buffer, size_t n) { + size_t i = 0; + spinlock_acquire(&pipe->spinlock); + for (; i < n; i++) { + if (rbuf_push(&pipe->rbuf, buffer[i]) < 0) { + break; + } + } + spinlock_release(&pipe->spinlock); + return i; +} + +int32_t ipc_piperead(IpcPipe *pipe, uint8_t *const buffer, size_t n) { + size_t i = 0; + spinlock_acquire(&pipe->spinlock); + for (; i < n; i++) { + if (rbuf_pop(&pipe->rbuf, &buffer[i]) < 0) { + break; + } + } + spinlock_release(&pipe->spinlock); + return i; +} diff --git a/kernel/ipc/pipe/pipe.h b/kernel/ipc/pipe/pipe.h new file mode 100644 index 0000000..0b883cf --- /dev/null +++ b/kernel/ipc/pipe/pipe.h @@ -0,0 +1,21 @@ +#ifndef IPC_PIPE_PIPE_H_ +#define IPC_PIPE_PIPE_H_ + +#include +#include +#include "rbuf/rbuf.h" +#include "spinlock/spinlock.h" + +#define IPC_PIPE_MAX 0x1000 + +typedef struct { + RBuf rbuf; + SpinLock spinlock; +} IpcPipe; + +int32_t ipc_pipeinit(IpcPipe *pipe); +void ipc_pipefree(IpcPipe *pipe); +int32_t ipc_pipewrite(IpcPipe *pipe, const uint8_t *const buffer, size_t n); +int32_t ipc_piperead(IpcPipe *pipe, uint8_t *const buffer, size_t n); + +#endif // IPC_PIPE_PIPE_H_ diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 0289034..e30c9d3 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -12,6 +12,7 @@ #include "errors.h" #include "vfs/vfs.h" #include "bootinfo/bootinfo.h" +#include "ipc/pipe/pipe.h" #define PROC_REAPER_FREQ 30 @@ -162,6 +163,9 @@ Proc *proc_spawnuser(char *mountpoint, char *path) { proc->state = PROC_READY; proc->pid = pids++; + proc->pipes[0] = dlmalloc(sizeof(IpcPipe)); + ipc_pipeinit(proc->pipes[0]); + return proc; } @@ -201,6 +205,14 @@ void proc_reaper(void) { } } + for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) { + if (zombie->pipes[i] != NULL) { + dlfree(zombie->pipes[i]); + ipc_pipefree(zombie->pipes[i]); + zombie->pipes[i] = NULL; + } + } + pmm_free((uintptr_t)(zombie->platformdata.kstack - PROC_STACKSIZE), PROC_STACKBLOCKS); if (!zombie->kern) { @@ -278,16 +290,31 @@ void proc_status(void) { } } +Proc *init_proc = NULL; +#define PIPEREADER_BUF_SIZE 100 + +void proc_init_pipereader(void) { + char buf[PIPEREADER_BUF_SIZE]; + hal_memset(buf, 0, sizeof(buf)); + for (;;) { + int32_t read = ipc_piperead(init_proc->pipes[0], buf, PIPEREADER_BUF_SIZE); + kprintf("%.*s", read, buf); + hal_memset(buf, 0, sizeof(buf)); + } +} + void proc_init(void) { spinlock_init(&PROCS.spinlock); PROCS.procs = NULL; - Proc *idle = proc_spawnkern(&proc_idle, "kIDLE"); + Proc *idle = proc_spawnkern(&proc_idle, "k-idle"); proc_register(idle); PROCS.current = idle; /* proc_register(proc_spawnkern(&proc_status, "status")); */ - proc_register(proc_spawnuser("base", "/bin/init")); + init_proc = proc_spawnuser("base", "/bin/init"); + proc_register(init_proc); + proc_register(proc_spawnkern(&proc_init_pipereader, "k-init-pipereader")); hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); } diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 6e67f34..aababaf 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -6,6 +6,7 @@ #include "spinlock/spinlock.h" #include "bitmap/bitmap.h" #include "vfs/vfs.h" +#include "ipc/pipe/pipe.h" #define PROC_NAME_MAX 0x100 @@ -13,7 +14,9 @@ #define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE) #define PROC_MAX 0x100 // max amount of processes -#define PROC_VFSHANDLES_MAX 0x80 + +#define PROC_VFSHANDLES_MAX 0x80 +#define PROC_PIPEHANDLES_MAX 0x20 typedef struct { IntrStackFrame trapframe; @@ -42,6 +45,8 @@ typedef struct Proc { VfsObj *vobjs[PROC_VFSHANDLES_MAX]; uint64_t vobjcnt; + + IpcPipe *pipes[PROC_PIPEHANDLES_MAX]; } Proc; typedef struct { diff --git a/kernel/rbuf/rbuf.c b/kernel/rbuf/rbuf.c new file mode 100644 index 0000000..cf2241f --- /dev/null +++ b/kernel/rbuf/rbuf.c @@ -0,0 +1,37 @@ +#include +#include +#include "rbuf.h" + +int32_t rbuf_push(RBuf *rbuf, uint8_t data) { + size_t next; + + next = rbuf->head + 1; + if (next >= rbuf->cap) { + next = 0; + } + + if (next == rbuf->tail) { + return -1; + } + + rbuf->buffer[rbuf->head] = data; + rbuf->head = next; + return 0; +} + +int32_t rbuf_pop(RBuf *rbuf, uint8_t *data) { + size_t next; + + if (rbuf->head == rbuf->tail) { + return -1; + } + + next = rbuf->tail + 1; + if (next >= rbuf->cap) { + next = 0; + } + + *data = rbuf->buffer[rbuf->tail]; + rbuf->tail = next; + return 0; +} diff --git a/kernel/rbuf/rbuf.h b/kernel/rbuf/rbuf.h new file mode 100644 index 0000000..5f1aa3c --- /dev/null +++ b/kernel/rbuf/rbuf.h @@ -0,0 +1,17 @@ +#ifndef RBUF_RBUF_H_ +#define RBUF_RBUF_H_ + +#include +#include + +typedef struct { + uint8_t *buffer; + size_t head; + size_t tail; + size_t cap; +} RBuf; + +int32_t rbuf_push(RBuf *rbuf, uint8_t data); +int32_t rbuf_pop(RBuf *rbuf, uint8_t *data); + +#endif // RBUF_RBUF_H_ diff --git a/kernel/syscall/ipcpipe.c b/kernel/syscall/ipcpipe.c new file mode 100644 index 0000000..c698f58 --- /dev/null +++ b/kernel/syscall/ipcpipe.c @@ -0,0 +1,76 @@ +#include +#include +#include "ipcpipe.h" +#include "ipc/pipe/pipe.h" +#include "sysdefs/ipcpipe.h" +#include "dlmalloc/malloc.h" +#include "proc/proc.h" +#include "spinlock/spinlock.h" +#include "errors.h" +#include "util/util.h" + +int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { + uint64_t pid = pid1; + uint64_t pipenum = pipenum1; + uint64_t cmd = cmd1; + int32_t ret = E_OK; + + if (pid == -1) { + pid = PROCS.current->pid; + } + + spinlock_acquire(&PROCS.spinlock); + Proc *proc = NULL; + LL_FINDPROP(PROCS.procs, proc, pid, pid); + spinlock_release(&PROCS.spinlock); + + if (proc == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + switch (cmd) { + case IPCPIPE_MAKE: { + if (pipenum >= PROC_PIPEHANDLES_MAX) { + ret = E_NOMEMORY; + goto done; + } + + IpcPipe *pipe = dlmalloc(sizeof(*pipe)); + if (pipe == NULL) { + ret = E_NOMEMORY; + goto done; + } + + if ((ret = ipc_pipeinit(pipe)) < 0) { + goto done; + } + + proc->pipes[pipenum] = pipe; + + ret = E_OK; + } break; + case IPCPIPE_WRITE: { + if (pipenum >= PROC_PIPEHANDLES_MAX) { + ret = E_INVALIDARGUMENT; + goto done; + } + + const uint8_t *const buffer = (const uint8_t *const)buffer1; + if (buffer == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + IpcPipe *pipe = proc->pipes[pipenum]; + + ret = ipc_pipewrite(pipe, buffer, len1); + } break; + default: { + ret = E_INVALIDARGUMENT; + } break; + } + +done: + return ret; +} diff --git a/kernel/syscall/ipcpipe.h b/kernel/syscall/ipcpipe.h new file mode 100644 index 0000000..a757bf3 --- /dev/null +++ b/kernel/syscall/ipcpipe.h @@ -0,0 +1,8 @@ +#ifndef SYSCALL_IPCPIPE_H_ +#define SYSCALL_IPCPIPE_H_ + +#include "syscall.h" + +int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1); + +#endif // SYSCALL_IPCPIPE_H_ diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 7b6b6e5..696df84 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -5,6 +5,7 @@ #include "processctl.h" #include "sysdefs/syscall.h" #include "ioctl.h" +#include "ipcpipe.h" int32_t SYSCALL1(sys_debugprint, string) { char *p = (char *)string; @@ -16,4 +17,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = { [SYS_DEBUGPRINT] = &sys_debugprint, [SYS_PROCESSCTL] = &sys_processctl, [SYS_IOCTL] = &sys_ioctl, + [SYS_IPCPIPE] = &sys_ipcpipe, }; diff --git a/share/sysdefs/ipcpipe.h b/share/sysdefs/ipcpipe.h new file mode 100644 index 0000000..9f83e23 --- /dev/null +++ b/share/sysdefs/ipcpipe.h @@ -0,0 +1,16 @@ +#ifndef SHARE_SYSDEFS_IPCPIPE_H_ +#define SHARE_SYSDEFS_IPCPIPE_H_ + +#include +#include + +#define IPCPIPE_SELFPID (-1) +#define IPCPIPE_OUT (0) + +enum { + IPCPIPE_MAKE = 0, + IPCPIPE_READ = 1, + IPCPIPE_WRITE = 2, +}; + +#endif // SHARE_SYSDEFS_IPCPIPE_H_ diff --git a/share/sysdefs/syscall.h b/share/sysdefs/syscall.h index f28fc1b..23a3606 100644 --- a/share/sysdefs/syscall.h +++ b/share/sysdefs/syscall.h @@ -5,6 +5,7 @@ enum { SYS_DEBUGPRINT = 1, SYS_PROCESSCTL = 2, SYS_IOCTL = 3, + SYS_IPCPIPE = 4, }; #endif // SHARE_HDRS_SYSCALL_H_ diff --git a/ulib/system/ioctl.c b/ulib/system/ioctl.c index b772cea..1c303fb 100644 --- a/ulib/system/ioctl.c +++ b/ulib/system/ioctl.c @@ -2,7 +2,12 @@ #include #include #include -#include +#include +#include + +int32_t ioctl(uint64_t ioh, uint64_t cmd, void *extra) { + return syscall(SYS_IOCTL, ioh, cmd, (uint64_t)extra, 0, 0, 0); +} int32_t ioctl_openfile(const char *path, uint64_t flags) { IOCtlOF cfg = { .path = path, .flags = flags }; diff --git a/ulib/system/ioctl.h b/ulib/system/ioctl.h index 5edc011..00b4b20 100644 --- a/ulib/system/ioctl.h +++ b/ulib/system/ioctl.h @@ -4,6 +4,7 @@ #include #include +int32_t ioctl(uint64_t ioh, uint64_t cmd, void *extra); int32_t ioctl_openfile(const char *path, uint64_t flags); int32_t ioctl_writefile(int32_t ioh, const uint8_t *const buffer, size_t len, size_t off); int32_t ioctl_readfile(int32_t ioh, uint8_t *const buffer, size_t len, size_t off); diff --git a/ulib/system/ipcpipe.c b/ulib/system/ipcpipe.c new file mode 100644 index 0000000..7fd9b3b --- /dev/null +++ b/ulib/system/ipcpipe.c @@ -0,0 +1,10 @@ +#include +#include +#include "ipcpipe.h" +#include +#include +#include + +int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len) { + return syscall(SYS_IPCPIPE, pid, pipenum, cmd, (uint64_t)buffer, (uint64_t)len, 0); +} diff --git a/ulib/system/ipcpipe.h b/ulib/system/ipcpipe.h new file mode 100644 index 0000000..8f5c373 --- /dev/null +++ b/ulib/system/ipcpipe.h @@ -0,0 +1,9 @@ +#ifndef ULIB_SYSTEM_IPCPIPE_H_ +#define ULIB_SYSTEM_IPCPIPE_H_ + +#include +#include + +int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len); + +#endif // ULIB_SYSTEM_IPCPIPE_H_ diff --git a/ulib/system/processctl.c b/ulib/system/processctl.c new file mode 100644 index 0000000..85d81f6 --- /dev/null +++ b/ulib/system/processctl.c @@ -0,0 +1,8 @@ +#include +#include +#include +#include + +int32_t processctl(uint64_t pid, uint64_t cmd, void *extra) { + return syscall(SYS_PROCESSCTL, pid, cmd, (uint64_t)extra, 0, 0, 0); +} diff --git a/ulib/system/processctl.h b/ulib/system/processctl.h new file mode 100644 index 0000000..65fb002 --- /dev/null +++ b/ulib/system/processctl.h @@ -0,0 +1,6 @@ +#ifndef ULIB_SYSTEM_PROCESSCTL_H_ +#define ULIB_SYSTEM_PROCESSCTL_H_ + +int32_t processctl(uint64_t pid, uint64_t cmd, void *extra); + +#endif // ULIB_SYSTEM_PROCESSCTL_H_ diff --git a/ulib/system/system.c b/ulib/system/system.c index eded22d..ede79dd 100644 --- a/ulib/system/system.c +++ b/ulib/system/system.c @@ -7,11 +7,3 @@ void debugprint(const char *string) { syscall(SYS_DEBUGPRINT, (uint64_t)string, 0, 0, 0, 0, 0); } -int32_t processctl(uint64_t pid, uint64_t cmd, void *extra) { - return syscall(SYS_PROCESSCTL, pid, cmd, (uint64_t)extra, 0, 0, 0); -} - -int32_t ioctl(uint64_t ioh, uint64_t cmd, void *extra) { - return syscall(SYS_IOCTL, ioh, cmd, (uint64_t)extra, 0, 0, 0); -} - diff --git a/ulib/system/system.h b/ulib/system/system.h index 9a45337..11afe05 100644 --- a/ulib/system/system.h +++ b/ulib/system/system.h @@ -4,7 +4,5 @@ #include void debugprint(const char *string); -int32_t processctl(uint64_t pid, uint64_t cmd, void *extra); -int32_t ioctl(uint64_t ioh, uint64_t cmd, void *extra); #endif // ULIB_SYSTEM_SYSTEM_H_ diff --git a/user/init/main.c b/user/init/main.c index 664a8e1..c686006 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -1,8 +1,10 @@ #include -#include -#include -#include #include +#include +#include +#include +#include +#include void main(void) { debugprint("Hello world from userspace in C"); @@ -18,5 +20,10 @@ void main(void) { debugprint(buf); ioctl_closefile(ioh); + + char *aba = "Hello!"; + ipcpipe(IPCPIPE_SELFPID, IPCPIPE_OUT, IPCPIPE_WRITE, (uint8_t *)aba, string_len(aba)); + + for(;;); }