1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_LightEvent.cpp
4 Copyright (C)2009 Nintendo Co., Ltd. All rights reserved.
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10 $Rev: 16480 $
11 *---------------------------------------------------------------------------
12
13
14 */
15
16 #include <nn/os/os_LightEvent.h>
17
18 //---------------------------------------------------------------------------
19
20
21 namespace nn {
22 namespace os {
23
24 // Gets whether the flag is set.
TryWait()25 bool LightEvent::TryWait()
26 {
27 if( *m_Counter == SIGNALED_MANUAL )
28 {
29 // Since it is a manual reset, do not reset the flag.
30 return true;
31 }
32 else
33 {
34 // If a flag is set, the flag is reset and true is returned.
35 return m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO;
36 }
37 }
38
39 // Waits until the flag is set.
Wait()40 void LightEvent::Wait()
41 {
42 for(;;)
43 {
44 switch( *m_Counter )
45 {
46 // Waits until flag is set, does not clear flag.
47 case NOT_SIGNALED_MANUAL: m_Counter.WaitIfLessThan(0); return;
48
49 // Does not wait because flag is set.
50 case SIGNALED_MANUAL: return;
51
52 // Waits because flag is not set.
53 case NOT_SIGNALED_AUTO: break;
54
55 // Does not wait because flag is set. Reset flag.
56 case SIGNALED_AUTO:
57 {
58 if( m_Counter->CompareAndSwap(SIGNALED_AUTO, NOT_SIGNALED_AUTO) == SIGNALED_AUTO )
59 {
60 return;
61 }
62 }
63 break;
64 }
65
66 // Waits until the flag is set
67 // If the flag is set, m_Counter changes from NOT_SIGNALED_AUTO to SIGNALED_AUTO.
68 m_Counter.WaitIfLessThan(0);
69 }
70 }
71
72 // Set flag.
Signal()73 void LightEvent::Signal()
74 {
75 if( *m_Counter == NOT_SIGNALED_AUTO )
76 {
77 *m_Counter = SIGNALED_AUTO;
78 // For automatic reset, wake up high priority threads.
79 // At the same time the thread is awakened, the flag is reset.
80 m_Counter.Signal(1);
81 }
82 else if( *m_Counter == NOT_SIGNALED_MANUAL )
83 {
84 *m_Counter = SIGNALED_MANUAL;
85 // For manual reset, wake up all standby threads.
86 // Even if the thread is awakened, the flag is not reset.
87 m_Counter.SignalAll();
88 }
89 // If there are no threads on standby, the flag does not change.
90 }
91
92 // Releases threads waiting for the flag to be set.
Pulse()93 void LightEvent::Pulse()
94 {
95 switch( *m_Counter )
96 {
97 case SIGNALED_MANUAL:
98 *m_Counter = NOT_SIGNALED_MANUAL;
99 // not break
100 case NOT_SIGNALED_MANUAL:
101 // Wakes up all threads waiting for the flag to be set.
102 // At the same time the thread is awakened, the flag is reset.
103 m_Counter.SignalAll();
104 break;
105
106 case NOT_SIGNALED_AUTO:
107 // Wakes up the highest priority thread of the threads waiting for the flag to be set.
108 //
109 // At the same time the thread is awakened, the flag is reset.
110 m_Counter.Signal(1);
111 break;
112
113 case SIGNALED_AUTO:
114 // Reset flag.
115 *m_Counter = NOT_SIGNALED_AUTO;
116 break;
117 }
118 }
119
120 // Clear flag.
ClearSignal()121 void LightEvent::ClearSignal()
122 {
123 if( *m_Counter == SIGNALED_MANUAL )
124 {
125 *m_Counter = NOT_SIGNALED_MANUAL;
126 }
127 else if( *m_Counter == SIGNALED_AUTO )
128 {
129 *m_Counter = NOT_SIGNALED_AUTO;
130 }
131 }
132
133 }
134 }
135
136
137
138 using namespace nn;
139
140
141 // C Function Definitions
142
143 #include <new>
144
145 using namespace nn::os;
146
147 extern "C" {
148
nnosLightEventInitialize(nnosLightEvent * p,bool isManualReset)149 void nnosLightEventInitialize(nnosLightEvent* p, bool isManualReset)
150 {
151 new (p) LightEvent(isManualReset);
152 }
153
nnosLightEventIsSignaled(nnosLightEvent * p)154 bool nnosLightEventIsSignaled(nnosLightEvent* p)
155 {
156 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
157 return pLightEvent->IsSignaled();
158 }
159
nnosLightEventIsManualReset(nnosLightEvent * p)160 bool nnosLightEventIsManualReset(nnosLightEvent* p)
161 {
162 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
163 return pLightEvent->IsManualReset();
164 }
165
nnosLightEventTryWait(nnosLightEvent * p)166 bool nnosLightEventTryWait(nnosLightEvent* p)
167 {
168 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
169 return pLightEvent->TryWait();
170 }
171
nnosLightEventWait(nnosLightEvent * p)172 void nnosLightEventWait(nnosLightEvent* p)
173 {
174 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
175 pLightEvent->Wait();
176 }
177
nnosLightEventSignal(nnosLightEvent * p)178 void nnosLightEventSignal(nnosLightEvent* p)
179 {
180 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
181 pLightEvent->Signal();
182 }
183
nnosLightEventPulse(nnosLightEvent * p)184 void nnosLightEventPulse(nnosLightEvent* p)
185 {
186 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
187 pLightEvent->Pulse();
188 }
189
nnosLightEventClearSignal(nnosLightEvent * p)190 void nnosLightEventClearSignal(nnosLightEvent* p)
191 {
192 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
193 pLightEvent->ClearSignal();
194 }
195
nnosLightEventFinalize(nnosLightEvent * p)196 void nnosLightEventFinalize(nnosLightEvent* p)
197 {
198 LightEvent* pLightEvent = reinterpret_cast<LightEvent*>(p);
199 pLightEvent->Finalize();
200 pLightEvent->~LightEvent();
201 }
202
203 } // extern "C"
204