signal.c

来自「fsmlabs的real time linux的内核」· C语言 代码 · 共 282 行

C
282
字号
 /* * RTLinux signal support * * Written by Michael Barabanov * Copyright (C) Finite State Machine Labs Inc., 2000 * Released under the terms of the GPL Version 2 * *  Added user signals support - Dec, 2002 Josep Vidal <jvidal@disca.upv.es> (OCERA) *  */#include <signal.h>#include <errno.h>#include <rtl_core.h>#include <asm/irq.h>/* Thread signals */ /* F. Gonz醠ez & J. Vidal *//* Array of sigactions. Thread signals from (7..31) */struct sigaction rtl_sigact [RTL_SIGIRQMAX];/* for compatibility issues */#define sigact rtl_sigactunsigned int rtl_sig_interrupt (unsigned int irq, struct pt_regs *regs){	int sig = irq + RTL_SIGIRQMIN;	if (sigact[sig].sa_handler != SIG_IGN && sigact[sig].sa_handler != SIG_DFL) {		sigact[sig].sa_sigaction(sig, NULL, NULL);	}	/* shall we reenable here? */	return 0;}/* Thread signals added. */ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact){#ifdef CONFIG_OC_PSIGNALS   int flags;#endif	int irq = -1;	if (act && (act->sa_flags & SA_IRQ)) {		irq = sig;	} else {	  /* for now, only hard global interrupts 	     & thread signals from RTL_SIGNAL_READY+1 to  	     RTL_MAX_SIGNAL 	  */	  if (sig <= RTL_SIGNAL_READY || (sig > RTL_MAX_SIGNAL && sig < RTL_SIGIRQMIN) || sig >= RTL_SIGIRQMIN + NR_IRQS) {			errno = EINVAL;			return -1;		}		irq = sig - RTL_SIGIRQMIN;	}	if (oact) {		*oact = sigact[sig];	  /*hard global interrupts */	  if (sig > RTL_MAX_SIGNAL)		rtl_irq_set_affinity(irq, NULL, &oact->sa_focus);	}	if (!act) {		return 0;	}	/*hard global interrupts */	if (sig > RTL_MAX_SIGNAL){	if (sigact[sig].sa_handler != act->sa_handler) {		/* free old irq first if needed */		if (sigact[sig].sa_handler != SIG_IGN				&& sigact[sig].sa_handler != SIG_DFL) {	      /* 			rtl_printf("freeing %d\n", sig - RTL_SIGIRQMIN); */			rtl_free_global_irq (irq);		}		/* now request */		if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL) {			sigact[sig] = *act;	      /* 			rtl_printf("requesting %d\n", sig - RTL_SIGIRQMIN); */			rtl_request_global_irq (irq, rtl_sig_interrupt);		}	}	  if ( act->sa_flags & SA_FOCUS) {		rtl_irq_set_affinity (irq, &act->sa_focus, NULL);	}	}	/*End hard global interrupts */#ifdef CONFIG_OC_PSIGNALS 	rtl_no_interrupts(flags);#endif	sigact[sig].sa_handler = act->sa_handler;#ifdef CONFIG_OC_PSIGNALS 	if (sig > RTL_SIGNAL_READY && sig <= RTL_MAX_SIGNAL ){	  if (sigact[sig].sa_handler == SIG_IGN	      || sigact[sig].sa_handler == SIG_DFL){	    sigact[sig].sa_handler = NULL;	  }	}#endif	sigact[sig].sa_flags = act->sa_flags;	sigact[sig].sa_focus = act->sa_focus;	sigact[sig].sa_mask = act->sa_mask;#ifdef CONFIG_OC_PSIGNALS 	sigact[sig].owner = pthread_self();	rtl_restore_interrupts(flags);#endif		return 0;}#ifdef CONFIG_OC_PSIGNALS int pthread_sigmask(int how, const rtl_sigset_t *set, rtl_sigset_t *oset){  pthread_t self=pthread_self();  int err=0,flags;    if (oset) *oset=self->blocked;  if (!set) return EFAULT;   /*    With pthread_sigmask RTLINUX scheduler signals can't be blocked    or unblocked. For this reason the RTL_THREAD_SIGNALS_MASK is     applied.  */  rtl_no_interrupts(flags);  switch (how){  case SIG_SETMASK:    self->blocked=( self->blocked & ~RTL_THREAD_SIGNALS_MASK) |       (RTL_THREAD_SIGNALS_MASK & *set);    break;  case SIG_BLOCK:    self->blocked=( self->blocked & ~RTL_THREAD_SIGNALS_MASK) |       (RTL_THREAD_SIGNALS_MASK & (self->blocked | *set));    break;  case SIG_UNBLOCK:    self->blocked=( self->blocked & ~RTL_THREAD_SIGNALS_MASK) |       (RTL_THREAD_SIGNALS_MASK & (self->blocked & ~(*set)));    break;  default:    rtl_restore_interrupts(flags);    return EINVAL;  }  rtl_restore_interrupts(flags);  return err;} int sigsuspend(const rtl_sigset_t *sigmask){  rtl_sigset_t oset;  int flags;  pthread_t self=pthread_self();  if (!sigmask) {    errno=EFAULT;    return -1;  }  rtl_no_interrupts(flags);  // Backup old mask.  oset=self->blocked;  /*    Instaure new.    With pthread_sigmask RTLINUX scheduler signals can't be blocked    or unblocked.         0 .. 6 from oset, 7 .. 31 to 0 OR     0 .. 6 to 0, 7 .. 31 from sigmask      */  self->blocked= (oset & ~RTL_THREAD_SIGNALS_MASK) | (*sigmask & RTL_THREAD_SIGNALS_MASK) ;  // Mark as interrumpible by a signal.  set_bit(RTL_THREAD_SIGNAL_INTERRUMPIBLE,&self->threadflags);  // Suspend calling thread until a signal arrives.  pthread_suspend_np(self);      // do_user_signal clears the bit RTL_THREAD_SIGNAL_INTERRUMPIBLE from threadflags.  if (!test_and_clear_bit(RTL_THREAD_SIGNAL_INTERRUMPIBLE,&self->threadflags)){    errno=EINTR;  }  // Restore thread blocked set.  self->blocked=oset;  rtl_restore_interrupts(flags);   return -1;}int sigpending(rtl_sigset_t *set){  if (set){    *set=pthread_self()->pending;	return 0;  } else {    errno=EFAULT;    return -1;  }    }#endif	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?