/*---------------------------------------------------------------------------* Project: Horizon File: os_LightEvent.cpp Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 16480 $ *--------------------------------------------------------------------------- */ #include //--------------------------------------------------------------------------- namespace nn { namespace os { // Gets whether the flag is set. bool LightEvent::TryWait() { if( *m_Counter == SIGNALED_MANUAL ) { // Since it is a manual reset, do not reset the flag. return true; } else { // If a flag is set, the flag is reset and true is returned. return m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO; } } // Waits until the flag is set. void LightEvent::Wait() { for(;;) { switch( *m_Counter ) { // Waits until flag is set, does not clear flag. case NOT_SIGNALED_MANUAL: m_Counter.WaitIfLessThan(0); return; // Does not wait because flag is set. case SIGNALED_MANUAL: return; // Waits because flag is not set. case NOT_SIGNALED_AUTO: break; // Does not wait because flag is set. Reset flag. case SIGNALED_AUTO: { if( m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO ) { return; } } break; } // Waits until the flag is set // If the flag is set, m_Counter changes from NOT_SIGNALED_AUTO to SIGNALED_AUTO. m_Counter.WaitIfLessThan(0); } } // Set flag. void LightEvent::Signal() { if( *m_Counter == NOT_SIGNALED_AUTO ) { *m_Counter = SIGNALED_AUTO; // For automatic reset, wake up high priority threads. // At the same time the thread is awakened, the flag is reset. m_Counter.Signal(1); } else if( *m_Counter == NOT_SIGNALED_MANUAL ) { *m_Counter = SIGNALED_MANUAL; // For manual reset, wake up all standby threads. // Even if the thread is awakened, the flag is not reset. m_Counter.SignalAll(); } // If there are no threads on standby, the flag does not change. } // Releases threads waiting for the flag to be set. void LightEvent::Pulse() { switch( *m_Counter ) { case SIGNALED_MANUAL: *m_Counter = NOT_SIGNALED_MANUAL; // not break case NOT_SIGNALED_MANUAL: // Wakes up all threads waiting for the flag to be set. // At the same time the thread is awakened, the flag is reset. m_Counter.SignalAll(); break; case NOT_SIGNALED_AUTO: // Wakes up the highest priority thread of the threads waiting for the flag to be set. // // At the same time the thread is awakened, the flag is reset. m_Counter.Signal(1); break; case SIGNALED_AUTO: // Reset flag. *m_Counter = NOT_SIGNALED_AUTO; break; } } // Clear flag. void LightEvent::ClearSignal() { if( *m_Counter == SIGNALED_MANUAL ) { *m_Counter = NOT_SIGNALED_MANUAL; } else if( *m_Counter == SIGNALED_AUTO ) { *m_Counter = NOT_SIGNALED_AUTO; } } } } using namespace nn; // C Function Definitions #include using namespace nn::os; extern "C" { void nnosLightEventInitialize(nnosLightEvent* p, bool isManualReset) { new (p) LightEvent(isManualReset); } bool nnosLightEventIsSignaled(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->IsSignaled(); } bool nnosLightEventIsManualReset(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->IsManualReset(); } bool nnosLightEventTryWait(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); return pLightEvent->TryWait(); } void nnosLightEventWait(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Wait(); } void nnosLightEventSignal(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Signal(); } void nnosLightEventPulse(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Pulse(); } void nnosLightEventClearSignal(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->ClearSignal(); } void nnosLightEventFinalize(nnosLightEvent* p) { LightEvent* pLightEvent = reinterpret_cast(p); pLightEvent->Finalize(); pLightEvent->~LightEvent(); } } // extern "C"