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

📄 signal.cxx

📁 ecos实时嵌入式操作系统
💻 CXX
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      signal.cxx////      POSIX signal functions implementation////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Nick Garnett//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):           nickg// Contributors:        nickg// Date:                2000-03-27// Purpose:             POSIX signal functions implementation// Description:         This file contains the implementation of the POSIX signal//                      functions.//              //              ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/posix.h>#ifdef CYGPKG_POSIX_SIGNALS#include <pkgconf/hal.h>#include <pkgconf/kernel.h>#include <pkgconf/isoinfra.h>#include <cyg/kernel/ktypes.h>          // base kernel types#include <cyg/infra/cyg_trac.h>         // tracing macros#include <cyg/infra/cyg_ass.h>          // assertion macros#include "pprivate.h"                   // POSIX private header#include <signal.h>                     // our header#include <setjmp.h>#include <unistd.h>                     // _exit#include <cyg/kernel/clock.hxx>#include <cyg/kernel/thread.hxx>#include <cyg/kernel/clock.inl>#include <cyg/kernel/thread.inl>// -------------------------------------------------------------------------// Internal definitions// Handle entry to a signal package function. #define SIGNAL_ENTRY() CYG_REPORT_FUNCTYPE( "returning %d" );// Do a signal package defined return. This requires the error code// to be placed in errno, and if it is non-zero, -1 returned as the// result of the function. This also gives us a place to put any// generic tidyup handling needed for things like signal delivery and// cancellation.#define SIGNAL_RETURN(err)                      \CYG_MACRO_START                                 \    int __retval = 0;                           \    if( err != 0 ) __retval = -1, errno = err;  \    CYG_REPORT_RETVAL( __retval );              \    return __retval;                            \CYG_MACRO_END// Similarly for functions that have valid non-zero returns#define SIGNAL_RETURN_VALUE(val)                \CYG_MACRO_START                                 \    CYG_REPORT_RETVAL( val );                   \    return val;                                 \CYG_MACRO_END// Range check on a signal value.#define SIGNAL_VALID(_sig_) (((_sig_) > 0) && ((_sig_) < ((int)sizeof(sigset_t)*8)))//==========================================================================// Signal management structurestypedef struct signal_info{    struct signal_info          *next;  // link in list of pending signals    siginfo_t                   si;     // siginfo to pass to handler} signal_info;typedef struct{    struct sigaction            sa;     // Sigaction defining what to do    signal_info                 *pending; // List of pending signals - this is                                          // a circular list with pending pointing                                          // to the tail element (or NULL if empty).} signal_state;//==========================================================================// Signal management variables// Lock used to protect signal management structuresCyg_Mutex signal_mutex CYGBLD_POSIX_INIT;// Condition variable for all threads in sigsuspend() and sigwait()// to wait on.Cyg_Condition_Variable signal_sigwait( signal_mutex ) CYGBLD_POSIX_INIT;// Global pending signal setsigset_t sig_pending;// Array controlling signal statesstatic signal_state sigstate[sizeof(sigset_t)*8];// Array of available signal_info objects for queueing signalsstatic signal_info siginfo[SIGQUEUE_MAX];// List of free signal_info objectsstatic signal_info *siginfo_next = NULL;//==========================================================================// Variables used to support alarm()// Forward def of action functionstatic void sigalrm_action( Cyg_Alarm *alarm, CYG_ADDRWORD data );// Kernel alarm objectstatic Cyg_Alarm sigalrm_alarm( Cyg_Clock::real_time_clock, sigalrm_action, 0 ) CYGBLD_POSIX_INIT;// Set true when alarm is armedvolatile cyg_bool sigalrm_armed = false;// Set true when alarm has fired and is waiting to be deliveredvolatile cyg_bool sigalrm_pending = false;//==========================================================================// Implementation functions.// These are where the real work of the signal mechanism gets done.externC void cyg_posix_signal_start(){    // Chain all free signal_info objects together    for( int i = 0; i < SIGQUEUE_MAX; i++ )    {        siginfo[i].next = siginfo_next;        siginfo_next = &siginfo[i];    }        // initialize all signal actions to SIG_DFL    for ( unsigned int i=0; i<(sizeof(sigstate)/sizeof(signal_state)); i++ )    {        sigstate[i].sa.sa_handler = SIG_DFL;    }    // Clear the pending signal set    sigemptyset( &sig_pending );}// -------------------------------------------------------------------------// Generate a signalcyg_bool cyg_sigqueue( const struct sigevent *sev, int code,                       pthread_info *thread ){    if( sev->sigev_notify == SIGEV_NONE )    {        // Do nothing        return true;    }    if( sev->sigev_notify == SIGEV_THREAD )    {        // create a thread to run the notification        // function.        // FIXME: implement SIGEV_THREAD        return true;    }    // Otherwise we must have a SIGEV_SIGNAL notification    // Find out whether the current thread already has the mutex    // locked. This is a distinct possibility if this function is    // called from the ASR while exiting the signal_sigwait condvar in    // pause() and sigtimedwait().        pthread_info *self = pthread_self_info();    cyg_bool locked = (self != NULL) && (signal_mutex.get_owner() == self->thread);        // Lock the mutex only if we do not already own it    if( !locked ) signal_mutex.lock();        int signo = sev->sigev_signo;    signal_state *ss = &sigstate[signo];    if( ss->sa.sa_flags & SA_SIGINFO )    {        // We have a queuable signal, allocate a signal_info        // object and add it to the queue.        if( siginfo_next == NULL )        {            if( !locked ) signal_mutex.unlock();            return false;        }        signal_info *si = siginfo_next;        siginfo_next = si->next;        si->si.si_signo = signo;        si->si.si_code = code;        si->si.si_value = sev->sigev_value;        if( ss->pending == NULL )        {            si->next = si;        }        else        {            si->next = ss->pending->next;            ss->pending->next = si;        }                    ss->pending = si;    }    // else A non-queuable signal, just set it pending    if( thread != NULL )    {        sigaddset( &thread->sigpending, signo );        // just wake the thread up now if it's blocked somewhere        if ((thread->sigpending & ~thread->sigmask) != 0)        {            thread->thread->set_asr_pending();            thread->thread->release();        }    }    else    {        sigaddset( &sig_pending, signo );        // Wake up any threads in sigsuspend() and sigwait().        if (!signal_sigwait.get_queue()->empty())        {            signal_sigwait.broadcast();        }         else        {            cyg_posix_pthread_release_thread( &sig_pending );        }    }    if( !locked ) signal_mutex.unlock();        return true;}// -------------------------------------------------------------------------// Deliver any pending unblocked signals to the current thread// Returns true if a signal handler was called.cyg_bool cyg_deliver_signals(){    cyg_bool res = false;        pthread_info *self = pthread_self_info();    // If there is no pthread_info pointer for this thread then    // it is not a POSIX thread and cannot have signals delivered    // to it.        if( self == NULL ) return false;        // If there are no pending signals our work is done    if( sig_pending == 0 && self->sigpending == 0 )        return false;    // If there are no unmasked pending signals our    // work is also done    if( ((sig_pending | self->sigpending) & ~self->sigmask) == 0 )        return false;    // As with cyg_sigqueue(), this function can get called from an    // ASR where the signal_mutex is already locked. Check here to    // avoid relocking...        cyg_bool locked = signal_mutex.get_owner() == self->thread;        if( !locked ) signal_mutex.lock();            sigset_t todo;    // Since a signal handler may raise another signal, or unmask an existing    // signal, we loop here while there are no more unblocked signals pending.    while( (todo = ((sig_pending | self->sigpending) & ~self->sigmask)) != 0 )    {        // Here todo is a mask of the signals available for delivery                int signo = 0;        // This prioritizes low numbered signals        HAL_LSBIT_INDEX( signo, todo );        signal_state *ss = &sigstate[signo];        sigset_t sigbit = 1L<<signo;        if( ss->sa.sa_handler != SIG_IGN )        {            sigset_t oldmask = self->sigmask;            siginfo_t lsi;            if(ss->pending != NULL)            {                // There is a queued signal. Dequeue it and copy the                // siginfo object to a local copy.                                signal_info *si = ss->pending->next;                                    // Make a local copy of the siginfo object                lsi = si->si;                                    // 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;            }            else            {                // There are no signals queued. Set up the local siginfo_t                // object with default values.                 lsi.si_signo = signo;                lsi.si_code = SI_USER;                lsi.si_value.sival_int = 0;            }                        // Clear the bit from the pending masks. If the pending            // queue is not empty, leave the bits set, otherwise clear            // them. Do this now so that if the signal handler longjumps            // out, the signal subsystem is clean.                    if( ss->pending == NULL )            {                // Clear the bit in both masks regardless of which                // one it actually came from. This is cheaper than                // trying to find out.                sig_pending &= ~sigbit;                self->sigpending &= ~sigbit;            }            // Add the mask set and the signal itself to the            // mask while we call the signal handler            self->sigmask = oldmask | ss->sa.sa_mask | sigbit;                        // Unlock now so that a longjmp out of the handler            // does the right thing. We do this even if we did not            // lock the mutex since it will only recently have been            // relocked and thus all data is still consistent.                            signal_mutex.unlock();                        if( ss->sa.sa_flags & SA_SIGINFO )            {                // A sigaction delivery                CYG_CHECK_FUNC_PTR( ss->sa.sa_sigaction,                                    "Bad sa_sigaction signal handler" );                ss->sa.sa_sigaction( signo, &lsi, NULL );            }            else if ( ss->sa.sa_handler == SIG_DFL )            {                CYG_TRACE2( true,                            "Unhandled POSIX signal: sig=%d, mask=%08x",                            signo, oldmask );                // FIXME: should do something better here#if CYGINT_ISO_EXIT                _exit( -signo );#endif                CYG_FAIL("Unhandled POSIX signal");            }                        else            {

⌨️ 快捷键说明

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