コード例 #1
0
/**
 * Used to initialize static objects only once, in a threadsafe way
 * \param g guard struct
 * \return 0 if object already initialized, 1 if this thread has to initialize
 * it, or lock if another thread has already started initializing it
 */
extern "C" int __cxa_guard_acquire(__guard *g)
{
    miosix::InterruptDisableLock dLock;
    volatile MiosixGuard *guard=reinterpret_cast<volatile MiosixGuard*>(g);
    for(;;)
    {
        if(guard->flag==1) return 0; //Object already initialized, good
        
        if(guard->flag==0)
        {
            //Object uninitialized, and no other thread trying to initialize it
            guard->owner=miosix::Thread::IRQgetCurrentThread();

            //guard->owner serves the double task of being the thread id of
            //the thread initializing the object, and being the flag to signal
            //that the object is initialized or not. If bit #0 of guard->owner
            //is @ 1 the object is initialized. All this works on the assumption
            //that Thread* pointers never have bit #0 @ 1, and this assetion
            //checks that this condition really holds
            if(guard->flag & 1) miosix::errorHandler(miosix::UNEXPECTED);
            return 1;
        }

        //If we get here, the object is being initialized by another thread
        if(guard->owner==miosix::Thread::IRQgetCurrentThread())
        {
            //Wait, the other thread initializing the object is this thread?!?
            //We have a recursive initialization error. Not throwing an
            //exception to avoid pulling in exceptions even with -fno-exception
            IRQerrorLog("Recursive initialization\r\n");
            _exit(1);
        }

        {
            miosix::InterruptEnableLock eLock(dLock);
            miosix::Thread::yield(); //Sort of a spinlock, a "yieldlock"...
        }
    }
}
コード例 #2
0
ファイル: error.cpp プロジェクト: degrigis/polimi_projects
void errorHandler(Error e)
{
    // Here we must be careful since this function can be called within an
    // interrupt routine, and disabling interrupts within an interrupt
    // routine must be avoided.
    bool interrupts=areInterruptsEnabled();
    if(interrupts) disableInterrupts();

    bool isUnrecoverable=false;
    //Recoverable errors
    switch(e)
    {
    case INVALID_PARAMETERS:
        IRQerrorLog("\r\n***Invalid parameter\r\n");
        break;
    case PROPAGATED_EXCEPTION:
        IRQerrorLog("\r\n***An exception propagated through a thread\r\n");
        break;
    case MUTEX_UNLOCK_NOT_OWNER:
        IRQerrorLog("\r\n***unlock() called on a non locked mutex\r\n");
    default:
        isUnrecoverable=true;
    }
    //Unrecoverable errors
    switch(e)
    {

    case OUT_OF_MEMORY:
        IRQerrorLog("\r\n***Out of memory\r\n");
        break;
    case STACK_OVERFLOW:
        IRQerrorLog("\r\n***Stack overflow\r\n");
        break;
    case UNEXPECTED:
        IRQerrorLog("\r\n***Unexpected error\r\n");
        break;
    case PAUSE_KERNEL_NESTING:
        IRQerrorLog("\r\n***Pause kernel nesting\r\n");
        break;
    case DISABLE_INTERRUPTS_NESTING:
        IRQerrorLog("\r\n***Disable interrupt nesting\r\n");
        break;
    case MUTEX_DEADLOCK:
        IRQerrorLog("\r\n***Deadlock\r\n");
        break;
    case NESTING_OVERFLOW:
        IRQerrorLog("\r\n***Nesting overflow\r\n");
        break;
    case INTERRUPTS_ENABLED_AT_BOOT:
        IRQerrorLog("\r\n***Interrupts enabled at boot\r\n");
        break;
    default:
        break;
    }
    if(isUnrecoverable) miosix_private::IRQsystemReboot();
    if(interrupts) enableInterrupts();
}