Symbian3/PDK/Source/GUID-16AB388A-ED3E-4901-857D-834072437D25.dita
changeset 12 80ef3a206772
equal deleted inserted replaced
11:5072524fcc79 12:80ef3a206772
       
     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>