1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: os_SimpleLock.cpp
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: 46850 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn/os.h>
17 #include <nn/os/os_SimpleLock.h>
18
19 //---------------------------------------------------------------------------
20
21 using namespace nn;
22 using namespace nn::fnd;
23 using namespace nn::svc;
24 using namespace nn::os;
25 using namespace nn::util;
26
27 namespace nn{ namespace os{
28
29 namespace
30 {
31 struct ReverseIfPositiveUpdater
32 {
operator ()nn::os::__anon5b669f270111::ReverseIfPositiveUpdater33 bool operator()(s32& x)
34 {
35 if( x > 0 )
36 {
37 x = -x;
38 return true;
39 }
40 else
41 {
42 return false;
43 }
44 }
45 };
46
47 struct ReverseUpdater
48 {
49 s32 afterUpdate;
operator ()nn::os::__anon5b669f270111::ReverseUpdater50 bool operator()(s32& x)
51 {
52 x = -x;
53 afterUpdate = x;
54 return true;
55 }
56 };
57
58 struct DecrementIfNegativeUpdater
59 {
operator ()nn::os::__anon5b669f270111::DecrementIfNegativeUpdater60 bool operator()(s32& x)
61 {
62 if( x < 0 )
63 {
64 --x;
65 return true;
66 }
67 else
68 {
69 return false;
70 }
71 }
72 };
73
74 struct ReverseAndIncrementIfPositiveUpdater
75 {
operator ()nn::os::__anon5b669f270111::ReverseAndIncrementIfPositiveUpdater76 bool operator()(s32& x)
77 {
78 if( x > 0 )
79 {
80 x = -x + 1;
81 return true;
82 }
83 else
84 {
85 return false;
86 }
87 }
88 };
89 }
90
91 //
92 // m_Counter value
93 //
94 // +1 Unlocked state
95 // -1 1 client obtains lock
96 // -2 1 client obtains lock, 1 client stands by
97 // -(1+N) 1 client obtains lock, N clients stand by
98 // +(1+N) Unlocked state, N clients stand by
99 // +2 Unlocked state, 1 client stands by
100 //
101
102
Initialize()103 void SimpleLock::Initialize()
104 {
105 *m_Counter = 1;
106 }
107
TryLock()108 bool SimpleLock::TryLock()
109 {
110 ReverseIfPositiveUpdater updater;
111 return m_Counter->AtomicUpdateConditional(updater);
112 }
113
Lock()114 void SimpleLock::Lock()
115 {
116 if( ! TryLock() )
117 {
118 LockImpl();
119 }
120 }
121
Unlock()122 void SimpleLock::Unlock()
123 {
124 ReverseUpdater updater;
125 m_Counter->AtomicUpdateConditional(updater);
126
127 if( updater.afterUpdate > 1 )
128 {
129 m_Counter.Signal(1);
130 }
131 }
132
LockImpl()133 void SimpleLock::LockImpl()
134 {
135 for(;;)
136 {
137 DecrementIfNegativeUpdater incrementNumWaiterIfLocked;
138
139 if( m_Counter->AtomicUpdateConditional(incrementNumWaiterIfLocked) )
140 {
141 // Lock continuing, lock wait counter incremented
142 break;
143 }
144
145 // Unlocked state
146
147 if( TryLock() )
148 {
149 // Obtaining lock
150 return;
151 }
152 }
153
154
155 for(;;)
156 {
157 m_Counter.WaitIfLessThan(0);
158
159 ReverseAndIncrementIfPositiveUpdater decrementNumWaiterAndLockIfUnlocked;
160
161 if( m_Counter->AtomicUpdateConditional(decrementNumWaiterAndLockIfUnlocked) )
162 {
163 // Obtaining lock
164 break;
165 }
166 }
167 }
168
169 }} // namespace nn::os
170
171