diff --git a/kernel-src/include/kernel/proc.h b/kernel-src/include/kernel/proc.h new file mode 100644 index 00000000..bfcaeb80 --- /dev/null +++ b/kernel-src/include/kernel/proc.h @@ -0,0 +1,111 @@ +#ifndef _PROC_H +#define _PROC_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +typedef struct proc_t { + mutex_t mutex; + int refcount; + int status; + int state; + struct proc_t *sibling; + struct proc_t *parent; + struct proc_t *child; + pid_t pid; + cred_t cred; + spinlock_t threadlistlock; + thread_t *threadlist; + bool nomorethreads; + size_t runningthreadcount; + size_t fdcount; + uintmax_t fdfirst; + mutex_t fdmutex; + struct fd_t *fd; + mode_t umask; + int flags; + vnode_t *cwd; + vnode_t *root; + spinlock_t nodeslock; + semaphore_t waitsem; + spinlock_t exiting; + + spinlock_t jobctllock; + struct { + // NULL if this process is leader + struct proc_t *leader; + + // these are only applicable if the process is leader + struct proc_t *foreground; // process group leader, NULL if self + void *controllingtty; + } session; + + struct { + // NULL if this process is leader + struct proc_t *leader; + // linked list + struct proc_t *nextmember; + struct proc_t *previousmember; + + // these are only applicable if the process is leader + spinlock_t lock; // protects the linked list + } pgrp; + + struct { + spinlock_t lock; + sigaction_t actions[NSIG]; + sigset_t pending; + bool stopunwaited; + bool continueunwaited; + } signals; + + struct { + mutex_t mutex; + itimer_t realtime; + itimer_t virtualtime; + itimer_t profiling; + } timer; +} proc_t; + +#include + +#define UMASK(mode) ((mode) & ~current_thread()->proc->umask) +#define PROC_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) +// the acquire of the pid table mutex is done here to prevent a nasty race condition where sched_inactiveproc could be called multiple times +// due to the pid table itself not holding any references to the process +#define PROC_RELEASE(v) {\ + MUTEX_ACQUIRE(&proc_pid_table_mutex, false); \ + if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\ + proc_inactive(v); \ + (v) = NULL; \ + } \ + MUTEX_RELEASE(&proc_pid_table_mutex); \ + } + +extern proc_t *init_proc; +extern mutex_t proc_pid_table_mutex; + +proc_t *proc_get_from_pid(int pid); +proc_t *proc_create(void); +vnode_t *proc_get_cwd(void); +vnode_t *proc_get_root(void); +void proc_set_cwd(vnode_t *); +void proc_set_root(vnode_t *); +void proc_destroy(proc_t *); +void proc_inactive(proc_t *proc); +void proc_terminate(int status); +int proc_signal_all(int signal, proc_t *sender); +void proc_stop_other_threads(void); +pid_t proc_allocate_pid(void); +void proc_init(void); + +#endif diff --git a/kernel-src/include/kernel/scheduler.h b/kernel-src/include/kernel/scheduler.h index 270c8cf8..c33cfbee 100644 --- a/kernel-src/include/kernel/scheduler.h +++ b/kernel-src/include/kernel/scheduler.h @@ -10,6 +10,7 @@ #include #include #include +#include #define SCHED_THREAD_FLAGS_QUEUED 1 #define SCHED_THREAD_FLAGS_RUNNING 2 @@ -27,130 +28,7 @@ #define STACK_TOP (void *)0x0000800000000000 #define INTERP_BASE (void *)0x00000beef0000000 -struct proc_t; - -typedef struct thread_t { - void *kernelstacktop; - struct thread_t *next; - struct thread_t *prev; - struct thread_t *sleepnext; - struct thread_t *sleepprev; - struct thread_t *procnext; - struct proc_t *proc; - struct cpu_t *cpu; - struct cpu_t *cputarget; - context_t context; - extracontext_t extracontext; - void *kernelstack; - size_t kernelstacksize; - vmmcontext_t *vmmctx; - tid_t tid; - int flags; - long priority; - bool sleepintstatus; - spinlock_t sleeplock; - int wakeupreason; - bool shouldexit; - void *kernelarg; - context_t *usercopyctx; - struct { - spinlock_t lock; - eventheader_t waitpendingevent; - stack_t stack; - sigset_t mask; - sigset_t pending; - sigset_t urgent; // always handled before returning to userspace - sigset_t waiting; // for signal_wait - sigset_t returnmask; // for signal_returnmask - bool hasreturnmask; - bool stopped; - } signals; -} thread_t; - -typedef struct proc_t { - mutex_t mutex; - int refcount; - int status; - int state; - struct proc_t *sibling; - struct proc_t *parent; - struct proc_t *child; - pid_t pid; - cred_t cred; - spinlock_t threadlistlock; - thread_t *threadlist; - bool nomorethreads; - size_t runningthreadcount; - size_t fdcount; - uintmax_t fdfirst; - mutex_t fdmutex; - struct fd_t *fd; - mode_t umask; - int flags; - vnode_t *cwd; - vnode_t *root; - spinlock_t nodeslock; - semaphore_t waitsem; - spinlock_t exiting; - - spinlock_t jobctllock; - struct { - // NULL if this process is leader - struct proc_t *leader; - - // these are only applicable if the process is leader - struct proc_t *foreground; // process group leader, NULL if self - void *controllingtty; - } session; - - struct { - // NULL if this process is leader - struct proc_t *leader; - // linked list - struct proc_t *nextmember; - struct proc_t *previousmember; - - // these are only applicable if the process is leader - spinlock_t lock; // protects the linked list - } pgrp; - - struct { - spinlock_t lock; - sigaction_t actions[NSIG]; - sigset_t pending; - bool stopunwaited; - bool continueunwaited; - } signals; - - struct { - mutex_t mutex; - itimer_t realtime; - itimer_t virtualtime; - itimer_t profiling; - } timer; -} proc_t; - -#include - -#define UMASK(mode) ((mode) & ~current_thread()->proc->umask) -#define PROC_HOLD(v) __atomic_add_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) -// the acquire of the pid table mutex is done here to prevent a nasty race condition where sched_inactiveproc could be called multiple times -// due to the pid table itself not holding any references to the process -#define PROC_RELEASE(v) {\ - MUTEX_ACQUIRE(&sched_pidtablemutex, false); \ - if (__atomic_sub_fetch(&(v)->refcount, 1, __ATOMIC_SEQ_CST) == 0) {\ - sched_inactiveproc(v); \ - (v) = NULL; \ - } \ - MUTEX_RELEASE(&sched_pidtablemutex); \ - } - -extern proc_t *sched_initproc; -extern mutex_t sched_pidtablemutex; - -proc_t *sched_getprocfrompid(int pid); void sched_init(); -void sched_stopotherthreads(); void sched_runinit(); __attribute__((noreturn)) void sched_threadexit(); void sched_queue(thread_t *thread); @@ -158,20 +36,11 @@ void sched_stopcurrentthread(); int sched_yield(); void sched_preparesleep(bool interruptible); bool sched_wakeup(thread_t *thread, int reason); -proc_t *sched_newproc(); -vnode_t *sched_getcwd(); -vnode_t *sched_getroot(); -void sched_setcwd(vnode_t *); -void sched_setroot(vnode_t *); thread_t *sched_newthread(void *ip, size_t kstacksize, int priority, proc_t *proc, void *ustack); -void sched_destroyproc(proc_t *); void sched_destroythread(thread_t *); void sched_targetcpu(struct cpu_t *cpu); void sched_reschedule_on_cpu(struct cpu_t *cpu, bool target); void sched_sleepus(size_t us); void sched_apentry(); -void sched_inactiveproc(proc_t *proc); -void sched_terminateprogram(int status); -int sched_signalall(int signal, proc_t *sender); #endif diff --git a/kernel-src/include/kernel/syscalls.h b/kernel-src/include/kernel/syscalls.h index 0fafc060..e2b7f727 100644 --- a/kernel-src/include/kernel/syscalls.h +++ b/kernel-src/include/kernel/syscalls.h @@ -15,9 +15,9 @@ typedef struct { static inline int dirfd_enter(char *path, int dirfd, file_t **file, vnode_t **dirnode) { if (*path == '/') { - *dirnode = sched_getroot(); + *dirnode = proc_get_root(); } else if (dirfd == AT_FDCWD) { - *dirnode = sched_getcwd(); + *dirnode = proc_get_cwd(); } else { *file = fd_get(dirfd); if (file == NULL) { diff --git a/kernel-src/include/kernel/thread.h b/kernel-src/include/kernel/thread.h new file mode 100644 index 00000000..ae801afc --- /dev/null +++ b/kernel-src/include/kernel/thread.h @@ -0,0 +1,49 @@ +#ifndef _THREAD_H +#define _THREAD_H + +#include +#include +#include +#include + +struct proc_t; + +typedef struct thread_t { + void *kernelstacktop; + struct thread_t *next; + struct thread_t *prev; + struct thread_t *sleepnext; + struct thread_t *sleepprev; + struct thread_t *procnext; + struct proc_t *proc; + struct cpu_t *cpu; + struct cpu_t *cputarget; + context_t context; + extracontext_t extracontext; + void *kernelstack; + size_t kernelstacksize; + vmmcontext_t *vmmctx; + tid_t tid; + int flags; + long priority; + bool sleepintstatus; + spinlock_t sleeplock; + int wakeupreason; + bool shouldexit; + void *kernelarg; + context_t *usercopyctx; + struct { + spinlock_t lock; + eventheader_t waitpendingevent; + stack_t stack; + sigset_t mask; + sigset_t pending; + sigset_t urgent; // always handled before returning to userspace + sigset_t waiting; // for signal_wait + sigset_t returnmask; // for signal_returnmask + bool hasreturnmask; + bool stopped; + } signals; +} thread_t; + +#endif diff --git a/kernel-src/io/net/localsocket.c b/kernel-src/io/net/localsocket.c index ac39229e..50e0aa72 100644 --- a/kernel-src/io/net/localsocket.c +++ b/kernel-src/io/net/localsocket.c @@ -602,7 +602,7 @@ static int localsock_connect(socket_t *socket, sockaddr_t *addr, uintmax_t flags } // get the vnode specified in addr - refnode = addr->path[0] == '/' ? sched_getroot() : sched_getcwd(); + refnode = addr->path[0] == '/' ? proc_get_root() : proc_get_cwd(); error = vfs_lookup(&result, refnode, addr->path, NULL, 0); if (error) goto leave; @@ -883,7 +883,7 @@ static int localsock_bind(socket_t *socket, sockaddr_t *addr, cred_t *cred) { strcpy(path, addr->path); - refnode = *path == '/' ? sched_getroot() : sched_getcwd(); + refnode = *path == '/' ? proc_get_root() : proc_get_cwd(); vattr_t attr = { .mode = current_thread()->proc ? UMASK(0777) : 0644, .gid = current_thread()->proc ? current_thread()->proc->cred.gid : 0, diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index 870125c3..469cadca 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -356,7 +356,7 @@ int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cre if (e) return e; - proc_t *proc = sched_getprocfrompid(pgrp); + proc_t *proc = proc_get_from_pid(pgrp); if (proc == NULL) return ESRCH; diff --git a/kernel-src/sys/proc.c b/kernel-src/sys/proc.c new file mode 100644 index 00000000..825c16c2 --- /dev/null +++ b/kernel-src/sys/proc.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include +#include +#include + +static hashtable_t pid_table; +static scache_t *processcache; + +// not defined as static because its acquired/released from a macro in kernel/proc.h +mutex_t proc_pid_table_mutex; + +proc_t *init_proc; +static pid_t currpid = 1; + +pid_t proc_allocate_pid(void) { + return __atomic_fetch_add(&currpid, 1, __ATOMIC_SEQ_CST); +} + +proc_t *proc_get_from_pid(int pid) { + MUTEX_ACQUIRE(&proc_pid_table_mutex, false); + void *_proc = NULL; + hashtable_get(&pid_table, &_proc, &pid, sizeof(pid)); + proc_t *proc = _proc; + if (proc) { + PROC_HOLD(proc); + } + MUTEX_RELEASE(&proc_pid_table_mutex); + + return proc; +} + +int proc_signal_all(int signal, proc_t *sender) { + MUTEX_ACQUIRE(&proc_pid_table_mutex, false); + + pid_t senderpgid = sender ? jobctl_getpgid(sender) : 0; + + size_t donecount = 0; + HASHTABLE_FOREACH(&pid_table) { + proc_t *current = entry->value; + // init does not get signaled + if (current->pid == 1) + continue; + + pid_t currentpgid = jobctl_getpgid(current); + + if (senderpgid == 0 || (signal == SIGCONT && currentpgid == senderpgid) || auth_process_check(&sender->cred, AUTH_ACTIONS_PROCESS_SIGNAL, current) == 0) { + ++donecount; + signal_signalproc(current, signal); + } + } + + MUTEX_RELEASE(&proc_pid_table_mutex); + return donecount == 0 ? EPERM : 0; +} + +static void rtdpc(context_t *, dpcarg_t arg) { + signal_signalproc(arg, SIGALRM); +} + +static void vtdpc(context_t *, dpcarg_t arg) { + signal_signalproc(arg, SIGVTALRM); +} + +static void profdpc(context_t *, dpcarg_t arg) { + signal_signalproc(arg, SIGPROF); +} + +proc_t *proc_create() { + proc_t *proc = slab_allocate(processcache); + if (proc == NULL) + return NULL; + + memset(proc, 0, sizeof(proc_t)); + + // TODO move this to slab + proc->state = SCHED_PROC_STATE_NORMAL; + proc->runningthreadcount = 1; + MUTEX_INIT(&proc->mutex); + SPINLOCK_INIT(proc->nodeslock); + proc->fdcount = 3; + proc->refcount = 1; + proc->fdfirst = 3; + MUTEX_INIT(&proc->fdmutex); + SEMAPHORE_INIT(&proc->waitsem, 0); + SPINLOCK_INIT(proc->jobctllock); + SPINLOCK_INIT(proc->pgrp.lock); + SPINLOCK_INIT(proc->signals.lock); + MUTEX_INIT(&proc->timer.mutex); + itimer_init(&proc->timer.realtime, rtdpc, proc); + itimer_init(&proc->timer.virtualtime, vtdpc, proc); + itimer_init(&proc->timer.profiling, profdpc, proc); + SPINLOCK_INIT(proc->threadlistlock); + + proc->fd = alloc(sizeof(fd_t) * 3); + if (proc->fd == NULL) { + slab_free(processcache, proc); + return NULL; + } + + proc->pid = proc_allocate_pid(); + proc->umask = 022; // default umask + + // add to pid table + MUTEX_ACQUIRE(&proc_pid_table_mutex, false); + if (hashtable_set(&pid_table, proc, &proc->pid, sizeof(proc->pid), true)) { + MUTEX_RELEASE(&proc_pid_table_mutex); + free(proc->fd); + slab_free(processcache, proc); + return NULL; + } + MUTEX_RELEASE(&proc_pid_table_mutex); + + return proc; +} + +void proc_destroy(proc_t *proc) { + free(proc->fd); + slab_free(processcache, proc); +} + +void proc_inactive(proc_t *proc) { + // proc refcount 0, we can free the structure + // the pid table lock is already acquired. + + hashtable_remove(&pid_table, &proc->pid, sizeof(proc->pid)); + + //arch_e9_puts("\n\ndestroy proc\n\n"); + //printf("destroy proc\n"); + proc_destroy(proc); +} + +void proc_stop_other_threads() { + thread_t *thread = current_thread(); + proc_t *proc = thread->proc; + + bool intstatus = interrupt_set(false); + spinlock_acquire(&proc->threadlistlock); + + proc->nomorethreads = true; + thread_t *threadlist = proc->threadlist; + + spinlock_release(&proc->threadlistlock); + interrupt_set(intstatus); + + while (threadlist) { + if (threadlist == thread) { + threadlist = threadlist->procnext; + continue; + } + + threadlist->shouldexit = true; + sched_wakeup(threadlist, SCHED_WAKEUP_REASON_INTERRUPTED); + threadlist = threadlist->procnext; + } + + while (__atomic_load_n(&proc->runningthreadcount, __ATOMIC_SEQ_CST) > 1) { + arch_e9_puts("proc_stop_other_threads\n"); + sched_yield(); + } + + proc->nomorethreads = false; +} + +void proc_terminate(int status) { + thread_t *thread = current_thread(); + proc_t *proc = thread->proc; + if (spinlock_try(&proc->exiting) == false) + sched_threadexit(); + + proc_stop_other_threads(); + + proc->status = status; + + sched_threadexit(); +} + +static vnode_t *getnodeslock(vnode_t **addr) { + proc_t *proc = current_thread()->proc; + bool intstatus = interrupt_set(false); + spinlock_acquire(&proc->nodeslock); + vnode_t *vnode = *addr; + VOP_HOLD(vnode); + spinlock_release(&proc->nodeslock); + interrupt_set(intstatus); + return vnode; +} + +vnode_t *proc_get_cwd() { + proc_t *proc = current_thread()->proc; + return getnodeslock(&proc->cwd); +} + +vnode_t *proc_get_root() { + proc_t *proc = current_thread()->proc; + return getnodeslock(&proc->root); +} + +static void setnodeslock(vnode_t **addr, vnode_t *new) { + proc_t *proc = current_thread()->proc; + vnode_t *oldnode; + VOP_HOLD(new); + bool intstatus = interrupt_set(false); + spinlock_acquire(&proc->nodeslock); + oldnode = *addr; + *addr = new; + spinlock_release(&proc->nodeslock); + interrupt_set(intstatus); + VOP_RELEASE(oldnode); +} + +void proc_set_cwd(vnode_t *new) { + proc_t *proc = current_thread()->proc; + setnodeslock(&proc->cwd, new); +} + +void proc_set_root(vnode_t *new) { + proc_t *proc = current_thread()->proc; + setnodeslock(&proc->root, new); +} + +void proc_init(void) { + processcache = slab_newcache(sizeof(proc_t), 0, NULL, NULL); + __assert(processcache); + + __assert(hashtable_init(&pid_table, 100) == 0); + MUTEX_INIT(&proc_pid_table_mutex); +} diff --git a/kernel-src/sys/scheduler.c b/kernel-src/sys/scheduler.c index 1943a829..4722983b 100644 --- a/kernel-src/sys/scheduler.c +++ b/kernel-src/sys/scheduler.c @@ -19,7 +19,6 @@ #define SCHEDULER_STACK_SIZE PAGE_SIZE * 16 static scache_t *threadcache; -static scache_t *processcache; #define RUNQUEUE_COUNT 64 @@ -31,109 +30,6 @@ typedef struct { static rqueue_t runqueue[RUNQUEUE_COUNT]; static uint64_t runqueuebitmap; static spinlock_t runqueuelock; -static hashtable_t pidtable; -// not defined as static because its acquired/released from a macro in kernel/scheduler.h -mutex_t sched_pidtablemutex; - -proc_t *sched_initproc; -static pid_t currpid = 1; - -proc_t *sched_getprocfrompid(int pid) { - MUTEX_ACQUIRE(&sched_pidtablemutex, false); - void *_proc = NULL; - hashtable_get(&pidtable, &_proc, &pid, sizeof(pid)); - proc_t *proc = _proc; - if (proc) { - PROC_HOLD(proc); - } - MUTEX_RELEASE(&sched_pidtablemutex); - - return proc; -} - -int sched_signalall(int signal, proc_t *sender) { - MUTEX_ACQUIRE(&sched_pidtablemutex, false); - - pid_t senderpgid = sender ? jobctl_getpgid(sender) : 0; - - size_t donecount = 0; - HASHTABLE_FOREACH(&pidtable) { - proc_t *current = entry->value; - // init does not get signaled - if (current->pid == 1) - continue; - - pid_t currentpgid = jobctl_getpgid(current); - - if (senderpgid == 0 || (signal == SIGCONT && currentpgid == senderpgid) || auth_process_check(&sender->cred, AUTH_ACTIONS_PROCESS_SIGNAL, current) == 0) { - ++donecount; - signal_signalproc(current, signal); - } - } - - MUTEX_RELEASE(&sched_pidtablemutex); - return donecount == 0 ? EPERM : 0; -} - -static void rtdpc(context_t *, dpcarg_t arg) { - signal_signalproc(arg, SIGALRM); -} - -static void vtdpc(context_t *, dpcarg_t arg) { - signal_signalproc(arg, SIGVTALRM); -} - -static void profdpc(context_t *, dpcarg_t arg) { - signal_signalproc(arg, SIGPROF); -} - -proc_t *sched_newproc() { - proc_t *proc = slab_allocate(processcache); - if (proc == NULL) - return NULL; - - memset(proc, 0, sizeof(proc_t)); - - // TODO move this to slab - proc->state = SCHED_PROC_STATE_NORMAL; - proc->runningthreadcount = 1; - MUTEX_INIT(&proc->mutex); - SPINLOCK_INIT(proc->nodeslock); - proc->fdcount = 3; - proc->refcount = 1; - proc->fdfirst = 3; - MUTEX_INIT(&proc->fdmutex); - SEMAPHORE_INIT(&proc->waitsem, 0); - SPINLOCK_INIT(proc->jobctllock); - SPINLOCK_INIT(proc->pgrp.lock); - SPINLOCK_INIT(proc->signals.lock); - MUTEX_INIT(&proc->timer.mutex); - itimer_init(&proc->timer.realtime, rtdpc, proc); - itimer_init(&proc->timer.virtualtime, vtdpc, proc); - itimer_init(&proc->timer.profiling, profdpc, proc); - SPINLOCK_INIT(proc->threadlistlock); - - proc->fd = alloc(sizeof(fd_t) * 3); - if (proc->fd == NULL) { - slab_free(processcache, proc); - return NULL; - } - - proc->pid = __atomic_fetch_add(&currpid, 1, __ATOMIC_SEQ_CST); - proc->umask = 022; // default umask - - // add to pid table - MUTEX_ACQUIRE(&sched_pidtablemutex, false); - if (hashtable_set(&pidtable, proc, &proc->pid, sizeof(proc->pid), true)) { - MUTEX_RELEASE(&sched_pidtablemutex); - free(proc->fd); - slab_free(processcache, proc); - return NULL; - } - MUTEX_RELEASE(&sched_pidtablemutex); - - return proc; -} thread_t *sched_newthread(void *ip, size_t kstacksize, int priority, proc_t *proc, void *ustack) { thread_t *thread = slab_allocate(threadcache); @@ -158,7 +54,7 @@ thread_t *sched_newthread(void *ip, size_t kstacksize, int priority, proc_t *pro if (proc) { // each thread holds one reference to proc PROC_HOLD(proc); - thread->tid = __atomic_fetch_add(&currpid, 1, __ATOMIC_SEQ_CST); + thread->tid = proc_allocate_pid(); } CTX_INIT(&thread->context, proc != NULL, true); @@ -177,11 +73,6 @@ void sched_destroythread(thread_t *thread) { slab_free(threadcache, thread); } -void sched_destroyproc(proc_t *proc) { - free(proc->fd); - slab_free(processcache, proc); -} - static thread_t *getinrunqueue(rqueue_t *rq) { thread_t *thread = rq->list; @@ -311,7 +202,7 @@ __attribute__((noreturn)) void sched_stopcurrentthread() { // called when all threads in a process have exited void sched_procexit() { proc_t *proc = current_thread()->proc; - __assert(proc != sched_initproc); + __assert(proc != init_proc); // the process is going to be referenced by the child list, hold it // it only holds it now because it has to have running threads to be in the list @@ -339,7 +230,7 @@ void sched_procexit() { proc_t *lastchild = proc->child; - MUTEX_ACQUIRE(&sched_initproc->mutex, false); + MUTEX_ACQUIRE(&init_proc->mutex, false); int belowzombiecount = 0; @@ -347,37 +238,26 @@ void sched_procexit() { if (lastchild->state == SCHED_PROC_STATE_ZOMBIE) ++belowzombiecount; - lastchild->parent = sched_initproc; + lastchild->parent = init_proc; lastchild = lastchild->sibling; } if (lastchild) { - lastchild->sibling = sched_initproc->child; - sched_initproc->child = proc->child; + lastchild->sibling = init_proc->child; + init_proc->child = proc->child; } - MUTEX_RELEASE(&sched_initproc->mutex); + MUTEX_RELEASE(&init_proc->mutex); MUTEX_RELEASE(&proc->mutex); signal_signalproc(proc->parent, SIGCHLD); semaphore_signal(&proc->parent->waitsem); // TODO sigaction flag for this for (int i = 0; i < belowzombiecount; ++i) { - semaphore_signal(&sched_initproc->waitsem); + semaphore_signal(&init_proc->waitsem); } } -void sched_inactiveproc(proc_t *proc) { - // proc refcount 0, we can free the structure - // the pid table lock is already acquired. - - hashtable_remove(&pidtable, &proc->pid, sizeof(proc->pid)); - - //arch_e9_puts("\n\ndestroy proc\n\n"); - //printf("destroy proc\n"); - sched_destroyproc(proc); -} - static void threadexit_internal(context_t *, void *) { thread_t *thread = current_thread(); // we don't need to access the current thread anymore, as any state will be ignored and we are running on the scheduler stack @@ -476,51 +356,6 @@ __attribute__((no_caller_saved_registers)) void sched_userspacecheck(context_t * current_cpu()->intstatus = intstatus; } -void sched_stopotherthreads() { - thread_t *thread = current_thread(); - proc_t *proc = thread->proc; - - bool intstatus = interrupt_set(false); - spinlock_acquire(&proc->threadlistlock); - - proc->nomorethreads = true; - thread_t *threadlist = proc->threadlist; - - spinlock_release(&proc->threadlistlock); - interrupt_set(intstatus); - - while (threadlist) { - if (threadlist == thread) { - threadlist = threadlist->procnext; - continue; - } - - threadlist->shouldexit = true; - sched_wakeup(threadlist, SCHED_WAKEUP_REASON_INTERRUPTED); - threadlist = threadlist->procnext; - } - - while (__atomic_load_n(&proc->runningthreadcount, __ATOMIC_SEQ_CST) > 1) { - arch_e9_puts("sched_stopotherthreads\n"); - sched_yield(); - } - - proc->nomorethreads = false; -} - -void sched_terminateprogram(int status) { - thread_t *thread = current_thread(); - proc_t *proc = thread->proc; - if (spinlock_try(&proc->exiting) == false) - sched_threadexit(); - - sched_stopotherthreads(); - - proc->status = status; - - sched_threadexit(); -} - static void yield(context_t *context, void *) { thread_t *thread = current_thread(); @@ -611,49 +446,6 @@ bool sched_wakeup(thread_t *thread, int reason) { return true; } -static vnode_t *getnodeslock(vnode_t **addr) { - proc_t *proc = current_thread()->proc; - bool intstatus = interrupt_set(false); - spinlock_acquire(&proc->nodeslock); - vnode_t *vnode = *addr; - VOP_HOLD(vnode); - spinlock_release(&proc->nodeslock); - interrupt_set(intstatus); - return vnode; -} - -vnode_t *sched_getcwd() { - proc_t *proc = current_thread()->proc; - return getnodeslock(&proc->cwd); -} - -vnode_t *sched_getroot() { - proc_t *proc = current_thread()->proc; - return getnodeslock(&proc->root); -} - -static void setnodeslock(vnode_t **addr, vnode_t *new) { - proc_t *proc = current_thread()->proc; - vnode_t *oldnode; - VOP_HOLD(new); - bool intstatus = interrupt_set(false); - spinlock_acquire(&proc->nodeslock); - oldnode = *addr; - *addr = new; - spinlock_release(&proc->nodeslock); - interrupt_set(intstatus); - VOP_RELEASE(oldnode); -} - -void sched_setcwd(vnode_t *new) { - proc_t *proc = current_thread()->proc; - setnodeslock(&proc->cwd, new); -} -void sched_setroot(vnode_t *new) { - proc_t *proc = current_thread()->proc; - setnodeslock(&proc->root, new); -} - // once a scheduler dpc gets run, the return context is set to this function using the scheduler stack static void dopreempt() { // interrupts are disabled, the thread context is already saved @@ -791,13 +583,9 @@ void sched_apentry() { } void sched_init() { + proc_init(); threadcache = slab_newcache(sizeof(thread_t), 0, NULL, NULL); __assert(threadcache); - processcache = slab_newcache(sizeof(proc_t), 0, NULL, NULL); - __assert(processcache); - - __assert(hashtable_init(&pidtable, 100) == 0); - MUTEX_INIT(&sched_pidtablemutex); current_cpu()->schedulerstack = vmm_map(NULL, SCHEDULER_STACK_SIZE, VMM_FLAGS_ALLOCATE, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, NULL); __assert(current_cpu()->schedulerstack); @@ -830,10 +618,10 @@ void sched_runinit() { // leave kernel context to load elf vmm_switchcontext(vmmctx); - proc_t *proc = sched_newproc(); + proc_t *proc = proc_create(); __assert(proc); - sched_initproc = proc; + init_proc = proc; vnode_t *initnode; __assert(vfs_open(vfsroot, "/init", 0, &initnode) == 0); diff --git a/kernel-src/sys/signal.c b/kernel-src/sys/signal.c index 2af71e60..c3521790 100644 --- a/kernel-src/sys/signal.c +++ b/kernel-src/sys/signal.c @@ -435,7 +435,7 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin THREAD_LEAVE(thread); PROCESS_LEAVE(proc); interrupt_set(true); - sched_terminateprogram(SIGKILL); + proc_terminate(SIGKILL); } // find the first pending signal which is unmasked @@ -492,7 +492,7 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin THREAD_LEAVE(thread); PROCESS_LEAVE(proc); interrupt_set(true); - sched_terminateprogram(signal); + proc_terminate(signal); case ACTION_STOP: // TODO what if a thread unmasks a stop signal? // check if sigcont is not pending for the thread (SIGCONT is always sent to the thread) @@ -570,7 +570,7 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin THREAD_LEAVE(thread); PROCESS_LEAVE(proc); interrupt_set(true); - sched_terminateprogram(SIGSEGV); + proc_terminate(SIGSEGV); } // configure new thread signal mask diff --git a/kernel-src/sys/syscalls/chdir.c b/kernel-src/sys/syscalls/chdir.c index 6170f026..f6729823 100644 --- a/kernel-src/sys/syscalls/chdir.c +++ b/kernel-src/sys/syscalls/chdir.c @@ -26,7 +26,7 @@ syscallret_t syscall_chdir(context_t *, char *upath) { return ret; } - vnode_t *ref = path[0] == '/' ? sched_getroot() : sched_getcwd(); + vnode_t *ref = path[0] == '/' ? proc_get_root() : proc_get_cwd(); vnode_t *new = NULL; ret.errno = vfs_lookup(&new, ref, path, NULL, 0); @@ -40,7 +40,7 @@ syscallret_t syscall_chdir(context_t *, char *upath) { goto cleanup; } - sched_setcwd(new); + proc_set_cwd(new); ret.ret = 0; cleanup: @@ -69,7 +69,7 @@ syscallret_t syscall_fchdir(context_t *, int fd) { goto cleanup; } - sched_setcwd(file->vnode); + proc_set_cwd(file->vnode); ret.errno = 0; cleanup: diff --git a/kernel-src/sys/syscalls/chroot.c b/kernel-src/sys/syscalls/chroot.c index 2e40f0c0..dff33708 100644 --- a/kernel-src/sys/syscalls/chroot.c +++ b/kernel-src/sys/syscalls/chroot.c @@ -31,7 +31,7 @@ syscallret_t syscall_chroot(context_t *, char *upath) { return ret; } - vnode_t *ref = path[0] == '/' ? sched_getroot() : sched_getcwd(); + vnode_t *ref = path[0] == '/' ? proc_get_root() : proc_get_cwd(); vnode_t *new = NULL; ret.errno = vfs_lookup(&new, ref, path, NULL, 0); @@ -45,7 +45,7 @@ syscallret_t syscall_chroot(context_t *, char *upath) { goto cleanup; } - sched_setroot(new); + proc_set_root(new); ret.ret = 0; cleanup: diff --git a/kernel-src/sys/syscalls/execve.c b/kernel-src/sys/syscalls/execve.c index de1e2e9a..51d87740 100644 --- a/kernel-src/sys/syscalls/execve.c +++ b/kernel-src/sys/syscalls/execve.c @@ -171,7 +171,7 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char goto error; } - refnode = *path == '/' ? sched_getroot() : sched_getcwd(); + refnode = *path == '/' ? proc_get_root() : proc_get_cwd(); ret.errno = vfs_lookup(&node, refnode, path, NULL, 0); if (ret.errno) @@ -241,7 +241,7 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char if (interp) { vnode_t *interpnode = NULL; - vnode_t *interprefnode = *interp == '/' ? sched_getroot() : sched_getcwd(); + vnode_t *interprefnode = *interp == '/' ? proc_get_root() : proc_get_cwd(); ret.errno = vfs_lookup(&interpnode, interprefnode, interp, NULL, 0); if (ret.errno) goto error; @@ -273,7 +273,7 @@ static syscallret_t execve(context_t *context, char *upath, char *uargv[], char ret.ret = 0; - sched_stopotherthreads(); + proc_stop_other_threads(); // close O_CLOEXEC fds diff --git a/kernel-src/sys/syscalls/exit.c b/kernel-src/sys/syscalls/exit.c index aa5033c8..707b76ac 100644 --- a/kernel-src/sys/syscalls/exit.c +++ b/kernel-src/sys/syscalls/exit.c @@ -6,6 +6,6 @@ #include __attribute__((noreturn)) void syscall_exit(context_t *context, int status) { - sched_terminateprogram(status << 8); + proc_terminate(status << 8); __builtin_unreachable(); } diff --git a/kernel-src/sys/syscalls/fork.c b/kernel-src/sys/syscalls/fork.c index 14382150..cc25e506 100644 --- a/kernel-src/sys/syscalls/fork.c +++ b/kernel-src/sys/syscalls/fork.c @@ -12,7 +12,7 @@ syscallret_t syscall_fork(context_t *ctx) { }; proc_t *proc = current_thread()->proc; - proc_t *nproc = sched_newproc(); + proc_t *nproc = proc_create(); if (nproc == NULL) { ret.errno = ENOMEM; goto cleanup; @@ -45,8 +45,8 @@ syscallret_t syscall_fork(context_t *ctx) { nproc->umask = current_thread()->proc->umask; nproc->cred = current_thread()->proc->cred; - nproc->root = sched_getroot(); - nproc->cwd = sched_getcwd(); + nproc->root = proc_get_root(); + nproc->cwd = proc_get_cwd(); nproc->threadlist = nthread; nthread->procnext = NULL; diff --git a/kernel-src/sys/syscalls/kill.c b/kernel-src/sys/syscalls/kill.c index 3fa0f2c9..2575d4dd 100644 --- a/kernel-src/sys/syscalls/kill.c +++ b/kernel-src/sys/syscalls/kill.c @@ -20,7 +20,7 @@ syscallret_t syscall_kill(context_t *context, int pid, int signal) { else if (pid < -1) effectivepid = -pid; // target specific process group - proc_t *target = sched_getprocfrompid(effectivepid); + proc_t *target = proc_get_from_pid(effectivepid); if (target == NULL && pid != 0 && pid != -1) { ret.errno = ESRCH; return ret; @@ -39,7 +39,7 @@ syscallret_t syscall_kill(context_t *context, int pid, int signal) { signal_signalproc(target, signal); } else if (pid == -1) { - ret.errno = sched_signalall(signal, current_thread()->proc); + ret.errno = proc_signal_all(signal, current_thread()->proc); } else { ret.errno = jobctl_signal(target, signal, current_thread()->proc); } diff --git a/kernel-src/sys/syscalls/killthread.c b/kernel-src/sys/syscalls/killthread.c index 7461dbdc..257c3f73 100644 --- a/kernel-src/sys/syscalls/killthread.c +++ b/kernel-src/sys/syscalls/killthread.c @@ -15,7 +15,7 @@ syscallret_t syscall_killthread(context_t *context, int pid, int tid, int signal } proc_t *sender = current_thread()->proc; - proc_t *target = sched_getprocfrompid(pid); + proc_t *target = proc_get_from_pid(pid); if (target == NULL) { ret.errno = ESRCH; return ret; diff --git a/kernel-src/sys/syscalls/mount.c b/kernel-src/sys/syscalls/mount.c index b720e8b1..d5fe9846 100644 --- a/kernel-src/sys/syscalls/mount.c +++ b/kernel-src/sys/syscalls/mount.c @@ -70,8 +70,8 @@ syscallret_t syscall_mount(context_t *context, char *ubacking, char *umountpoint vnode_t *backingrefnode = NULL; if (ubacking) - backingrefnode = *backing == '/' ? sched_getroot() : sched_getcwd(); - vnode_t *mountpointrefnode = *mountpoint == '/' ? sched_getroot() : sched_getcwd(); + backingrefnode = *backing == '/' ? proc_get_root() : proc_get_cwd(); + vnode_t *mountpointrefnode = *mountpoint == '/' ? proc_get_root() : proc_get_cwd(); vnode_t *backingnode = NULL; if (ubacking) { diff --git a/kernel-src/sys/syscalls/setpid.c b/kernel-src/sys/syscalls/setpid.c index d3524e1a..069968b0 100644 --- a/kernel-src/sys/syscalls/setpid.c +++ b/kernel-src/sys/syscalls/setpid.c @@ -25,7 +25,7 @@ syscallret_t syscall_setpgid(context_t *, pid_t pid, pid_t pgid) { proc = currentproc; PROC_HOLD(proc); } else { - proc = sched_getprocfrompid(pid); + proc = proc_get_from_pid(pid); } if (proc == NULL) { @@ -44,7 +44,7 @@ syscallret_t syscall_setpgid(context_t *, pid_t pid, pid_t pgid) { pgrp = currentproc; PROC_HOLD(pgrp); } else { - pgrp = sched_getprocfrompid(pgid); + pgrp = proc_get_from_pid(pgid); } if (pgrp == NULL) { diff --git a/kernel-src/sys/syscalls/sigreturn.c b/kernel-src/sys/syscalls/sigreturn.c index fe5202d7..3aba707a 100644 --- a/kernel-src/sys/syscalls/sigreturn.c +++ b/kernel-src/sys/syscalls/sigreturn.c @@ -9,7 +9,7 @@ __attribute__((noreturn)) void syscall_sigreturn(context_t *context) { int error = usercopy_fromuser(&sigframe, (void *)CTX_SP(context), sizeof(sigframe_t)); if (error || ARCH_CONTEXT_ISUSER(&sigframe.context) == false) { printf("syscall_sigreturn: bad return stack or bad return information\n"); - sched_terminateprogram(SIGSEGV); + proc_terminate(SIGSEGV); } interrupt_set(false);