1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     os_CriticalSection.h
4 
5   Copyright (C)2009-2012 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: 47236 $
14  *---------------------------------------------------------------------------*/
15 
16 /* Please see man pages for details
17 
18 
19 
20 */
21 
22 #ifndef NN_OS_OS_CRITICALSECTION_H_
23 #define NN_OS_OS_CRITICALSECTION_H_
24 
25 #include <nn/os/os_SimpleLock.h>
26 #include <nn/assert.h>
27 #include <nn/WithInitialize.h>
28 #include <nn/util/detail/util_ScopedLockImpl.h>
29 #include <nn/hw/ARM/reg_access.h>
30 
31 #ifdef __cplusplus
32 
33 namespace nn { namespace os {
34 
35 /* Please see man pages for details
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 */
55 
56 class CriticalSection : private nn::util::NonCopyable<CriticalSection>
57 {
58 public:
59     /* Please see man pages for details
60 
61 
62 
63 
64 
65     */
CriticalSection()66     CriticalSection() : m_ThreadUniqueValue(GetInvalidThreadUniqueValue()), m_LockCount(-1) {}
67 
68     /* Please see man pages for details
69 
70     */
CriticalSection(const nn::WithInitialize &)71     CriticalSection(const nn::WithInitialize&) { Initialize(); }
72 
73     /* Please see man pages for details
74 
75 
76 
77     */
78     void Initialize();
79 
80     /* Please see man pages for details
81 
82 
83 
84     */
TryInitialize()85     nn::Result TryInitialize()
86     {
87         Initialize();
88         return ResultSuccess();
89     }
90 
91     /* Please see man pages for details
92 
93 
94 
95 
96 
97     */
Finalize()98     void Finalize() { m_LockCount = -1; }
99 
100     /* Please see man pages for details
101 
102     */
~CriticalSection()103     ~CriticalSection() {}
104 
105     /* Please see man pages for details
106 
107 
108 
109     */
110     void Enter();
111 
112     /* Please see man pages for details
113 
114 
115 
116     */
117     bool TryEnter();
118 
119     /* Please see man pages for details
120 
121 
122 
123     */
124     void Leave();
125 
126     /* Please see man pages for details
127 
128 
129 
130 
131     */
132     class ScopedLock;
133 
IsLocked()134     bool IsLocked() const
135     {
136         return m_Lock.IsLocked();
137     }
138 
139 private:
OnLocked()140     void OnLocked()
141     {
142         NN_TASSERT_(m_LockCount == 0);
143 
144         // Save ID of thread that got critical section.
145         this->m_ThreadUniqueValue = GetThreadUniqueValue();
146     }
147 
148     // TODO: Recommend moving to ARM.
149 #ifdef NN_PROCESSOR_ARM946ES
GetThreadUniqueValue()150     static uptr GetThreadUniqueValue()
151     {
152         return nn::os::CTR::ARM946ES::GetThreadId();
153     }
GetInvalidThreadUniqueValue()154     static uptr GetInvalidThreadUniqueValue()
155     {
156         return static_cast<uptr>(-1);
157     }
158 #else
GetThreadUniqueValue()159     static uptr GetThreadUniqueValue()
160     {
161         uptr v;
162         HW_GET_CP15_THREAD_ID_USER_READ_ONLY(v);
163         return v;
164     }
GetInvalidThreadUniqueValue()165     static uptr GetInvalidThreadUniqueValue()
166     {
167         return 0;
168     }
169 #endif
170 
LockedByCurrentThread()171     bool LockedByCurrentThread() const
172     {
173         return GetThreadUniqueValue() == m_ThreadUniqueValue;
174     }
IsInitialized()175     bool IsInitialized() const
176     {
177         return m_LockCount >= 0;
178     }
179 
180 private:
181     SimpleLock  m_Lock;
182     uptr        m_ThreadUniqueValue;
183     s32         m_LockCount;
184 };
185 
186 NN_UTIL_DETAIL_DEFINE_SCOPED_LOCK(CriticalSection, Enter(), Leave());
187 
188 }} // namespace nn::os
189 
190 #endif // __cplusplus
191 
192 // Below is the C declaration
193 
194 #include <nn/util/detail/util_CLibImpl.h>
195 
196 #define NN_OS_CRITICALSECTION_SIZE 12
197 
198 /* Please see man pages for details
199 
200 
201 
202 
203 
204 
205 
206 
207 */
208 
209 /* Please see man pages for details
210 
211 
212 
213 
214 */
215 NN_UTIL_DETAIL_CLIBIMPL_DEFINE_BUFFER_CLASS(nnosCriticalSection, nn::os::CriticalSection, NN_OS_CRITICALSECTION_SIZE, u32);
216 
217 /* Please see man pages for details
218 
219 */
220 NN_EXTERN_C void nnosCriticalSectionInitialize(nnosCriticalSection* this_);
221 
222 /* Please see man pages for details
223 
224 */
225 NN_EXTERN_C bool nnosCriticalSectionTryInitialize(nnosCriticalSection* this_);
226 
227 /* Please see man pages for details
228 
229 */
230 NN_EXTERN_C void nnosCriticalSectionEnter(nnosCriticalSection* this_);
231 
232 /* Please see man pages for details
233 
234 */
235 NN_EXTERN_C bool nnosCriticalSectionTryEnter(nnosCriticalSection* this_);
236 
237 /* Please see man pages for details
238 
239 */
240 NN_EXTERN_C void nnosCriticalSectionLeave(nnosCriticalSection* this_);
241 
242 /* Please see man pages for details
243 
244 */
245 NN_EXTERN_C void nnosCriticalSectionFinalize(nnosCriticalSection* this_);
246 
247 /*
248 
249 
250 
251 */
252 
253 #endif
254