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