signal.c

Go to the documentation of this file.
00001 
00103 #include "signal.h"
00104 
00105 #include <cfg/debug.h>
00106 #include <drv/timer.h>
00107 #include <kern/proc.h>
00108 #include <kern/proc_p.h>
00109  
00110 
00111 #if CONFIG_KERN_SIGNALS
00112 
00117 sigmask_t sig_check(sigmask_t sigs)
00118 {
00119     sigmask_t result;
00120     cpuflags_t flags;
00121 
00122     IRQ_SAVE_DISABLE(flags);
00123     result = CurrentProcess->sig_recv & sigs;
00124     CurrentProcess->sig_recv &= ~sigs;
00125     IRQ_RESTORE(flags);
00126 
00127     return result;
00128 }
00129 
00130 
00135 sigmask_t sig_wait(sigmask_t sigs)
00136 {
00137     sigmask_t result;
00138     cpuflags_t flags;
00139 
00140     IRQ_SAVE_DISABLE(flags);
00141 
00142     /* Loop until we get at least one of the signals */
00143     while (!(result = CurrentProcess->sig_recv & sigs))
00144     {
00145         /* go to sleep and proc_schedule() another process */
00146         CurrentProcess->sig_wait = sigs;
00147         proc_schedule();
00148 
00149         /* When we come back here, a signal must be arrived */
00150         ASSERT(!CurrentProcess->sig_wait);
00151         ASSERT(CurrentProcess->sig_recv);
00152     }
00153 
00154     /* Signals found: clear them and return */
00155     CurrentProcess->sig_recv &= ~sigs;
00156 
00157     IRQ_RESTORE(flags);
00158     return result;
00159 }
00160 
00167 sigmask_t sig_waitTimeout(sigmask_t sigs, ticks_t timeout)
00168 {
00169     Timer t;
00170     sigmask_t res;
00171     cpuflags_t flags;
00172 
00173     ASSERT(!sig_check(SIG_TIMEOUT));
00174     ASSERT(!(sigs & SIG_TIMEOUT));
00175     /* IRQ are needed to run timer */
00176     ASSERT(IRQ_ENABLED());
00177 
00178     timer_set_event_signal(&t, proc_current(), SIG_TIMEOUT);
00179     timer_setDelay(&t, timeout);
00180     timer_add(&t);
00181     res = sig_wait(SIG_TIMEOUT | sigs);
00182 
00183     IRQ_SAVE_DISABLE(flags);
00184     /* Remove timer if sigs occur before timer signal */
00185     if (!(res & SIG_TIMEOUT) && !sig_check(SIG_TIMEOUT))
00186         timer_abort(&t);
00187     IRQ_RESTORE(flags);
00188     return res;
00189 }
00190 
00191 
00198 void sig_signal(Process *proc, sigmask_t sigs)
00199 {
00200     cpuflags_t flags;
00201     IRQ_SAVE_DISABLE(flags);
00202 
00203     /* Set the signals */
00204     proc->sig_recv |= sigs;
00205 
00206     /* Check if process needs to be awoken */
00207     if (proc->sig_recv & proc->sig_wait)
00208     {
00209         /* Wake up process and enqueue in ready list */
00210         proc->sig_wait = 0;
00211         SCHED_ENQUEUE(proc);
00212     }
00213 
00214     IRQ_RESTORE(flags);
00215 }
00216 
00217 #endif /* CONFIG_KERN_SIGNALS */
00218