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:
#endif /* ! FEATURE(POSIX) */
}
+ /* if there is a pending signal, handle it */
+ task_signal_handle(cproc, ctask, &ctx);
+
return;
}
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) {
ctx.eax = ret_val;
+ /* if there is a pending signal, handle it */
+ task_signal_handle(cproc, ctask, &ctx);
+
return;
}
enum procstate p_state;
int p_status;
+ int p_sigpending;
+ siginfo_t p_siginfo;
+
+ int p_sigflags[32];
sighandler_t p_sighandler[32];
};
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 */
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
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;
/*
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;
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;
}