|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-16AB388A-ED3E-4901-857D-834072437D25" xml:lang="en"><title>Spin |
|
13 Locks</title><shortdesc>Spin locks allow resource execution control through fast lock context |
|
14 switching. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
15 <section id="GUID-9AE2107C-CEA2-453E-9E89-5F1075370F86"><title>Introduction</title><p>Spin |
|
16 locks are a type of lock mechanism. In a spin lock, the thread will simply |
|
17 wait in a loop checking for the resource to become available. It is the execution |
|
18 of the thread waiting in a loop ("spins"), that gives this lock mechanism |
|
19 its name. The thread will only come out of the loop once the resource is available.</p><p>When |
|
20 using a spin lock, the following should be noted :</p><ul> |
|
21 <li><p>Spin locks should only be used in environments where the waiting period |
|
22 will be short</p></li> |
|
23 <li><p>Spin locks are very wasteful, since the thread in question is always |
|
24 in the active state</p></li> |
|
25 <li><p>Spin locks can lock/unlock very quickly, since the thread never changes |
|
26 state</p></li> |
|
27 <li><p>For spin locks to work on the Symbian platform, the interrupts have |
|
28 to be disabled before use. This is due to the fact that spin locks do not |
|
29 protect against interrupts from occurring on the same CPU.</p></li> |
|
30 </ul><p>Because of these properties, spin locks are used in environments where |
|
31 the operation has to be fast and where the waiting times have to be short. |
|
32 For this reason, on the Symbian platform they are only used in kernel code. |
|
33 If a more efficient use of thread processing time is required, then a mutex |
|
34 should be used.</p><p>There are two types of spin lock:</p><ul> |
|
35 <li><p>spin locks and</p></li> |
|
36 <li><p>read write spin locks.</p></li> |
|
37 </ul><p>The difference between the two types of spin locks is that the read |
|
38 write spin locks have been optimised to allow multiple reading threads to |
|
39 acquire the lock simultaneously.</p> </section> |
|
40 <section id="GUID-B99EB4FC-3845-4B04-928F-914EFCB879F5"><title>Required interrupt |
|
41 behaviour</title><p>When using spin locks, the following steps have to be |
|
42 carried out:</p><ol> |
|
43 <li id="GUID-B1271135-AC0F-4E19-9077-915B71E8618E"><p>disable the interrupts</p></li> |
|
44 <li id="GUID-0422F03D-D250-47C9-9255-49BEA54B9D54"><p>acquire the lock</p></li> |
|
45 <li id="GUID-593FDE3C-8509-4329-B258-009139095785"><p>enable the interrupts |
|
46 after the lock is released.</p></li> |
|
47 </ol><p>If the above steps have not been carried out, then a dead lock condition |
|
48 could occur.</p></section> |
|
49 <section id="GUID-5DBAD802-F902-4B5E-A190-40BC05313FEA"><title>The types of |
|
50 spin locks available</title><p>There are two types of spin locks on the Symbian |
|
51 platform. These are spin locks and read write spin locks. Read write spin |
|
52 locks are described in the next section.</p><p>There are two ways of implementing |
|
53 spin locks on the Symbian platform:</p><ul> |
|
54 <li><p>A Spin lock API and</p></li> |
|
55 <li><p>the use of spin lock macros.</p></li> |
|
56 </ul><p>The spin lock API should never be used directly, instead the macros |
|
57 should be used. This is due to:</p><ul> |
|
58 <li><p>The spin lock macros carry out the required interrupt enable/disable |
|
59 operations</p></li> |
|
60 <li><p>The spin lock macros provide compatibility between SMP and non-SMP |
|
61 builds.</p></li> |
|
62 </ul><p>The spin lock API is only for internal use and should never be used. |
|
63 For spin locks it is provided by the <xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref> class and |
|
64 is defined in <filepath>nkern.h</filepath>. It will not be discussed any further.</p><p>The |
|
65 spin lock macros available are :</p><table id="GUID-CF9670A1-AB07-4451-AB4F-20F44D8FC5F9"> |
|
66 <tgroup cols="5"><colspec colname="col1" colwidth="0.96*"/><colspec colname="col2" colwidth="0.96*"/><colspec colname="col3" colwidth="0.97*"/><colspec colname="COLSPEC0" colwidth="0.97*"/><colspec colname="col4" colwidth="1.15*"/> |
|
67 <tbody> |
|
68 <row> |
|
69 <entry><p><b>Macro</b></p></entry> |
|
70 <entry><p><b>Parameter 1</b></p><p><b>Purpose and Data Type</b></p></entry> |
|
71 <entry><p><b>Parameter 2</b></p><p><b>Purpose and Data Type</b></p></entry> |
|
72 <entry><p><b>Return Value</b></p><p><b>Purpose and Data Type</b></p></entry> |
|
73 <entry><p><b>Operation</b></p></entry> |
|
74 </row> |
|
75 <row> |
|
76 <entry><p>__SPIN_LOCK_IRQSAVE(lock)</p></entry> |
|
77 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
78 <entry><p>N/A</p></entry> |
|
79 <entry><p>The original interrupt state.</p><xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref></entry> |
|
80 <entry><p>Disable interrupts and acquire the lock.</p></entry> |
|
81 </row> |
|
82 <row> |
|
83 <entry><p>__SPIN_UNLOCK_IRQRESTORE(lock,irq)</p></entry> |
|
84 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
85 <entry><p>The interrupt state</p><xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref></entry> |
|
86 <entry><p>N/A</p></entry> |
|
87 <entry><p>Release the lock, then restore the interrupt state.</p></entry> |
|
88 </row> |
|
89 <row> |
|
90 <entry><p>__SPIN_FLASH_IRQRESTORE(lock,irq)</p></entry> |
|
91 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
92 <entry><p>The interrupt state.</p><xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref></entry> |
|
93 <entry><p>ETrue if the lock/unlock operation has occurred, otherwise EFalse.</p><xref href="GUID-4B942C06-1BAC-3A21-B3B1-89FB5C51ADA0.dita"><apiname>TBool</apiname></xref></entry> |
|
94 <entry><p>If another thread is waiting for the spin lock or there is an interrupt |
|
95 pending, then execute the __SPIN_UNLOCK_IRQRESTORE macro and then execute |
|
96 the __SPIN_LOCK_IRQ macro.</p></entry> |
|
97 </row> |
|
98 <row> |
|
99 <entry><p>__SPIN_LOCK(lock)</p></entry> |
|
100 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
101 <entry><p>N/A</p></entry> |
|
102 <entry><p>N/A</p></entry> |
|
103 <entry><p>Acquire the lock, assuming the interrupts and preemption have been |
|
104 disabled.</p></entry> |
|
105 </row> |
|
106 <row> |
|
107 <entry><p>__SPIN_UNLOCK(lock)</p></entry> |
|
108 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
109 <entry><p>N/A</p></entry> |
|
110 <entry><p>N/A</p></entry> |
|
111 <entry><p>Release the lock without changing the interrupt and preemption states.</p></entry> |
|
112 </row> |
|
113 <row> |
|
114 <entry><p>__SPIN_FLASH_PREEMPT(lock)</p></entry> |
|
115 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
116 <entry><p>N/A</p></entry> |
|
117 <entry><p>ETrue if the lock/unlock operation has occurred, otherwise EFalse.</p><xref href="GUID-4B942C06-1BAC-3A21-B3B1-89FB5C51ADA0.dita"><apiname>TBool</apiname></xref></entry> |
|
118 <entry><p>If another thread is waiting for the lock, then execute (after the |
|
119 unlock <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-C9314237-B43B-34E0-9108-E8861196022E"><apiname>NKern::PreemptionPoint</apiname></xref> has been called) the __SPIN_UNLOCK |
|
120 macro and then the __SPIN_LOCK macro.</p></entry> |
|
121 </row> |
|
122 <row> |
|
123 <entry><p>__SPIN_LOCK_IRQ(lock)</p></entry> |
|
124 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
125 <entry><p>N/A</p></entry> |
|
126 <entry><p>N/A</p></entry> |
|
127 <entry><p>Disable interrupts and acquire the lock.</p></entry> |
|
128 </row> |
|
129 <row> |
|
130 <entry><p>__SPIN_UNLOCK_IRQ(lock)</p></entry> |
|
131 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
132 <entry><p>N/A</p></entry> |
|
133 <entry><p>N/A</p></entry> |
|
134 <entry><p>Release the lock, then enable the interrupts.</p></entry> |
|
135 </row> |
|
136 <row> |
|
137 <entry><p>__SPIN_FLASH_IRQ(lock)</p></entry> |
|
138 <entry><p>The spin lock order.</p><xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref></entry> |
|
139 <entry><p>N/A</p></entry> |
|
140 <entry><p>ETrue if the lock/unlock operation has occurred, otherwise EFalse.</p><xref href="GUID-4B942C06-1BAC-3A21-B3B1-89FB5C51ADA0.dita"><apiname>TBool</apiname></xref></entry> |
|
141 <entry><p>If another thread is waiting for the spin lock or if there is an |
|
142 interrupt pending, then execute the __SPIN_UNLOCK_IRQ macro and then execute |
|
143 the __SPIN_LOCK_IRQ macro.</p></entry> |
|
144 </row> |
|
145 </tbody> |
|
146 </tgroup> |
|
147 </table><p>The spin lock order parameter is used to provide a priority of |
|
148 the spin lock. The spin lock order parameter allows spin locks to be nested |
|
149 and to guard against deadlocks.</p><p>The list of acceptable spin lock order |
|
150 values are defined in <filepath>nkern.h</filepath>.</p><p>Which spin lock |
|
151 macro should be used is shown in the following table :</p><table id="GUID-FD737DFA-85A9-4C8F-BE02-2CCB08096E65"> |
|
152 <tgroup cols="4"><colspec colname="col1" colwidth="0.58*"/><colspec colname="col2" colwidth="0.84*"/><colspec colname="col3" colwidth="1.29*"/><colspec colname="col4" colwidth="1.29*"/> |
|
153 <tbody> |
|
154 <row> |
|
155 <entry><p><b>Is the spin lock to be used within an ISR ?</b></p></entry> |
|
156 <entry><p><b>The ISR State</b></p></entry> |
|
157 <entry><p><b>Other Circumstances to Consider</b></p></entry> |
|
158 <entry><p><b>The Spin Lock Macros to Use</b></p></entry> |
|
159 </row> |
|
160 <row> |
|
161 <entry><p>Yes</p></entry> |
|
162 <entry><p>Unknown</p></entry> |
|
163 <entry><p>None</p></entry> |
|
164 <entry><p>__SPIN_LOCK_IRQSAVE(lock)</p></entry> |
|
165 </row> |
|
166 <row> |
|
167 <entry/> |
|
168 <entry/> |
|
169 <entry/> |
|
170 <entry><p>__SPIN_UNLOCK_IRQRESTORE(lock,irq)</p></entry> |
|
171 </row> |
|
172 <row> |
|
173 <entry/> |
|
174 <entry/> |
|
175 <entry/> |
|
176 <entry><p>__SPIN_FLASH_IRQRESTORE(lock,irq)</p></entry> |
|
177 </row> |
|
178 <row> |
|
179 <entry><p>N/A</p></entry> |
|
180 <entry><p>The interrupts have already been disabled.</p></entry> |
|
181 <entry><p>None</p></entry> |
|
182 <entry><p>__SPIN_LOCK(lock)</p></entry> |
|
183 </row> |
|
184 <row> |
|
185 <entry/> |
|
186 <entry/> |
|
187 <entry/> |
|
188 <entry><p>__SPIN_UNLOCK(lock)</p></entry> |
|
189 </row> |
|
190 <row> |
|
191 <entry/> |
|
192 <entry/> |
|
193 <entry/> |
|
194 <entry><p>__SPIN_FLASH_IRQRESTORE(lock,irq)</p></entry> |
|
195 </row> |
|
196 <row> |
|
197 <entry><p>No</p></entry> |
|
198 <entry><p>N/A</p></entry> |
|
199 <entry><p>Code is within a pair of <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-61C8A02A-B7F9-3BF9-B677-6BF83C6972B0"><apiname>NKern::Lock</apiname></xref>/<xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-A1DA547A-B5C2-3951-9613-DC1D6A313C70"><apiname>NKern::Unlock</apiname></xref> statements.</p></entry> |
|
200 <entry><p>__SPIN_LOCK(lock)</p></entry> |
|
201 </row> |
|
202 <row> |
|
203 <entry/> |
|
204 <entry/> |
|
205 <entry/> |
|
206 <entry><p>__SPIN_UNLOCK(lock)</p></entry> |
|
207 </row> |
|
208 <row> |
|
209 <entry/> |
|
210 <entry/> |
|
211 <entry/> |
|
212 <entry><p>__SPIN_FLASH_PREEMPT(lock)</p></entry> |
|
213 </row> |
|
214 <row> |
|
215 <entry><p>Yes</p></entry> |
|
216 <entry><p>Known</p></entry> |
|
217 <entry><p>The interrupts must already be disabled.</p></entry> |
|
218 <entry><p>__SPIN_LOCK_IRQ(lock)</p></entry> |
|
219 </row> |
|
220 <row> |
|
221 <entry/> |
|
222 <entry/> |
|
223 <entry/> |
|
224 <entry><p>__SPIN_UNLOCK_IRQ(lock)</p></entry> |
|
225 </row> |
|
226 <row> |
|
227 <entry/> |
|
228 <entry/> |
|
229 <entry/> |
|
230 <entry><p>__SPIN_FLASH_IRQ(lock)</p></entry> |
|
231 </row> |
|
232 </tbody> |
|
233 </tgroup> |
|
234 </table><note/><p>Only the above combinations of interrupt states and |
|
235 spin lock macros are allowed.</p><p>The spin lock macros __SPIN_LOCK_IRQSAVE |
|
236 and __SPIN_UNLOCK_IRQRESTORE would be used in almost all cases.</p></section> |
|
237 <section id="GUID-85F32921-FE0C-48EE-9B88-C45A76DC8481"><title>How to Use |
|
238 Spin Locks</title><p>An example of how to use the spin lock macros is :</p><codeblock xml:space="preserve">TInt irq = __SPIN_LOCK_IRQSAVE(EOrderThread); |
|
239 // some code... |
|
240 __SPIN_UNLOCK_IRQSTORE(EOrderThread,irq);</codeblock><p>The first line calls |
|
241 the macro to disable the interrupts and acquire the spin lock. This line returns |
|
242 the original interrupt state (stored in the variable irq).</p><p>The last |
|
243 line calls the macro to release the spin lock and then restore the IRQ to |
|
244 its original state.</p></section> |
|
245 <section id="GUID-66A13635-5DDD-40D3-B113-234D811ACBF2"><title>Read Write |
|
246 Spin Locks</title><p>This sub set of spin locks allows for the multiple reading |
|
247 threads to acquire the lock simultaneously. The operation of read write spin |
|
248 locks is :</p><table id="GUID-FB47DAFD-955C-4E3B-93B3-293CC54910FD"> |
|
249 <tgroup cols="2"><colspec colname="col1"/><colspec colname="col2"/> |
|
250 <tbody> |
|
251 <row> |
|
252 <entry><p><b>Behaviour</b></p></entry> |
|
253 <entry><p><b>Required Conditions</b></p></entry> |
|
254 </row> |
|
255 <row> |
|
256 <entry><p>Acquire the lock for a read operation</p></entry> |
|
257 <entry><p>The lock is either free or is being held for reading</p></entry> |
|
258 </row> |
|
259 <row> |
|
260 <entry><p>Blocked for a read operation</p></entry> |
|
261 <entry><p>The lock is held for a write operation</p></entry> |
|
262 </row> |
|
263 <row> |
|
264 <entry><p>Acquire the lock for a write operation</p></entry> |
|
265 <entry><p>The lock is free</p></entry> |
|
266 </row> |
|
267 <row> |
|
268 <entry><p>Blocked for a write operation</p></entry> |
|
269 <entry><p>The lock is held for a read or a write operation</p></entry> |
|
270 </row> |
|
271 </tbody> |
|
272 </tgroup> |
|
273 </table><p>The macros are the same name as for the spin locks, except :</p><table id="GUID-7FB86C27-DDC5-4AC3-982F-2736FBA9BAA8"> |
|
274 <tgroup cols="2"><colspec colname="col1"/><colspec colname="col2"/> |
|
275 <tbody> |
|
276 <row> |
|
277 <entry><p><b>Operation</b></p></entry> |
|
278 <entry><p><b>Postfix</b></p></entry> |
|
279 </row> |
|
280 <row> |
|
281 <entry><p>read access</p></entry> |
|
282 <entry><p>_R</p></entry> |
|
283 </row> |
|
284 <row> |
|
285 <entry><p>write access</p></entry> |
|
286 <entry><p>_W</p></entry> |
|
287 </row> |
|
288 </tbody> |
|
289 </tgroup> |
|
290 </table><p>An example of the use of read write spin lock macros are __SPIN_LOCK_IRQ_R(lock) |
|
291 and __SPIN_UNLOCK_IRQ_W(lock).</p><p>Read write spin locks are implemented |
|
292 by the <xref href="GUID-F8145088-041C-35E3-9AB2-AF151832ECC8.dita"><apiname>TRWSpinLock</apiname></xref> class. As with the <xref href="GUID-FB1605A8-9946-364C-A649-DEF60E1F761B.dita"><apiname>TSpinLock</apiname></xref> class, |
|
293 this class is for internal use only and will not be discussed any further.</p><p>An |
|
294 example of the use of read write spin locks is :</p><codeblock xml:space="preserve"> |
|
295 __SPIN_LOCK_IRQ_R(EOrderThread); |
|
296 // some code... |
|
297 __SPIN_UNLOCK_IRQ_R(EOrderThread);</codeblock></section> |
|
298 </conbody><related-links> |
|
299 <link href="GUID-CE72E71B-6ED3-4961-B4C5-C43D823ACA9D.dita"><linktext>SMP Overview</linktext> |
|
300 </link> |
|
301 </related-links></concept> |