/*---------------------------------------------------------------------------* Project: Horizon File: os_InterCoreLightSemaphore.h 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: 33107 $ *---------------------------------------------------------------------------*/ #ifndef NN_OS_OS_INTERCORE_LIGHTSEMAPHORE_H_ #define NN_OS_OS_INTERCORE_LIGHTSEMAPHORE_H_ #ifdef __cplusplus #include #include #include #include #include #include namespace nn { namespace os { /* Please see man pages for details */ /* Please see man pages for details */ class InterCoreLightSemaphore { public: static const s32 MAX_MAX_COUNT = 0x7fff; private: struct DecrementIfPositive { bool operator()(s32& x) { if( x > 0 ) { --x; return true; } else { return false; } } }; struct LimitedAdd { s32 max; s32 value; s32 beforeUpdate; bool operator()(s32& x) { beforeUpdate = x; if( x > max - value ) { x = max; } else { x += value; } return true; } }; private: WaitableCounter m_Counter; #if NN_PLATFORM_HAS_16BIT_LL_SC fnd::InterlockedVariable m_NumWaiting; s16 m_Max; #else fnd::InterlockedVariable m_NumWaiting; #endif public: //---------------------------------------- // // /* Please see man pages for details */ InterCoreLightSemaphore() {} /* Please see man pages for details */ InterCoreLightSemaphore(s32 initialCount, s32 maxCount) { Initialize(initialCount, maxCount); } InterCoreLightSemaphore(s32 initialCount) { Initialize(initialCount); } /* Please see man pages for details */ void Initialize(s32 initialCount, s32 maxCount) { NN_MIN_TASSERT_( initialCount, 0 ); NN_MIN_TASSERT_( maxCount, 1 ); NN_MAX_TASSERT_( initialCount, maxCount ); NN_MAX_TASSERT_( maxCount, MAX_MAX_COUNT ); *m_Counter = initialCount; m_NumWaiting = 0; #if NN_PLATFORM_HAS_16BIT_LL_SC m_Max = maxCount; #else NN_UNUSED_VAR(maxCount); #endif } void Initialize(s32 initialCount) { Initialize(initialCount, MAX_MAX_COUNT); } /* Please see man pages for details */ void Finalize() {} // //---------------------------------------- // // /* Please see man pages for details */ #if NN_PLATFORM_HAS_16BIT_LL_SC s32 GetMax() const { return m_Max; } #endif /* Please see man pages for details */ s32 GetCount() const { return *m_Counter; } // //---------------------------------------- // // /* Please see man pages for details */ void Acquire() { while( ! TryAcquire() ) { ++m_NumWaiting; m_Counter.WaitIfLessThan(1); --m_NumWaiting; } } /* Please see man pages for details */ bool TryAcquire() { DecrementIfPositive updater; bool ret = m_Counter->AtomicUpdateConditional(updater); DataSynchronizationBarrier(); return ret; } /* Please see man pages for details */ s32 Release(s32 releaseCount = 1); // class ScopedAcquire { private: InterCoreLightSemaphore* m_Semaphore; public: ScopedAcquire(InterCoreLightSemaphore& semaphore, bool wait = true) : m_Semaphore(wait ? (semaphore.Acquire(), &semaphore) : (semaphore.TryAcquire() ? &semaphore : 0)) {} bool Aquired() const { return m_Semaphore != 0; } void Detach() { this->m_Semaphore = 0; } ~ScopedAcquire() { if (m_Semaphore) { m_Semaphore->Release(); } } }; }; }} // namespace nn::os #endif // __cplusplus // C declarations follow #include NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosInterCoreLightSemaphore, nn::os::InterCoreLightSemaphore, 8, u32); NN_EXTERN_C void nnosInterCoreLightSemaphoreInitialize(nnosInterCoreLightSemaphore* this_, s32 initialCount, s32 maxCount); #if NN_PLATFORM_HAS_16BIT_LL_SC NN_EXTERN_C s32 nnosInterCoreLightSemaphoreGetMax(nnosInterCoreLightSemaphore* p); #endif NN_EXTERN_C s32 nnosInterCoreLightSemaphoreGetCount(nnosInterCoreLightSemaphore* p); NN_EXTERN_C s32 nnosInterCoreLightSemaphoreRelease(nnosInterCoreLightSemaphore* this_, s32 releaseCount); NN_EXTERN_C void nnosInterCoreLightSemaphoreAcquire(nnosInterCoreLightSemaphore* this_); NN_EXTERN_C bool nnosInterCoreLightSemaphoreTryAcquire(nnosInterCoreLightSemaphore* this_); NN_EXTERN_C void nnosInterCoreLightSemaphoreFinalize(nnosInterCoreLightSemaphore* this_); #endif // ifndef NN_OS_OS_INTERCORE_LIGHTSEMAPHORE_H_