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