initial signal implementation

This commit is contained in:
Matheus
2024-05-14 15:04:48 -03:00
parent 00c212fa8d
commit 7b0cc4c51b
22 changed files with 824 additions and 55 deletions
+3 -3
View File
@@ -8,12 +8,12 @@
__attribute__((noreturn)) void syscall_exit(context_t *context, int status) {
thread_t *thread = _cpu()->thread;
proc_t *proc = thread->proc;
__assert(proc != sched_initproc);
__assert(spinlock_try(&proc->exiting)); // only one thread can exit at the same time
if (spinlock_try(&proc->exiting) == false)
sched_threadexit();
sched_stopotherthreads();
proc->status = status;
proc->status = status << 8;
sched_threadexit();
}
+2 -4
View File
@@ -35,15 +35,13 @@ syscallret_t syscall_fork(context_t *ctx) {
if (ret.errno)
goto cleanup;
bool intstate = interrupt_set(false);
spinlock_acquire(&proc->lock);
MUTEX_ACQUIRE(&proc->mutex, false);
nproc->parent = proc;
nproc->sibling = proc->child;
proc->child = nproc;
spinlock_release(&proc->lock);
interrupt_set(intstate);
MUTEX_RELEASE(&proc->mutex);
nproc->umask = _cpu()->thread->proc->umask;
nproc->root = sched_getroot();
+40
View File
@@ -0,0 +1,40 @@
#include <kernel/syscalls.h>
#include <arch/cpu.h>
#include <logging.h>
syscallret_t syscall_kill(context_t *context, int pid, int signal) {
syscallret_t ret = {
.ret = -1
};
int effectivepid = -1;
if (pid > 0) // specific process
effectivepid = pid;
else if (pid == 0) // own process group
effectivepid = 0;
else if (pid == -1) // every process, unsupported atm
effectivepid = -1;
else if (pid < -1)
effectivepid = -pid; // target specific process group
if (effectivepid == -1) {
ret.errno = ESRCH;
return ret;
}
proc_t *target = sched_getprocfrompid(pid);
if (target == NULL && pid != 0) {
ret.errno = ESRCH;
return ret;
}
if (pid >= 1)
signal_signalproc(target, signal);
else
ret.errno = jobctl_signal(target, signal);
ret.errno = 0;
ret.ret = 0;
return ret;
}
+3 -3
View File
@@ -16,11 +16,11 @@ syscallret_t syscall_newthread(context_t *, void *entry, void *stack) {
proc_t *proc = _cpu()->thread->proc;
spinlock_acquire(&proc->lock);
MUTEX_ACQUIRE(&proc->mutex, false);
// if we currently don't want any more threads to start
if (proc->nomorethreads == true) {
spinlock_release(&proc->lock);
MUTEX_RELEASE(&proc->mutex);
ret.errno = EAGAIN;
return ret;
}
@@ -63,6 +63,6 @@ syscallret_t syscall_newthread(context_t *, void *entry, void *stack) {
sched_queue(proc->threads[i]);
cleanup:
spinlock_release(&proc->lock);
MUTEX_RELEASE(&proc->mutex);
return ret;
}
+29
View File
@@ -0,0 +1,29 @@
#include <kernel/syscalls.h>
#include <arch/cpu.h>
#include <logging.h>
syscallret_t syscall_sigaction(context_t *, int sig, sigaction_t *new, sigaction_t *old) {
syscallret_t ret = {
.ret = -1
};
if (sig > NSIG || sig == SIGKILL || sig == SIGSTOP) {
ret.errno = EINVAL;
return ret;
}
sigaction_t newtmp, oldtmp;
if (new) {
newtmp = *new;
__assert(newtmp.flags & SA_RESTORER);
}
signal_action(_cpu()->thread->proc, sig, new ? &newtmp : NULL, old ? &oldtmp : NULL);
if (old)
*old = oldtmp;
ret.errno = 0;
ret.ret = 0;
return ret;
}
+21
View File
@@ -0,0 +1,21 @@
#include <kernel/syscalls.h>
#include <arch/cpu.h>
syscallret_t syscall_sigaltstack(context_t *, stack_t *new, stack_t *old) {
syscallret_t ret = {
.ret = -1
};
stack_t newtmp, oldtmp;
if (new)
newtmp = *new;
signal_altstack(_cpu()->thread, new ? &newtmp : NULL, old ? &oldtmp : NULL);
if (old)
*old = oldtmp;
ret.errno = 0;
ret.ret = 0;
return ret;
}
+32
View File
@@ -0,0 +1,32 @@
#include <kernel/syscalls.h>
#include <arch/cpu.h>
#define SIG_BLOCK 0
#define SIG_UNBLOCK 1
#define SIG_SETMASK 2
syscallret_t syscall_sigprocmask(context_t *, int how, sigset_t *set, sigset_t *oldset) {
syscallret_t ret = {
.ret = -1
};
sigset_t new, old;
if (set) {
if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK) {
ret.errno = EINVAL;
return ret;
}
new = *set;
}
signal_changemask(_cpu()->thread, how, set ? &new : NULL, oldset ? &old : NULL);
if (oldset)
*oldset = old;
ret.ret = 0;
ret.errno = 0;
return ret;
}
+26
View File
@@ -0,0 +1,26 @@
#include <kernel/syscalls.h>
#include <arch/signal.h>
#include <arch/cpu.h>
#include <logging.h>
// this expects CTX_SP to be pointing to the signal frame
__attribute__((noreturn)) void syscall_sigreturn(context_t *context) {
// TODO check if the information is valid
sigframe_t sigframe;
memcpy(&sigframe, (void *)CTX_SP(context), sizeof(sigframe_t));
interrupt_set(false);
signal_altstack(_cpu()->thread, &sigframe.oldstack, NULL);
signal_changemask(_cpu()->thread, SIG_SETMASK, &sigframe.oldmask, NULL);
__assert(ARCH_CONTEXT_ISUSER(&sigframe.context));
memcpy(&_cpu()->thread->extracontext, &sigframe.extracontext, sizeof(extracontext_t));
ARCH_CONTEXT_THREADLOAD(_cpu()->thread, context);
arch_context_switch(&sigframe.context);
// if we were to return normally, CTX_RET and CTX_ERRNO would be corrupted,
// so we will manually call arch_context_switch, which will jump to the right userland code
// (and also check for pending signals again)
__builtin_unreachable();
}
+8 -8
View File
@@ -19,7 +19,7 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
thread_t *thread = _cpu()->thread;
proc_t *proc = thread->proc;
spinlock_acquire(&proc->lock);
MUTEX_ACQUIRE(&proc->mutex, false);
proc_t *prev = NULL;
proc_t *iterator = proc->child;
@@ -29,10 +29,10 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
if (iterator == NULL) {
if (pid > 0 && desired == NULL) {
ret.errno = ECHILD;
spinlock_release(&proc->lock);
MUTEX_RELEASE(&proc->mutex);
return ret;
}
spinlock_release(&proc->lock);
MUTEX_RELEASE(&proc->mutex);
if ((options & WNOHANG) && semaphore_test(&proc->waitsem) == false) {
ret.errno = 0;
ret.ret = 0;
@@ -41,7 +41,7 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
ret.errno = EINTR;
return ret;
}
spinlock_acquire(&proc->lock);
MUTEX_ACQUIRE(&proc->mutex, false);
prev = NULL;
iterator = proc->child;
desired = NULL; // set as null to be certain another thread didn't get it
@@ -65,12 +65,12 @@ syscallret_t syscall_waitpid(context_t *context, pid_t pid, int *status, int opt
else
proc->child = iterator->sibling;
spinlock_release(&proc->lock);
MUTEX_RELEASE(&proc->mutex);
// TODO memory safe operation
// TODO the signal number goes in the low byte of status
if (status)
*status = iterator->status << 8;
if (status) {
*status = iterator->status;
}
for (int i = 0; i < iterator->threadtablesize; ++i) {
if (iterator->threads[i] == NULL)