1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_LightSemaphore.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: 33107 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NN_OS_OS_LIGHTSEMAPHORE_H_
17 #define NN_OS_OS_LIGHTSEMAPHORE_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 <nn/config.h>
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 LightSemaphore
51 {
52 public:
53     static const s32 MAX_MAX_COUNT  = 0x7fff;
54 
55 private:
56     struct DecrementIfPositive
57     {
operatorDecrementIfPositive58         bool operator()(s32& x)
59         {
60             if( x > 0 )
61             {
62                 --x;
63                 return true;
64             }
65             else
66             {
67                 return false;
68             }
69         }
70     };
71     struct LimitedAdd
72     {
73         s32 max;
74         s32 value;
75         s32 beforeUpdate;
76 
operatorLimitedAdd77         bool operator()(s32& x)
78         {
79             beforeUpdate = x;
80 
81             if( x > max - value )
82             {
83                 x = max;
84             }
85             else
86             {
87                 x += value;
88             }
89 
90             return true;
91         }
92     };
93 
94 private:
95     WaitableCounter                 m_Counter;
96 #if NN_PLATFORM_HAS_16BIT_LL_SC
97     fnd::InterlockedVariable<s16>   m_NumWaiting;
98     s16                             m_Max;
99 #else
100     fnd::InterlockedVariable<s32>   m_NumWaiting;
101 #endif
102 
103 
104 public:
105     //----------------------------------------
106     //
107     //
108 
109     /*
110 
111 
112 
113 
114 
115 
116      */
LightSemaphore()117     LightSemaphore() {}
118 
119     /*
120 
121 
122 
123 
124 
125 
126 
127 
128 
129 
130      */
LightSemaphore(s32 initialCount,s32 maxCount)131     LightSemaphore(s32 initialCount, s32 maxCount) { Initialize(initialCount, maxCount); }
132 
LightSemaphore(s32 initialCount)133     LightSemaphore(s32 initialCount) { Initialize(initialCount); }
134 
135     /*
136 
137 
138 
139 
140 
141 
142 
143 
144      */
Initialize(s32 initialCount,s32 maxCount)145     void Initialize(s32 initialCount, s32 maxCount)
146     {
147         NN_MIN_TASSERT_( initialCount, 0 );
148         NN_MIN_TASSERT_( maxCount, 1 );
149         NN_MAX_TASSERT_( initialCount, maxCount );
150         NN_MAX_TASSERT_( maxCount, MAX_MAX_COUNT );
151 
152         *m_Counter      = initialCount;
153         m_NumWaiting    = 0;
154 #if NN_PLATFORM_HAS_16BIT_LL_SC
155         m_Max           = maxCount;
156 #else
157         NN_UNUSED_VAR(maxCount);
158 #endif
159     }
Initialize(s32 initialCount)160     void Initialize(s32 initialCount) { Initialize(initialCount, MAX_MAX_COUNT); }
161 
162     /*
163 
164 
165 
166 
167      */
Finalize()168     void Finalize() {}
169 
170     //
171 
172     //----------------------------------------
173     //
174     //
175 
176     /*
177 
178 
179 
180 
181 
182      */
183 #if NN_PLATFORM_HAS_16BIT_LL_SC
GetMax()184     s32  GetMax()   const { return m_Max; }
185 #endif
186 
187     /*
188 
189 
190 
191 
192      */
GetCount()193     s32  GetCount() const { return *m_Counter; }
194 
195     //
196 
197     //----------------------------------------
198     //
199     //
200 
201     /*
202 
203 
204 
205 
206 
207 
208 
209      */
Acquire()210     void Acquire()
211     {
212         while( ! TryAcquire() )
213         {
214             ++m_NumWaiting;
215             m_Counter.WaitIfLessThan(1);
216             --m_NumWaiting;
217         }
218     }
219 
220     /*
221 
222 
223 
224 
225 
226 
227 
228      */
TryAcquire()229     bool TryAcquire()
230     {
231         DecrementIfPositive updater;
232         return m_Counter->AtomicUpdateConditional(updater);
233     }
234 
235     /*
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255 
256      */
257     s32 Release(s32 releaseCount = 1);
258 
259     //
260 
261     class ScopedAcquire
262     {
263     private:
264         LightSemaphore* m_Semaphore;
265     public:
266         ScopedAcquire(LightSemaphore& semaphore, bool wait = true)
267             : m_Semaphore(wait ? (semaphore.Acquire(), &semaphore) : (semaphore.TryAcquire() ? &semaphore : 0)) {}
Aquired()268         bool Aquired() const { return m_Semaphore != 0; }
Detach()269         void Detach() { this->m_Semaphore = 0; }
~ScopedAcquire()270         ~ScopedAcquire() { if (m_Semaphore) { m_Semaphore->Release(); } }
271     };
272 };
273 
274 
275 }} // namespace nn::os
276 
277 #endif // __cplusplus
278 
279 // C declarations follow
280 
281 #include <nn/util/detail/util_CLibImpl.h>
282 
283 /* Please see man pages for details
284 
285 
286 
287 
288 
289 
290 
291 
292 */
293 
294 /* Please see man pages for details
295 
296 
297 
298 */
299 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosLightSemaphore, nn::os::LightSemaphore, 8, u32);
300 
301 /* Please see man pages for details
302 
303 */
304 NN_EXTERN_C void nnosLightSemaphoreInitialize(nnosLightSemaphore* this_, s32 initialCount, s32 maxCount);
305 
306 #if NN_PLATFORM_HAS_16BIT_LL_SC
307 /* Please see man pages for details
308 
309 */
310 NN_EXTERN_C s32 nnosLightSemaphoreGetMax(nnosLightSemaphore* p);
311 #endif
312 
313 /* Please see man pages for details
314 
315 */
316 NN_EXTERN_C s32 nnosLightSemaphoreGetCount(nnosLightSemaphore* p);
317 
318 /* Please see man pages for details
319 
320 */
321 NN_EXTERN_C s32 nnosLightSemaphoreRelease(nnosLightSemaphore* this_, s32 releaseCount);
322 
323 /* Please see man pages for details
324 
325 */
326 NN_EXTERN_C void nnosLightSemaphoreAcquire(nnosLightSemaphore* this_);
327 
328 /* Please see man pages for details
329 
330 */
331 NN_EXTERN_C bool nnosLightSemaphoreTryAcquire(nnosLightSemaphore* this_);
332 
333 /* Please see man pages for details
334 
335 */
336 NN_EXTERN_C void nnosLightSemaphoreFinalize(nnosLightSemaphore* this_);
337 
338 /*
339 
340 
341 
342 */
343 
344 #endif  // ifndef NN_OS_OS_LIGHTSEMAPHORE_H_
345