]> git.corax.cc Git - corax/commitdiff
Deliver signals to processes by storing pending signals and accompanying
authorMatthias Kruk <m@m10k.eu>
Sun, 19 Jan 2020 09:11:43 +0000 (18:11 +0900)
committerMatthias Kruk <m@m10k.eu>
Sun, 19 Jan 2020 09:11:43 +0000 (18:11 +0900)
signal information in the destination process structure, from where the
destination process will retrieve it before returning from an interrupt
or system call. Exception delivery is not affected by this because
exceptions can be delivered directly.

Function implementations added:
 - task_signal_handle()
 - process_put_signal()
 - process_get_signal()
 - process_clear_signal()
 - process_set_sighandler()

kernel/arch/interrupt.c
kernel/core/process.c
kernel/core/signal.c
kernel/include/process.h

index 14b8cc19d52b0e9cb635b1841dbef344fc319566..946a1361ec29530c942f8004af053407016f8a27 100644 (file)
@@ -80,8 +80,36 @@ void task_signal_deliver(task_t *task, stack_frame_t *stk, int signum, siginfo_t
        return;
 }
 
+void task_signal_handle(process_t *proc, task_t *task, stack_frame_t *stk)
+{
+       siginfo_t *siginfo;
+       int signal;
+       int ret_val;
+
+       ret_val = process_get_signal(proc, &signal, &siginfo);
+
+       if(!ret_val && signal >= 0) {
+               /* there is a signal to be handled */
+
+               dbg_printf("Process %p has a pending signal\n", proc);
+
+               task_signal_deliver(task, stk, signal, siginfo);
+
+               dbg_printf("Signal %u delivered to %p:%p\n", signal, proc, task);
+               process_clear_signal(proc);
+       }
+
+       return;
+}
+
 void _int_handle(stack_frame_t ctx)
 {
+       process_t *cproc;
+       task_t *ctask;
+
+       cproc = process_get_current();
+       ctask = task_get_current();
+
     switch(ctx.intn) {
 #if CONFIG_APIC == 1
        case INT_APICERR:
@@ -138,6 +166,9 @@ void _int_handle(stack_frame_t ctx)
 #endif /* ! FEATURE(POSIX) */
        }
 
+       /* if there is a pending signal, handle it */
+       task_signal_handle(cproc, ctask, &ctx);
+
     return;
 }
 
@@ -242,7 +273,11 @@ void _exc_handle(stack_frame_t ctx)
 void _sys_handle(stack_frame_t ctx)
 {
        int ret_val;
+       process_t *cproc;
+       task_t *ctask;
 
+       cproc = process_get_current();
+       ctask = task_get_current();
     ret_val = -ENOSYS;
 
        switch(ctx.intn) {
@@ -273,5 +308,8 @@ void _sys_handle(stack_frame_t ctx)
 
        ctx.eax = ret_val;
 
+       /* if there is a pending signal, handle it */
+       task_signal_handle(cproc, ctask, &ctx);
+
     return;
 }
index 2fea2de98eafce703206c1f3b62c610f7a2999f3..9587e286cc736c11b9bbdd313e6c92c87be50f3a 100644 (file)
@@ -38,6 +38,10 @@ struct process {
        enum procstate p_state;
        int            p_status;
 
+       int            p_sigpending;
+       siginfo_t      p_siginfo;
+
+       int            p_sigflags[32];
        sighandler_t   p_sighandler[32];
 };
 
@@ -325,6 +329,7 @@ int process_create(process_t **dst, pid_t pid, u32_t ppl, void *entry)
                memcpy(proc->p_sighandler, _sig_dfl, sizeof(proc->p_sighandler));
 
                proc->p_privl = ppl;
+               proc->p_sigpending = -1;
 
                if(pid == PID_ANY) {
                        /* no specific pid requested */
@@ -746,8 +751,9 @@ int process_signal_deliver(process_t *proc, int signal)
 
                if(cproc != proc) {
                        dbg_printf("Signal %u to different process\n", signal);
+                       /* TODO: Put the pending signal into the process structure */
+
                        /* FIXME: Need to suspend the process in order to deliver the signal safely */
-                       process_suspend(proc);
 
                        /*
                         * Elect a task to handle the signal - right now, this is simple since the
@@ -766,12 +772,17 @@ int process_signal_deliver(process_t *proc, int signal)
                        task = task_get_current();
                }
 
+               dbg_printf("Delivering signal to task %p\n", task);
+
                if(!task) {
+                       dbg_printf("Couldn't find a task to deliver the signal to\n");
                        /* this should actually never happen */
                        ret_val = -EBADFD;
                        goto cleanup;
                }
 
+               dbg_printf("Should be delivering the irq here\n");
+
                kstk = (stack_frame_t*)task->t_sp;
 
                /*
@@ -1046,6 +1057,25 @@ void* process_get_sighandler(process_t *proc, int signal)
        return((void*)proc->p_sighandler[signal]);
 }
 
+int process_set_sighandler(process_t *proc, int signal, struct sigaction *sa)
+{
+       int ret_val;
+
+       ret_val = -EINVAL;
+
+       if(proc && signal >= 0 && signal <= SIGMAX) {
+               proc->p_sigflags[signal] = sa->sa_flags;
+               proc->p_sighandler[signal] = sa->sa_flags & SA_SIGINFO ?
+                       sa->sa_sigaction : sa->sa_handler;
+
+               dbg_printf("process_set_sighandler: %p[%u] -> %p\n", proc, signal, sa->sa_handler);
+
+               ret_val = 0;
+       }
+
+       return(ret_val);
+}
+
 int _process_hwint_deliver(pid_t pid, int irq)
 {
        process_t *proc;
@@ -1054,8 +1084,114 @@ int _process_hwint_deliver(pid_t pid, int irq)
        ret_val = -EINVAL;
        proc = process_lookup(pid);
 
+       dbg_printf("Delivering irq %u to %u [%p]\n", irq, pid, proc);
+
+       if(proc) {
+               siginfo_t siginfo;
+
+               /* everything but si_signo and si_trapno is 0 for now */
+               memset(&siginfo, 0, sizeof(siginfo));
+               siginfo.si_signo = SIGHWINT;
+               siginfo.si_trapno = irq;
+
+               ret_val = process_put_signal(proc, SIGHWINT, &siginfo);
+       }
+
+       return(ret_val);
+}
+
+/*
+ * process_put_signal() - Deliver a signal to a process
+ *
+ * SYNOPSIS
+ *  int process_put_signal(process_t *proc, int signal, siginfo_t *si)
+ *
+ * DESCRIPTION
+ *  The process_put_signal() function puts information about a signal
+ *  into the structure of a process.
+ *  The signal will only be stored in the process structure if there
+ *  has not already been stored information about a pending signal.
+ *  If the slot for the pending signal is available, it will be set to
+ *  the signal number passed in the `signal' argument. If the `si'
+ *  argument is not NULL, the additional signal information wil be
+ *  copied into the process structure.
+ *  The process_put_signal() function is atomic, in the sense that it
+ *  will lock the process for the time that it uses the process
+ *  structure.
+ *
+ * RETURN VALUE
+ *          0 The signal was successfully delivered
+ *    -EINVAL Invalid values were passed in `proc' and/or `signal'
+ *  -EALREADY There is already a pending signal for the process
+ */
+int process_put_signal(process_t *proc, int signal, siginfo_t *si)
+{
+       int ret_val;
+
+       ret_val = -EINVAL;
+
+       if(proc && signal >= 0 && signal <= SIGMAX) {
+               ret_val = -EALREADY;
+
+               process_lock(proc);
+
+               /* only deliver the signal if there is no pending one */
+               if(proc->p_sigpending < 0) {
+                       proc->p_sigpending = signal;
+
+                       /* copy the additional signal information, if provided */
+                       if(si) {
+                               memcpy(&(proc->p_siginfo), si, sizeof(proc->p_siginfo));
+                       }
+
+                       /* process needs to be woken up if it was sleeping */
+
+                       ret_val = 0;
+               }
+
+               process_unlock(proc);
+       }
+
+       return(ret_val);
+}
+
+int process_get_signal(process_t *proc, int *signal, siginfo_t **si)
+{
+       int ret_val;
+
+       ret_val = -EINVAL;
+
+       if(proc && signal && si) {
+               process_lock(proc);
+
+               if(proc->p_sigpending >= 0) {
+                       *signal = proc->p_sigpending;
+                       *si = (proc->p_sigflags[proc->p_sigpending] & SA_SIGINFO) ?
+                               &(proc->p_siginfo) : NULL;
+               } else {
+                       *signal = -1;
+                       *si = NULL;
+               }
+
+               process_unlock(proc);
+
+               ret_val = 0;
+       }
+
+       return(ret_val);
+}
+
+int process_clear_signal(process_t *proc)
+{
+       int ret_val;
+
+       ret_val = -EINVAL;
+
        if(proc) {
-               process_signal_deliver(proc, SIGHWINT);
+               process_lock(proc);
+               proc->p_sigpending = -1;
+               process_unlock(proc);
+
                ret_val = 0;
        }
 
index 506dba06ada7f4814da5bf4b5444fbdb159e4022..ac60f0506a083f5088fc664d91606be289d5b692 100644 (file)
@@ -81,6 +81,8 @@ int sys_sigaction(stack_frame_t *stk)
        old = (struct sigaction*)stk->edx;
        process_memcpy_ptok(cproc, &new, (void*)stk->ecx, sizeof(new));
 
+       /* FIXME: Save the previous sigaction information in `old' */
+
        switch(signum) {
        case SIGHWINT:
                /* this is the Corax way to notify processes about hardware interrupts */
@@ -140,5 +142,10 @@ int sys_sigaction(stack_frame_t *stk)
                break;
        }
 
+       if(!ret_val) {
+               /* everything seems fine - update the process structure */
+               ret_val = process_set_sighandler(cproc, signum, &new);
+       }
+
        return(ret_val);
 }
index ce2a108f4cea352c7a163675a242e35a41878d21..4d9eef95d56a87410260e7ae33e65a39f16eaf54 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef __PROCESS_H
 #define __PROCESS_H
 
+#include <signal.h>
 #include <corax/types.h>
 #include <corax/ipc.h>
 #include <arch.h>
@@ -47,7 +48,10 @@ struct cxmsg* process_inbox_get(pid_t);
 int           process_wait(pid_t);
 int           process_signal(pid_t);
 int           process_signal_deliver(process_t*, int);
-
+int           process_put_signal(process_t*, int, siginfo_t*);
+int           process_get_signal(process_t*, int*, siginfo_t**);
+int           process_clear_signal(process_t*);
+int           process_set_sighandler(process_t*, int, struct sigaction*);
 void*         process_get_sighandler(process_t*, int);
 
 void*         process_get_tasks(process_t*);