1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: os_LightBarrier.h 4 5 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Rev: 38846 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_OS_OS_LIGHTBARRIER_H_ 17 #define NN_OS_OS_LIGHTBARRIER_H_ 18 19 #ifdef __cplusplus 20 21 #include <nn/os/os_WaitableCounter.h> 22 #include <nn/assert.h> 23 #include <nn/WithInitialize.h> 24 #include <nn/util/detail/util_ScopedLockImpl.h> 25 #include <cstdlib> 26 27 namespace nn { namespace os { 28 29 /* Please see man pages for details 30 31 32 33 34 */ 35 36 /* 37 38 39 40 41 42 43 44 45 46 47 48 49 */ 50 class LightBarrier 51 { 52 private: 53 struct IncrementIfLessThan_1 54 { operatorIncrementIfLessThan_155 bool operator()(s32& x) 56 { 57 if( x < -1 ) 58 { 59 ++x; 60 return true; 61 } 62 else 63 { 64 return false; 65 } 66 } 67 }; 68 69 private: 70 WaitableCounter m_CounterPlus; 71 WaitableCounter m_CounterMinus; 72 s32 m_ReleaseCountAndSign; 73 74 public: 75 //---------------------------------------- 76 // 77 // 78 79 /* 80 81 82 83 84 85 86 87 88 */ LightBarrier()89 LightBarrier() {} 90 91 /* 92 93 94 95 96 97 98 99 100 101 102 */ LightBarrier(s32 numWait)103 LightBarrier(s32 numWait) { Initialize(numWait); } 104 105 /* 106 107 108 109 110 111 112 */ Initialize(s32 numWait)113 void Initialize(s32 numWait) 114 { 115 NN_MIN_TASSERT_( numWait, 1 ); 116 117 *m_CounterPlus = - numWait; 118 *m_CounterMinus = - numWait; 119 m_ReleaseCountAndSign = numWait; 120 } 121 122 /* 123 124 125 126 127 */ Finalize()128 void Finalize() {} 129 130 // 131 132 //---------------------------------------- 133 // 134 // 135 136 /* 137 138 139 140 141 142 143 144 */ GetReleaseCount()145 s32 GetReleaseCount() const { return std::abs(m_ReleaseCountAndSign); } 146 147 /* 148 149 150 151 152 153 154 155 */ GetNumOfWaiting()156 s32 GetNumOfWaiting() const 157 { 158 const s32 relCountAndSign = m_ReleaseCountAndSign; 159 s32 minusRemain; 160 s32 relCount; 161 162 if( relCountAndSign > 0 ) 163 { 164 minusRemain = *m_CounterPlus; 165 relCount = relCountAndSign; 166 } 167 else 168 { 169 minusRemain = *m_CounterMinus; 170 relCount = - relCountAndSign; 171 } 172 173 return (minusRemain == 0) ? 0: relCount + minusRemain; 174 } 175 176 // 177 178 //---------------------------------------- 179 // 180 // 181 182 /* 183 184 185 186 187 188 189 190 */ Await()191 void Await() 192 { 193 const s32 relCountAndSign = m_ReleaseCountAndSign; 194 195 if( relCountAndSign > 0 ) 196 { 197 AwaitImpl(&m_CounterPlus, &m_CounterMinus, relCountAndSign); 198 } 199 else 200 { 201 AwaitImpl(&m_CounterMinus, &m_CounterPlus, - relCountAndSign); 202 } 203 } 204 205 // 206 207 private: AwaitImpl(nn::os::WaitableCounter * pCur,nn::os::WaitableCounter * pNext,s32 relCount)208 void AwaitImpl(nn::os::WaitableCounter* pCur, nn::os::WaitableCounter* pNext, s32 relCount) 209 { 210 IncrementIfLessThan_1 updater; 211 212 if( (*pCur)->AtomicUpdateConditional(updater) ) 213 { 214 pCur->WaitIfLessThan(0); 215 } 216 else 217 { 218 m_ReleaseCountAndSign = - m_ReleaseCountAndSign; 219 **pNext = - relCount; 220 **pCur = 0; 221 pCur->SignalAll(); 222 } 223 } 224 }; 225 226 227 }} // namespace nn::os 228 229 #endif // __cplusplus 230 231 // TODO: Requires an API for C. 232 233 #endif // ifndef NN_OS_OS_LIGHTBARRIER_H_ 234