⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.cxx

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 CXX
📖 第 1 页 / 共 3 页
字号:
                // 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 + -