diff --git a/kernel/ipc/pipe/pipe.c b/kernel/ipc/pipe/pipe.c index b18a0dc..0e3b54e 100644 --- a/kernel/ipc/pipe/pipe.c +++ b/kernel/ipc/pipe/pipe.c @@ -7,9 +7,10 @@ #include "errors.h" #include "pipe.h" -int32_t ipc_pipeinit(IpcPipe *pipe) { +int32_t ipc_pipeinit(IpcPipe *pipe, uint64_t pid) { hal_memset(pipe, 0, sizeof(*pipe)); spinlock_init(&pipe->spinlock); + pipe->ownerpid = pid; pipe->rbuf.buffer = dlmalloc(IPC_PIPE_MAX); if (pipe->rbuf.buffer == NULL) { return E_NOMEMORY; @@ -19,7 +20,9 @@ int32_t ipc_pipeinit(IpcPipe *pipe) { } void ipc_pipefree(IpcPipe *pipe) { - dlfree(pipe->rbuf.buffer); + if (pipe->rbuf.buffer != NULL) { + dlfree(pipe->rbuf.buffer); + } } int32_t ipc_pipewrite(IpcPipe *pipe, const uint8_t *const buffer, size_t n) { diff --git a/kernel/ipc/pipe/pipe.h b/kernel/ipc/pipe/pipe.h index a039189..d1d6295 100644 --- a/kernel/ipc/pipe/pipe.h +++ b/kernel/ipc/pipe/pipe.h @@ -12,9 +12,10 @@ typedef struct IpcPipe { struct IpcPipe *next; RBuf rbuf; SpinLock spinlock; + uint64_t ownerpid; } IpcPipe; -int32_t ipc_pipeinit(IpcPipe *pipe); +int32_t ipc_pipeinit(IpcPipe *pipe, uint64_t pid); 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); diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 70836aa..f4d38e5 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -17,6 +17,7 @@ #include "ps2kbproc/ps2kbproc.h" #include "termproc/termproc.h" #include "serialproc/serialproc.h" +#include "sysdefs/processctl.h" #define PROC_REAPER_FREQ 30 @@ -99,9 +100,10 @@ Proc *proc_spawnkern(void (*ent)(void), char *name) { proc->platformdata.trapframe.cs = 0x08; proc->platformdata.trapframe.rip = (uint64_t)ent; proc->platformdata.cr3 = hal_vmm_current_cr3(); - proc->state = PROC_READY; + proc->state = PROC_EMBRYO; proc->pid = pids++; spinlock_init(&proc->bcast_pipes.spinlock); + spinlock_init(&proc->pipes_spinlock); return proc; } @@ -165,9 +167,15 @@ Proc *proc_spawnuser(char *mountpoint, char *path) { proc->platformdata.trapframe.rflags = 0x202; proc->platformdata.trapframe.cs = 0x18 | 0x3; proc->platformdata.trapframe.rip = aux.entry; - proc->state = PROC_READY; + proc->state = PROC_EMBRYO; proc->pid = pids++; spinlock_init(&proc->bcast_pipes.spinlock); + spinlock_init(&proc->pipes_spinlock); + + proc->pipes[0] = dlmalloc(sizeof(IpcPipe)); + ipc_pipeinit(proc->pipes[0], proc->pid); + proc->pipes[1] = dlmalloc(sizeof(IpcPipe)); + ipc_pipeinit(proc->pipes[1], proc->pid); return proc; } @@ -184,7 +192,7 @@ Proc *proc_nextready(void) { if (proc == NULL) { proc = PROCS.procs; } - if (proc->state != PROC_ZOMBIE) { + if (proc->state == PROC_READY) { return proc; } proc = proc->next; @@ -209,7 +217,7 @@ void proc_reaper(void) { } for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) { - if (zombie->pipes[i] != NULL) { + if (zombie->pipes[i] != NULL && zombie->pipes[i]->ownerpid == zombie->pid) { dlfree(zombie->pipes[i]); ipc_pipefree(zombie->pipes[i]); zombie->pipes[i] = NULL; @@ -255,7 +263,6 @@ void proc_sched(void *cpustate) { PROCS.current->platformdata.trapframe = *frame; PROCS.current = proc_nextready(); - PROCS.current->state = PROC_RUNNING; hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); } @@ -294,19 +301,25 @@ void proc_init(void) { kproc_init(proc_spawnkern(&kproc_fn, "kproc")); proc_register(KPROC); PROCS.current = KPROC; + KPROC->state = PROC_READY; ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); proc_register(PS2KBPROC); + PS2KBPROC->state = PROC_READY; termproc_init(proc_spawnkern(&termproc_fn, "termproc")); proc_register(TERMPROC); + TERMPROC->state = PROC_READY; - serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); - proc_register(SERIALPROC); + /* serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); */ + /* proc_register(SERIALPROC); */ Proc *init = proc_spawnuser("base", "/bin/init"); + ipc_pipefree(init->pipes[0]); + dlfree(init->pipes[0]); init->pipes[0] = TERMPROC->pipes[1]; proc_register(init); + init->state = PROC_READY; hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); } diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index f7841be..abdf333 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -25,10 +25,10 @@ typedef struct { } ProcPlatformData; enum { - PROC_READY, - PROC_RUNNING, - PROC_ZOMBIE, - PROC_WAITING, + PROC_EMBRYO = 0, + PROC_READY = 1, + PROC_ZOMBIE = 2, + PROC_WAITING = 3, }; typedef struct Proc { @@ -46,6 +46,7 @@ typedef struct Proc { VfsObj *vobjs[PROC_VFSHANDLES_MAX]; uint64_t vobjcnt; IpcPipe *pipes[PROC_PIPEHANDLES_MAX]; + SpinLock pipes_spinlock; struct { IpcPipe *list; SpinLock spinlock; diff --git a/kernel/proc/serialproc/serialproc.c b/kernel/proc/serialproc/serialproc.c index 36650cb..98d3de8 100644 --- a/kernel/proc/serialproc/serialproc.c +++ b/kernel/proc/serialproc/serialproc.c @@ -12,9 +12,9 @@ Proc *SERIALPROC; void serialproc_init(Proc *proc) { SERIALPROC = proc; SERIALPROC->pipes[0] = dlmalloc(sizeof(IpcPipe)); - ipc_pipeinit(SERIALPROC->pipes[0]); + ipc_pipeinit(SERIALPROC->pipes[0], SERIALPROC->pid); SERIALPROC->pipes[1] = dlmalloc(sizeof(IpcPipe)); - ipc_pipeinit(SERIALPROC->pipes[1]); + ipc_pipeinit(SERIALPROC->pipes[1], SERIALPROC->pid); io_out8(SERIAL_PORT + 1, 0x00); io_out8(SERIAL_PORT + 3, 0x80); @@ -56,7 +56,10 @@ void serialproc_fn(void) { for (;;) { hal_memset(buf, 0, sizeof(buf)); - int32_t read = ipc_piperead(SERIALPROC->pipes[1], (uint8_t *)buf, sizeof(buf)); + spinlock_acquire(&SERIALPROC->pipes_spinlock); + IpcPipe *inpipe = SERIALPROC->pipes[1]; + spinlock_release(&SERIALPROC->pipes_spinlock); + int32_t read = ipc_piperead(inpipe, (uint8_t *)buf, sizeof(buf)); if (read > 0) { for (size_t i = 0; i < sizeof(buf); i++) { serialproc_write(buf[i]); @@ -68,6 +71,9 @@ void serialproc_fn(void) { } uint8_t inchar = io_in8(SERIAL_PORT); - ipc_pipewrite(SERIALPROC->pipes[0], &inchar, sizeof(inchar)); + spinlock_acquire(&SERIALPROC->pipes_spinlock); + IpcPipe *outpipe = SERIALPROC->pipes[0]; + spinlock_release(&SERIALPROC->pipes_spinlock); + ipc_pipewrite(outpipe, &inchar, sizeof(inchar)); } } diff --git a/kernel/proc/termproc/termproc.c b/kernel/proc/termproc/termproc.c index 7167029..5fd31d3 100644 --- a/kernel/proc/termproc/termproc.c +++ b/kernel/proc/termproc/termproc.c @@ -4,20 +4,24 @@ #include "kprintf.h" #include "hal/hal.h" #include "dlmalloc/malloc.h" +#include "spinlock/spinlock.h" Proc *TERMPROC; void termproc_init(Proc *proc) { TERMPROC = proc; TERMPROC->pipes[1] = dlmalloc(sizeof(IpcPipe)); - ipc_pipeinit(TERMPROC->pipes[1]); + ipc_pipeinit(TERMPROC->pipes[1], TERMPROC->pid); } void termproc_fn(void) { char buf[100]; for (;;) { hal_memset(buf, 0, sizeof(buf)); - int32_t read = ipc_piperead(TERMPROC->pipes[1], (uint8_t *)buf, sizeof(buf)); + spinlock_acquire(&TERMPROC->pipes_spinlock); + IpcPipe *inpipe = TERMPROC->pipes[1]; + spinlock_release(&TERMPROC->pipes_spinlock); + int32_t read = ipc_piperead(inpipe, (uint8_t *)buf, sizeof(buf)); if (read > 0) { kprintf("%.*s", read, buf); } diff --git a/kernel/syscall/ipcpipe.c b/kernel/syscall/ipcpipe.c index 2e55789..b8dc6de 100644 --- a/kernel/syscall/ipcpipe.c +++ b/kernel/syscall/ipcpipe.c @@ -43,12 +43,14 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { goto done; } - if ((ret = ipc_pipeinit(pipe)) < 0) { + if ((ret = ipc_pipeinit(pipe, proc->pid)) < 0) { ret = E_NOMEMORY; goto done; } + spinlock_acquire(&proc->pipes_spinlock); proc->pipes[pipenum] = pipe; + spinlock_release(&proc->pipes_spinlock); ret = E_OK; } break; @@ -64,7 +66,9 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { goto done; } + spinlock_acquire(&proc->pipes_spinlock); IpcPipe *pipe = proc->pipes[pipenum]; + spinlock_release(&proc->pipes_spinlock); if (pipe == NULL) { ret = E_INVALIDARGUMENT; @@ -85,7 +89,9 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { goto done; } + spinlock_acquire(&proc->pipes_spinlock); IpcPipe *pipe = proc->pipes[pipenum]; + spinlock_release(&proc->pipes_spinlock); if (pipe == NULL) { ret = E_INVALIDARGUMENT; @@ -100,7 +106,9 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { goto done; } + spinlock_acquire(&proc->pipes_spinlock); IpcPipe *pipe = proc->pipes[pipenum]; + spinlock_release(&proc->pipes_spinlock); if (pipe == NULL) { ret = E_INVALIDARGUMENT; @@ -125,6 +133,43 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { ret = E_OK; } break; + case IPCPIPE_REPLACE: { + if (pipenum >= PROC_PIPEHANDLES_MAX) { + ret = E_NOMEMORY; + goto done; + } + + uint64_t pid2 = buffer1; + uint64_t pipenum2 = len1; + + spinlock_acquire(&PROCS.spinlock); + Proc *proc2 = NULL; + LL_FINDPROP(PROCS.procs, proc2, pid, pid2); + spinlock_release(&PROCS.spinlock); + + if (proc2 == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + if (pipenum2 >= PROC_PIPEHANDLES_MAX) { + ret = E_NOMEMORY; + goto done; + } + + spinlock_acquire(&proc2->pipes_spinlock); + spinlock_acquire(&proc->pipes_spinlock); + + if (proc->pipes[pipenum] != NULL) { + ipc_pipefree(proc->pipes[pipenum]); + dlfree(proc->pipes[pipenum]); + proc->pipes[pipenum] = NULL; + } + proc->pipes[pipenum] = proc2->pipes[pipenum2]; + + spinlock_release(&proc->pipes_spinlock); + spinlock_release(&proc2->pipes_spinlock); + } break; default: { ret = E_INVALIDARGUMENT; } break; diff --git a/kernel/syscall/processctl.c b/kernel/syscall/processctl.c index af67751..dcbd365 100644 --- a/kernel/syscall/processctl.c +++ b/kernel/syscall/processctl.c @@ -5,13 +5,19 @@ #include "errors.h" #include "util/util.h" #include "sysdefs/processctl.h" +#include "vfs/vfs.h" +#include "path/path.h" +#include "kprintf.h" -int32_t SYSCALL3(sys_processctl, pid1, cmd1, optsptr1) { +#define PCTL_MP_MAX 0xff +#define PCTL_PATH_MAX VFS_PATH_MAX + +int32_t SYSCALL3(sys_processctl, pid1, cmd1, arg1) { uint64_t pid = pid1; uint64_t cmd = cmd1; int32_t ret = E_OK; - if (pid == -1) { + if (pid == (uint64_t)-1) { pid = PROCS.current->pid; } @@ -21,6 +27,10 @@ int32_t SYSCALL3(sys_processctl, pid1, cmd1, optsptr1) { spinlock_release(&PROCS.spinlock); if (proc == NULL) { + if (cmd == PCTL_POLLSTATE) { + ret = 2; + goto done; + } ret = E_INVALIDARGUMENT; goto done; } @@ -30,6 +40,36 @@ int32_t SYSCALL3(sys_processctl, pid1, cmd1, optsptr1) { proc_kill(proc); ret = E_DOSCHEDULING; } break; + case PCTL_SPAWN: { + const char *opath = (const char *)arg1; + + if (opath == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + char mp[PCTL_MP_MAX]; + char path[PCTL_PATH_MAX]; + + path_parse(opath, mp, path); + + Proc *newproc = proc_spawnuser(mp, path); + if (newproc == NULL) { + ret = E_NOMEMORY; + goto done; + } + proc_register(newproc); + ret = newproc->pid; + } break; + case PCTL_POLLSTATE: { + ret = proc->state; + } break; + case PCTL_RUN: { + proc->state = PROC_READY; + } break; + case PCTL_GETPID: { + ret = proc->pid; + } break; default: { ret = E_INVALIDARGUMENT; } break; diff --git a/kernel/syscall/processctl.h b/kernel/syscall/processctl.h index 2019498..b25d7be 100644 --- a/kernel/syscall/processctl.h +++ b/kernel/syscall/processctl.h @@ -4,6 +4,6 @@ #include #include "syscall.h" -int32_t SYSCALL3(sys_processctl, pid1, cmd1, optsptr1); +int32_t SYSCALL3(sys_processctl, pid1, cmd1, arg1); #endif // SYSCALL_PROCESSCTL_H_ diff --git a/share/sysdefs/ipcpipe.h b/share/sysdefs/ipcpipe.h index 6042bf4..f7f2760 100644 --- a/share/sysdefs/ipcpipe.h +++ b/share/sysdefs/ipcpipe.h @@ -14,6 +14,7 @@ enum { IPCPIPE_READ = 1, IPCPIPE_WRITE = 2, IPCPIPE_ADD_BCAST = 3, + IPCPIPE_REPLACE = 4, }; #endif // SHARE_SYSDEFS_IPCPIPE_H_ diff --git a/share/sysdefs/processctl.h b/share/sysdefs/processctl.h index 1efadc2..ef2b726 100644 --- a/share/sysdefs/processctl.h +++ b/share/sysdefs/processctl.h @@ -2,7 +2,11 @@ #define SHARE_HDRS_PROCESSCTL_H_ enum { - PCTL_KILL = 0, + PCTL_KILL = 0, + PCTL_SPAWN = 1, + PCTL_POLLSTATE = 2, + PCTL_RUN = 3, + PCTL_GETPID = 4, }; #endif // SHARE_HDRS_PROCESSCTL_H_ diff --git a/ulib/system/system.c b/ulib/system/system.c index 3a253f9..981783e 100644 --- a/ulib/system/system.c +++ b/ulib/system/system.c @@ -11,8 +11,8 @@ int32_t ioctl(uint64_t ioh, uint64_t cmd, uint64_t arg1, uint64_t arg2, uint64_t return syscall(SYS_IOCTL, ioh, cmd, arg1, arg2, arg3, 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 processctl(uint64_t pid, uint64_t cmd, uint64_t arg1) { + return syscall(SYS_PROCESSCTL, pid, cmd, arg1, 0, 0, 0); } int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len) { diff --git a/ulib/system/system.h b/ulib/system/system.h index fca7be5..8ce2f3f 100644 --- a/ulib/system/system.h +++ b/ulib/system/system.h @@ -6,7 +6,7 @@ void debugprint(const char *string); int32_t ioctl(uint64_t ioh, uint64_t cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3); -int32_t processctl(uint64_t pid, uint64_t cmd, void *extra); +int32_t processctl(uint64_t pid, uint64_t cmd, uint64_t arg1); int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, size_t len); #endif // ULIB_SYSTEM_SYSTEM_H_ diff --git a/user/init/main.c b/user/init/main.c index 314fc54..b448abd 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,11 @@ void main(void) { uprintf("Hello world using uprintf\n"); + int32_t tb = processctl(-1, PCTL_SPAWN, (uint64_t)"base:/bin/tb"); + ipcpipe(tb, IPCPIPE_OUT, IPCPIPE_REPLACE, (uint8_t *)(uint64_t)processctl(-1, PCTL_GETPID, 0), IPCPIPE_OUT); + processctl(tb, PCTL_RUN, 0); + while(processctl(tb, PCTL_POLLSTATE, 0) != 2); + if (ipcpipe(IPCPIPE_SELFPID, 10, IPCPIPE_MAKE, NULL, 0) < 0) { uprintf("failed to create 10th pipe\n"); } diff --git a/user/tb/.gitignore b/user/tb/.gitignore new file mode 100644 index 0000000..e4982ac --- /dev/null +++ b/user/tb/.gitignore @@ -0,0 +1,2 @@ +*.o +tb diff --git a/user/tb/Makefile b/user/tb/Makefile new file mode 100644 index 0000000..c712f0a --- /dev/null +++ b/user/tb/Makefile @@ -0,0 +1,24 @@ +include $(ROOT)/mk/grabsrc.mk +include ../Makefile.inc + +.PHONY: all clean + +TARGET := tb + +LDFLAGS += -L$(ROOT)/ulib -l:libulib.a + +SRCFILES := $(call GRABSRC, .) +CFILES := $(call GET_CFILES, $(SRCFILES)) +OBJ := $(call GET_OBJ, $(SRCFILES)) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(LD) $^ $(LDFLAGS) -o $@ + echo $$(realpath $(TARGET)) >> $(FILES) + +clean: + rm -f $(OBJ) $(TARGET) diff --git a/user/tb/main.c b/user/tb/main.c new file mode 100644 index 0000000..04ddc31 --- /dev/null +++ b/user/tb/main.c @@ -0,0 +1,5 @@ +#include + +void main(void) { + uprintf("Hello from tb!\n"); +}