📄 signal.cxx
字号:
// This is a standard signal delivery.
CYG_CHECK_FUNC_PTR( ss->sa.sa_handler,
"Bad sa_handler signal handler" );
ss->sa.sa_handler( signo );
}
// Relock the mutex
signal_mutex.lock();
// Restore original signal mask
self->sigmask = oldmask;
// return that we have handled a signal
res = true;
}
}
if( !locked ) signal_mutex.unlock();
return res;
}
// -------------------------------------------------------------------------
// Utility routine to signal any threads waiting in sigwait*().
void cyg_posix_signal_sigwait()
{
signal_sigwait.broadcast();
}
// -------------------------------------------------------------------------
// Action routine called from kernel alarm to deliver the SIGALRM signal.
// We cannot call any signal delivery functions directly here, so we simply
// set a flag and schedule an ASR to be called.
static void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data )
{
sigset_t mask;
sigalrm_armed = false;
sigalrm_pending = true;
sigemptyset( &mask );
sigaddset( &mask, SIGALRM );
// Wake up any threads in sigsuspend() and sigwait() in case they
// are waiting for an alarm, and would have SIGALRM masked
signal_sigwait.broadcast();
cyg_posix_pthread_release_thread( &mask );
}
// -------------------------------------------------------------------------
// Check for SIGALRMs. This is called from the ASR and sigtimedwait()
// as alarms need to be handled as a special case.
static __inline__ void check_sigalarm(void)
{
// If there is a pending SIGALRM, generate it
if( sigalrm_pending )
{
sigalrm_pending = false;
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGALRM;
sev.sigev_value.sival_int = 0;
// generate the signal
cyg_sigqueue( &sev, SI_USER );
}
}
// -------------------------------------------------------------------------
// signal ASR function. This is called from the general POSIX ASR to
// deal with any signal related issues.
externC void cyg_posix_signal_asr(pthread_info *self)
{
check_sigalarm();
// Now call cyg_deliver_signals() to see if we can
// handle any signals now.
cyg_deliver_signals();
}
//==========================================================================
// Per-thread initialization and destruction
externC void cyg_posix_thread_siginit( pthread_info *thread,
pthread_info *parentthread )
{
// Clear out signal masks
sigemptyset( &thread->sigpending );
// but threads inherit signal masks
if ( NULL == parentthread )
sigemptyset( &thread->sigmask );
else
thread->sigmask = parentthread->sigmask;
cyg_pthread_exception_init( thread );
}
externC void cyg_posix_thread_sigdestroy( pthread_info *thread )
{
cyg_pthread_exception_destroy( thread );
}
//==========================================================================
// Functions to generate signals
// -------------------------------------------------------------------------
// Deliver sig to a process.
// eCos only supports the value 0 for pid.
externC int kill (pid_t pid, int sig)
{
SIGNAL_ENTRY();
if( !SIGNAL_VALID(sig) )
SIGNAL_RETURN(EINVAL);
if( pid != 0 )
SIGNAL_RETURN(ESRCH);
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = sig;
sev.sigev_value.sival_int = 0;
cyg_sigqueue( &sev, SI_USER );
cyg_deliver_signals();
SIGNAL_RETURN(0);
}
// -------------------------------------------------------------------------
externC int pthread_kill (pthread_t threadid, int sig)
{
SIGNAL_ENTRY();
if( !SIGNAL_VALID(sig) )
SIGNAL_RETURN(EINVAL);
struct sigevent sev;
pthread_info *thread = pthread_info_id(threadid);
if( thread == NULL )
SIGNAL_RETURN(ESRCH);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = sig;
sev.sigev_value.sival_int = 0;
cyg_sigqueue( &sev, SI_USER, thread );
cyg_deliver_signals();
SIGNAL_RETURN(0);
}
//==========================================================================
// Functions to catch signals
// -------------------------------------------------------------------------
// Install signal handler for sig.
externC int sigaction (int sig, const struct sigaction *act,
struct sigaction *oact)
{
SIGNAL_ENTRY();
if( !SIGNAL_VALID(sig) )
SIGNAL_RETURN(EINVAL);
signal_state *ss = &sigstate[sig];
signal_mutex.lock();
if( oact != NULL )
*oact = ss->sa;
ss->sa = *act;
if( ss->sa.sa_handler == SIG_IGN )
{
// Setting the handler to SIG_IGN causes any pending
// signals to be discarded and any queued values to also
// be removed.
pthread_info *self = pthread_self_info();
sigset_t sigbit = 1<<sig;
if( (sig_pending | self->sigpending) & sigbit )
{
// This signal is pending, clear it
sig_pending &= ~sigbit;
self->sigpending &= ~sigbit;
// Clean out any queued signal_info objects
while( ss->pending != NULL )
{
signal_info *si = ss->pending->next;
// Remove the head signal_info object from the
// circular list.
if( ss->pending == si )
ss->pending = NULL;
else
ss->pending->next = si->next;
// Return it to the free list
si->next = siginfo_next;
siginfo_next = si;
}
}
}
cyg_deliver_signals();
signal_mutex.unlock();
SIGNAL_RETURN(0);
}
// -------------------------------------------------------------------------
// Queue signal to process with value.
externC int sigqueue (pid_t pid, int sig, const union sigval value)
{
SIGNAL_ENTRY();
if( !SIGNAL_VALID(sig) )
SIGNAL_RETURN(EINVAL);
struct sigevent sev;
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = sig;
sev.sigev_value = value;
cyg_sigqueue( &sev, SI_QUEUE );
cyg_deliver_signals();
SIGNAL_RETURN(0);
}
//==========================================================================
// Functions to deal with current blocked and pending masks
// -------------------------------------------------------------------------
// Set process blocked signal mask
// Map this onto pthread_sigmask().
externC int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
{
return pthread_sigmask( how, set, oset);
}
// -------------------------------------------------------------------------
// Set calling thread's blocked signal mask
externC int pthread_sigmask (int how, const sigset_t *set, sigset_t *oset)
{
int err = 0;
SIGNAL_ENTRY();
pthread_info *self = pthread_self_info();
// Save old set
if( oset != NULL )
*oset = self->sigmask;
if( set != NULL )
{
switch( how )
{
case SIG_BLOCK:
self->sigmask |= *set;
break;
case SIG_UNBLOCK:
self->sigmask &= ~*set;
break;
case SIG_SETMASK:
self->sigmask = *set;
break;
default:
err = EINVAL;
break;
}
}
// Deliver any newly unblocked signals
cyg_deliver_signals();
SIGNAL_RETURN(err);
}
// -------------------------------------------------------------------------
// Exported routine to set calling thread's blocked signal mask
//
// Optionally set and return the current thread's signal mask. This is
// exported to other packages so that they can manipulate the signal
// mask without necessarily having them delivered (as calling
// pthread_sigmask() would). Signals can be delivered by calling
// cyg_posix_deliver_signals().
externC void cyg_pthread_sigmask_set (const sigset_t *set, sigset_t *oset)
{
pthread_info *self = pthread_self_info();
if( self != NULL )
{
if( oset != NULL )
*oset = self->sigmask;
if( set != NULL )
self->sigmask = *set;
}
}
// -------------------------------------------------------------------------
// Exported routine to test for any pending signals.
//
// This routine tests for any pending undelivered, unmasked
// signals. If there are any it returns true. This is exported to
// other packages, such as FILEIO, so that they can detect whether to
// abort a current API call with an EINTR result.
externC cyg_bool cyg_posix_sigpending(void)
{
pthread_info *self = pthread_self_info();
if( self == NULL )
return false;
return ( ((sig_pending | self->sigpending) & ~self->sigmask) != 0 );
}
// -------------------------------------------------------------------------
// Exported routine to deliver selected signals
//
// This routine optionally sets the given mask and then tries to
// deliver any pending signals that have been unmasked. This is
// exported to other packages so that they can cause signals to be
// delivered at controlled points during execution.
externC void cyg_posix_deliver_signals( const sigset_t *mask )
{
sigset_t oldmask;
pthread_info *self = pthread_self_info();
if( self != NULL )
{
if( mask != NULL )
{
oldmask = self->sigmask;
self->sigmask = *mask;
}
else
oldmask = 0; // silence warning
cyg_deliver_signals();
if( mask != NULL )
self->sigmask = oldmask;
}
}
// -------------------------------------------------------------------------
// Get set of pending signals for this process
externC int sigpending (sigset_t *set)
{
SIGNAL_ENTRY();
if( set == NULL )
SIGNAL_RETURN(EINVAL);
pthread_info *self = pthread_self_info();
*set = self->sigpending | sig_pending;
SIGNAL_RETURN(0);
}
//==========================================================================
// Wait for or accept signals
// -------------------------------------------------------------------------
// Block signals in set and wait for a signal
externC int sigsuspend (const sigset_t *set)
{
SIGNAL_ENTRY();
pthread_info *self = pthread_self_info();
signal_mutex.lock();
// Save the old mask and set the current mask to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -