1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_InterCoreLightSemaphore.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_INTERCORE_LIGHTSEMAPHORE_H_
17 #define NN_OS_OS_INTERCORE_LIGHTSEMAPHORE_H_
18 
19 #ifdef __cplusplus
20 
21 #include <nn/os/os_MemoryBarrierSelect.h>
22 #include <nn/os/os_WaitableCounter.h>
23 #include <nn/assert.h>
24 #include <nn/WithInitialize.h>
25 #include <nn/util/detail/util_ScopedLockImpl.h>
26 #include <nn/config.h>
27 
28 namespace nn { namespace os {
29 
30 /* Please see man pages for details
31 
32 
33 
34 
35 */
36 
37 /* Please see man pages for details
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50  */
51 class InterCoreLightSemaphore
52 {
53 public:
54     static const s32 MAX_MAX_COUNT  = 0x7fff;
55 
56 private:
57     struct DecrementIfPositive
58     {
operatorDecrementIfPositive59         bool operator()(s32& x)
60         {
61             if( x > 0 )
62             {
63                 --x;
64                 return true;
65             }
66             else
67             {
68                 return false;
69             }
70         }
71     };
72     struct LimitedAdd
73     {
74         s32 max;
75         s32 value;
76         s32 beforeUpdate;
77 
operatorLimitedAdd78         bool operator()(s32& x)
79         {
80             beforeUpdate = x;
81 
82             if( x > max - value )
83             {
84                 x = max;
85             }
86             else
87             {
88                 x += value;
89             }
90 
91             return true;
92         }
93     };
94 
95 private:
96     WaitableCounter                 m_Counter;
97 #if NN_PLATFORM_HAS_16BIT_LL_SC
98     fnd::InterlockedVariable<s16>   m_NumWaiting;
99     s16                             m_Max;
100 #else
101     fnd::InterlockedVariable<s32>   m_NumWaiting;
102 #endif
103 
104 
105 public:
106     //----------------------------------------
107     //
108     //
109 
110     /* Please see man pages for details
111 
112 
113 
114 
115 
116 
117      */
InterCoreLightSemaphore()118     InterCoreLightSemaphore() {}
119 
120     /* Please see man pages for details
121 
122 
123 
124 
125 
126 
127 
128 
129 
130 
131      */
InterCoreLightSemaphore(s32 initialCount,s32 maxCount)132     InterCoreLightSemaphore(s32 initialCount, s32 maxCount) { Initialize(initialCount, maxCount); }
133 
InterCoreLightSemaphore(s32 initialCount)134     InterCoreLightSemaphore(s32 initialCount) { Initialize(initialCount); }
135 
136     /* Please see man pages for details
137 
138 
139 
140 
141 
142 
143 
144 
145      */
Initialize(s32 initialCount,s32 maxCount)146     void Initialize(s32 initialCount, s32 maxCount)
147     {
148         NN_MIN_TASSERT_( initialCount, 0 );
149         NN_MIN_TASSERT_( maxCount, 1 );
150         NN_MAX_TASSERT_( initialCount, maxCount );
151         NN_MAX_TASSERT_( maxCount, MAX_MAX_COUNT );
152 
153         *m_Counter      = initialCount;
154         m_NumWaiting    = 0;
155 #if NN_PLATFORM_HAS_16BIT_LL_SC
156         m_Max           = maxCount;
157 #else
158         NN_UNUSED_VAR(maxCount);
159 #endif
160     }
Initialize(s32 initialCount)161     void Initialize(s32 initialCount) { Initialize(initialCount, MAX_MAX_COUNT); }
162 
163     /* Please see man pages for details
164 
165 
166 
167 
168      */
Finalize()169     void Finalize() {}
170 
171     //
172 
173     //----------------------------------------
174     //
175     //
176 
177     /* Please see man pages for details
178 
179 
180 
181 
182 
183      */
184 #if NN_PLATFORM_HAS_16BIT_LL_SC
GetMax()185     s32  GetMax()   const { return m_Max; }
186 #endif
187 
188     /* Please see man pages for details
189 
190 
191 
192 
193      */
GetCount()194     s32  GetCount() const { return *m_Counter; }
195 
196     //
197 
198     //----------------------------------------
199     //
200     //
201 
202     /* Please see man pages for details
203 
204 
205 
206 
207 
208 
209 
210      */
Acquire()211     void Acquire()
212     {
213         while( ! TryAcquire() )
214         {
215             ++m_NumWaiting;
216             m_Counter.WaitIfLessThan(1);
217             --m_NumWaiting;
218         }
219     }
220 
221     /* Please see man pages for details
222 
223 
224 
225 
226 
227 
228 
229      */
TryAcquire()230     bool TryAcquire()
231     {
232         DecrementIfPositive updater;
233         bool ret = m_Counter->AtomicUpdateConditional(updater);
234         DataSynchronizationBarrier();
235         return ret;
236     }
237 
238     /* Please see man pages for details
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255 
256 
257 
258 
259      */
260     s32 Release(s32 releaseCount = 1);
261 
262     //
263 
264     class ScopedAcquire
265     {
266     private:
267         InterCoreLightSemaphore* m_Semaphore;
268     public:
269         ScopedAcquire(InterCoreLightSemaphore& semaphore, bool wait = true)
270             : m_Semaphore(wait ? (semaphore.Acquire(), &semaphore) : (semaphore.TryAcquire() ? &semaphore : 0)) {}
Aquired()271         bool Aquired() const { return m_Semaphore != 0; }
Detach()272         void Detach() { this->m_Semaphore = 0; }
~ScopedAcquire()273         ~ScopedAcquire() { if (m_Semaphore) { m_Semaphore->Release(); } }
274     };
275 };
276 
277 
278 }} // namespace nn::os
279 
280 #endif // __cplusplus
281 
282 // C declarations follow
283 
284 #include <nn/util/detail/util_CLibImpl.h>
285 
286 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosInterCoreLightSemaphore, nn::os::InterCoreLightSemaphore, 8, u32);
287 
288 NN_EXTERN_C void nnosInterCoreLightSemaphoreInitialize(nnosInterCoreLightSemaphore* this_, s32 initialCount, s32 maxCount);
289 
290 #if NN_PLATFORM_HAS_16BIT_LL_SC
291 NN_EXTERN_C s32 nnosInterCoreLightSemaphoreGetMax(nnosInterCoreLightSemaphore* p);
292 #endif
293 
294 NN_EXTERN_C s32 nnosInterCoreLightSemaphoreGetCount(nnosInterCoreLightSemaphore* p);
295 
296 NN_EXTERN_C s32 nnosInterCoreLightSemaphoreRelease(nnosInterCoreLightSemaphore* this_, s32 releaseCount);
297 
298 NN_EXTERN_C void nnosInterCoreLightSemaphoreAcquire(nnosInterCoreLightSemaphore* this_);
299 
300 NN_EXTERN_C bool nnosInterCoreLightSemaphoreTryAcquire(nnosInterCoreLightSemaphore* this_);
301 
302 NN_EXTERN_C void nnosInterCoreLightSemaphoreFinalize(nnosInterCoreLightSemaphore* this_);
303 
304 #endif  // ifndef NN_OS_OS_INTERCORE_LIGHTSEMAPHORE_H_
305