OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [compat/] [posix/] [v2_0/] [src/] [except.cxx] - Rev 174

Compare with Previous | Blame | View Log

//==========================================================================
//
//      except.cxx
//
//      POSIX exception translation
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// 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 exception translation
// Description:         This file contains code to translate eCos hardware
//                      exceptions into POSIX signals.
//              
//              
//
//####DESCRIPTIONEND####
//
//==========================================================================
 
#include <pkgconf/hal.h>
#include <pkgconf/kernel.h>
#include <pkgconf/posix.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 <cyg/infra/diag.h>
 
#include "pprivate.h"                   // POSIX private header
 
#include <signal.h>                     // our header
 
#include <cyg/kernel/thread.inl>
 
//==========================================================================
// Translation table from eCos exceptions to POSIX signals.
 
static const struct
{
    cyg_code    exception;
    int         signal;
} exception_signal_mapping[] =
{
#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
    {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
    {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
    {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
    {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
    {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
    {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
    {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
    {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
    {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
    {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
    {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
    {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
    {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
    {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
    {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
    {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
    {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
    {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
    {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
    {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
    {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_TRAP
    {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
    {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
    {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE},
#endif    
#ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
    {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
    {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
    {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
    {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
    {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
    {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
    {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
    {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_PARITY
    {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU
    {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
    {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
    {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
    {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
    {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE},
#endif
#ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
    {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS},
#endif
    {0, 0} // dummy value to ensure compiler is happy
};
 
//==========================================================================
// POSIX exception handler
 
static void cyg_posix_exception_handler(
    CYG_ADDRWORD        data,                   // user supplied data == signal number
    cyg_code            exception_number,       // exception being raised
    CYG_ADDRWORD        exception_info          // any exception specific info
    )
{
    int signo = 0;
 
    pthread_info *self = pthread_self_info();
 
    if( self == NULL )
    {
        // Not a POSIX thread, just return
        return;
    }
 
#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
 
    signo = data;
 
#else
 
    for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )    
    {
        if( exception_signal_mapping[i].exception == exception_number )
        {
            signo = exception_signal_mapping[i].signal;
            break;
        }
    }
 
#endif
 
    if( sigismember( &self->sigmask, signo ) )
    {
        // The signal is masked in the current thread. POSIX says that
        // the behaviour is undefined here. We choose to ignore it.
 
        return;
    }
 
    // The kernel exception handler may have disabled interrupts, so
    // we (re-)enable them here. From this point on we are running in
    // a context that is effectively just pushed onto the stack of the
    // current thread. If we return we will unwind and resume
    // execution from the excepting code. We can also, in theory,
    // longjump out of the signal handler, and although that is
    // deprecated, we make sure in cyg_deliver_signals() that it is
    // possible to do it.
 
    HAL_ENABLE_INTERRUPTS();
 
    struct sigevent sev;
 
    sev.sigev_notify           = SIGEV_SIGNAL;
    sev.sigev_signo            = signo;
    sev.sigev_value.sival_ptr  = (void *)exception_info;
 
    // Generate the signal
    cyg_sigqueue( &sev, SI_EXCEPT );
 
    // And try to deliver it
    cyg_deliver_signals();
}
 
//==========================================================================
// Install all the exception handlers
 
static void install_handlers( Cyg_Thread *thread)
{
#ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
 
    // With decoded exceptions, we must install a separate exception
    // handler for each supported exception.
 
    for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
    {
        thread->register_exception( exception_signal_mapping[i].exception,
                                    cyg_posix_exception_handler,
                                    exception_signal_mapping[i].signal,,
                                    NULL,
                                    NULL);
    }
 
#else
 
    // Otherwise there is just one exception handler for all exceptions.
 
    thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN,
                                cyg_posix_exception_handler,
                                0,
                                NULL,
                                NULL);
 
#endif    
 
}
 
//==========================================================================
// Initialization
 
externC void cyg_posix_exception_start()
{
#ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
 
    // With global exceptions, we only need to install a single static
    // set of exception handlers. Note that by this point in system
    // initialization the idle thread should be installed as the
    // current thread, so we pass a pointer to that to
    // install_handlers(). The identity of the thread passed is
    // actually irrelevant in this case and is just used as a handle
    // into the thread class.
 
    install_handlers( Cyg_Thread::self() );
 
#endif    
}
 
//==========================================================================
// Per thread exception initialization and destruction
 
externC void cyg_pthread_exception_init(pthread_info *thread)
{
#ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
 
    // With non-global exceptions we must install a new set of handlers
    // for each thread.
 
    install_handlers( thread->thread );
 
#endif
}
 
externC void cyg_pthread_exception_destroy(pthread_info *thread)
{
    // Nothing to do at present.
}
 
// -------------------------------------------------------------------------
// EOF except.cxx
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.