Adaptation/GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     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-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5" xml:lang="en"><title>Thread
       
    13 Synchronisation</title><shortdesc>Kernel-side techniques to protect critical regions in code or to
       
    14 allow safe access to shared data.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <p>Kernel-side code can use a number of techniques to perform thread synchronisation,
       
    16 to protect critical regions within threads or to ensure that shared data can
       
    17 be safely read or modified. </p>
       
    18 <ul>
       
    19 <li id="GUID-F76D1379-CEA0-5CEA-A050-88CCF23AFAC6"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-86E98109-EC1A-58B7-8AB2-EFD100739261">Mutexes</xref>  </p> </li>
       
    20 <li id="GUID-614F64B3-04C0-5ED0-9286-C64B8B1C4235"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-00E1F006-3D2C-52A3-BFCB-4D6A59321B26">Semaphores</xref> </p> </li>
       
    21 <li id="GUID-7970F858-7480-5EEB-A924-2157E40FB44E"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-7E632FD5-03B6-5D39-8A97-8F1948F2BB5B">Thread critical section</xref>  </p> </li>
       
    22 <li id="GUID-A3BFB534-95F0-5B32-A996-955AE40C19E6"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-7AECE882-9D48-5109-AE38-38BF0F8F717F">Atomic operations</xref>  </p> </li>
       
    23 <li id="GUID-C4B47444-2A35-5E0C-92EF-C33DDD68D0E1"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-A0FB7718-F39C-5FB3-B67C-430B490F6430">The system lock</xref>  </p> </li>
       
    24 <li id="GUID-ECFF18B2-9279-5B68-9939-78C897F32FB8"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-1806CDC5-9941-5CFC-B1F1-82BBA8D4F65B">The kernel lock</xref>  </p> </li>
       
    25 <li id="GUID-AF3CD2DE-B4FD-5D1B-B9CC-FB2E32380D38"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-961912E5-2D89-518A-A6EA-3AAC15D17B81">Disabling interrupts</xref>  </p> </li>
       
    26 </ul>
       
    27 <section id="GUID-86E98109-EC1A-58B7-8AB2-EFD100739261"><title>Mutexes</title> <p>A
       
    28 mutex (mutual exclusion) is a mechanism to prevent more than one thread from
       
    29 executing a section of code concurrently. The most common use is to synchronise
       
    30 access to data shared between two or more threads. </p> <p>There are two types
       
    31 of mutex: the fast mutex, and a more general heavyweight mutex - the Symbian
       
    32 platform mutex. Which one you use depends on the needs of your code and the
       
    33 context in which it runs. </p> <ul>
       
    34 <li id="GUID-737BE53A-9A91-5CEA-9073-E47D3B3DB9E8"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-09377BC3-770A-5558-B3A9-A7E2CE11EBC3">The fast mutex</xref>  </p> </li>
       
    35 <li id="GUID-5952D847-0802-5B05-9CE8-6316DCA96245"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-F5B59A23-48E0-5596-B589-10DD2549F124">The Symbian platform mutex</xref>  </p> </li>
       
    36 </ul> <p id="GUID-09377BC3-770A-5558-B3A9-A7E2CE11EBC3"><b>The fast mutex</b> </p> <p>A
       
    37 fast mutex is the fundamental way of allowing mutual exclusion between <i>nanokernel</i> threads.
       
    38 Remember that a Symbian platform thread, and a thread in a personality layer
       
    39 are also nanokernel threads. </p> <p>A fast mutex is represented by a <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita"><apiname>NFastMutex</apiname></xref> object.
       
    40 It is designed to be as fast as possible, especially in the case where there
       
    41 is no contention, and is also designed to occupy as little RAM as possible.
       
    42 A fast mutex is intended to protect <i>short</i> critical sections of code </p> <ul>
       
    43 <li id="GUID-646DB0EC-1627-5BDF-8068-D6717106DB17"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-4EE0B5C4-0473-54CD-A585-F2905FA76968">Rules</xref> </p> </li>
       
    44 <li id="GUID-3C470241-DD9E-52CF-B58D-C86A9301BEEE"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-083C9D63-A69D-5E66-9274-178F329F8445">How to use</xref>  </p> </li>
       
    45 <li id="GUID-D7C801A7-B0C1-5AF1-8594-CB994BDECF7B"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-111E74A3-8442-5598-8BB9-F78E2A77610A">Example using NFastmutex to protect a critical region</xref>  </p> </li>
       
    46 </ul> <p id="GUID-4EE0B5C4-0473-54CD-A585-F2905FA76968"><b>Rules</b> </p> <p>A
       
    47 fast mutex is, be definition, fast and the price to be paid is that there
       
    48 are a few rules that must be obeyed: </p> <ul>
       
    49 <li id="GUID-25FC4814-1BBB-5C6D-90FB-12E75274C388"><p>a thread can only hold
       
    50 one fast mutex at a time, i.e. a thread cannot wait on a fast mutex if it
       
    51 already holds another fast mutex </p> </li>
       
    52 <li id="GUID-693AB846-4629-5E3C-A14C-53A0879F1DB8"><p>a thread cannot wait
       
    53 on the same fast mutex more than once </p> </li>
       
    54 <li id="GUID-11EEC812-0BC7-5FFA-8D7B-DBD400CA5958"><p>a thread must not block
       
    55 or exit while holding a fast mutex because the thread is in an implied <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-7E632FD5-03B6-5D39-8A97-8F1948F2BB5B">critical
       
    56 section</xref>. </p> </li>
       
    57 </ul> <p>In the moving memory model, the user address space is not guaranteed
       
    58 to be consistent while a kernel thread holds a fast mutex. </p> <p id="GUID-083C9D63-A69D-5E66-9274-178F329F8445"><b>How
       
    59 to use</b> </p> <p>Typically you declare a fast mutex in a class declaration,
       
    60 for example: </p> <codeblock id="GUID-D1839B94-A1AF-5693-841F-F58C583F5D7E" xml:space="preserve">class DImpSysTest : public DLogicalChannelBase
       
    61     {
       
    62     ...
       
    63 public:
       
    64     ...
       
    65     NFastMutex iMutex;
       
    66     ...
       
    67     };
       
    68 </codeblock> <p>When you want to get hold of the fast mutex, i.e. when you
       
    69 are about to enter a section of code that no other thread is executing concurrently,
       
    70 you wait on that fast mutex. If no other thread has the mutex, then your thread
       
    71 gets the mutex, and control flows into your critical code. On exiting the
       
    72 section of code, you signal the fast mutex, which relinquishes it. </p> <p>If,
       
    73 on the other hand, another thread already has the fast mutex, then your thread
       
    74 blocks, and only resumes when the other thread exits the code section by signalling
       
    75 the fast mutex. </p> <p>Getting and relinquishing the mutex is done using
       
    76 the <codeph>Wait()</codeph> and <codeph>Signal()</codeph> functions of the <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita"><apiname>NFastMutex</apiname></xref> class.
       
    77 However, you will normally use the nanokernel functions: </p> <ul>
       
    78 <li id="GUID-E2D93FB0-7E2B-5497-AAC1-DF1F2DA388E0"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-133C9428-F0BE-399E-A986-5AE72460C720"><apiname>NKern::FMWait()</apiname></xref>  </p> </li>
       
    79 <li id="GUID-4E620FA6-4146-5C90-8B67-20050A1A88D1"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-FBD38D01-21A1-3E92-BA1D-719EBCC7AF1D"><apiname>NKern::FMSignal()</apiname></xref>  </p> </li>
       
    80 </ul> <p>respectively, passing a pointer to your <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita"><apiname>NFastMutex</apiname></xref> object. </p> <p>The
       
    81 kernel lock must be held when <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-76E5AE32-9A70-344A-9E6B-5B439622715A"><apiname>NFastMutex::Wait()</apiname></xref> and <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-CA8C65D8-E59A-385A-92B8-2B22A4A2F1CB"><apiname>NFastMutex::Signal()</apiname></xref> are
       
    82 called. <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-133C9428-F0BE-399E-A986-5AE72460C720"><apiname>NKern::FMWait()</apiname></xref> and <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-FBD38D01-21A1-3E92-BA1D-719EBCC7AF1D"><apiname>NKern::FMSignal()</apiname></xref> do
       
    83 this for you. They make sure that the kernel lock is on while <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-76E5AE32-9A70-344A-9E6B-5B439622715A"><apiname>NFastMutex::Wait()</apiname></xref> and <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-CA8C65D8-E59A-385A-92B8-2B22A4A2F1CB"><apiname>NFastMutex::Signal()</apiname></xref> are
       
    84 called by wrapping them in a pair of <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-7CBBF72B-4519-38DD-92CA-38AF636AFD8A"><apiname>NKern::Lock()</apiname></xref> and <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-A1A42137-906C-30F1-AF61-4F786FC372DE"><apiname>NKern::Unlock()</apiname></xref> calls. </p> <p>Although
       
    85 this sounds like you will be blocking while holding the kernel lock, in reality
       
    86 you do not because the thread is not blocked until after the kernel lock is
       
    87 released. </p> <p>Be aware however that there may be situations where you
       
    88 already have the kernel lock, or in the case of IDFCs, you do not need to
       
    89 acquire it as no preemption can occur. In these cases, you just call <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-76E5AE32-9A70-344A-9E6B-5B439622715A"><apiname>NFastMutex::Wait()</apiname></xref> and <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita#GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953/GUID-CA8C65D8-E59A-385A-92B8-2B22A4A2F1CB"><apiname>NFastMutex::Signal()</apiname></xref>. </p> <p>The following diagram illustrates the general principle: </p> <fig id="GUID-30A0EA62-83CF-5AB9-A07E-525D0972E55B">
       
    90 <title>Fast mutex</title>
       
    91 <image href="GUID-3AFE0D8B-FB9B-5355-A63B-FB71DD13E7D0_d0e73917_href.png" placement="inline"/>
       
    92 </fig> <p>There are a number of assumptions here, one of which is that the
       
    93 priorities are such that thread T1 does not run until a reschedule occurs,
       
    94 after T2 has been interrupted. </p> <p id="GUID-111E74A3-8442-5598-8BB9-F78E2A77610A"><b>Example
       
    95 using NFastmutex to protect a critical region</b> </p> <p>The file <filepath>...\f32test\nkern\d_implicit.cpp</filepath> is
       
    96 a device driver that contains 3 threads and 3 separate sub-tests. The third
       
    97 test, identified as <codeph>ETestDummy</codeph>, shows how to protect a critical
       
    98 region using a nanokernel fast mutex. </p> <p>The mutex itself is declared
       
    99 in the channel class: </p> <codeblock id="GUID-7EFD970B-9500-5F68-8BAD-21718F3953BC" xml:space="preserve">class DImpSysTest : public DLogicalChannelBase
       
   100     {
       
   101     ...
       
   102 public:
       
   103     ...
       
   104     NFastMutex iMutex;
       
   105     ...
       
   106     };
       
   107 </codeblock> <p>The function <codeph>Start()</codeph> takes an argument that
       
   108 sets the test number. This function initialises some test variables, creates
       
   109 three threads, and also initialises the mutex: </p> <codeblock id="GUID-A131C888-FAE0-53D3-BF12-E06D54E6A093" xml:space="preserve">TInt DImpSysTest::Start(TInt aTest)
       
   110     {
       
   111     ...
       
   112     new (&amp;iMutex) NFastMutex;
       
   113     ...    
       
   114     }
       
   115 </codeblock> <p>The overloaded <codeph>new</codeph> operator is called with
       
   116 the existing mutex as its argument, with the side effect of calling the constructor
       
   117 to initialise the mutex. There is also a corresponding <codeph>Stop()</codeph> function
       
   118 to kill the threads and return the results to the caller. </p> <p>Look at
       
   119 the test case for <codeph>iTestNum == ETestDummy</codeph>, where thread 1
       
   120 and thread 3 use the mutex as if sharing a critical resource. </p> <codeblock id="GUID-A97F5CF0-F7D8-5A08-9033-908AEF2AE576" xml:space="preserve">void DImpSysTest::Thread1(TAny* aPtr)
       
   121     {
       
   122     DImpSysTest&amp; d=*(DImpSysTest*)aPtr;
       
   123     ...    
       
   124     FOREVER
       
   125         {
       
   126         NKern::FMWait(&amp;d.iMutex);
       
   127         // this is a critical region protected by d.iMutex
       
   128         NKern::FMSignal(&amp;d.iMutex);
       
   129         ...
       
   130         }
       
   131     }</codeblock> <codeblock id="GUID-8D0EA108-B735-5189-99EE-0FE895B3A933" xml:space="preserve">void DImpSysTest::Thread3(TAny* aPtr)
       
   132     {
       
   133     DImpSysTest&amp; d=*(DImpSysTest*)aPtr;
       
   134     ...
       
   135     if (d.iTestNum==RImpSysTest::ETestPriority)
       
   136         {
       
   137         ...
       
   138         }
       
   139     else if (d.iTestNum==RImpSysTest::ETestDummy)
       
   140         {
       
   141         FOREVER
       
   142             {
       
   143             ...
       
   144             if (x&lt;85)
       
   145                 {
       
   146                 ...
       
   147                 }
       
   148             else
       
   149                 {
       
   150                 NKern::FMWait(&amp;d.iMutex);
       
   151                 // this is a critical region protected by d.iMutex
       
   152                 NKern::FMSignal(&amp;d.iMutex);
       
   153                 }
       
   154             }
       
   155         }
       
   156     }
       
   157 </codeblock> <p>Each thread takes a pointer to the channel object as an argument,
       
   158 this is the <codeph>aPtr</codeph> value passed to both <codeph>Thread1()</codeph> and <codeph>Thread3()</codeph> and
       
   159 each thread dereferences it to find the mutex. The important point is that
       
   160 there is only one mutex object, which is accessed by all interested threads. </p> <p>Before
       
   161 entering the critical region, the threads call <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-133C9428-F0BE-399E-A986-5AE72460C720"><apiname>NKern::FMWait()</apiname></xref> to
       
   162 gain ownership of the mutex. Before leaving the critical region, they call <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-FBD38D01-21A1-3E92-BA1D-719EBCC7AF1D"><apiname>NKern::FMSignal()</apiname></xref> to
       
   163 relinquish ownership. </p> <p id="GUID-F5B59A23-48E0-5596-B589-10DD2549F124"><b>The
       
   164 Symbian platform mutex</b> </p> <p>The Symbian platform mutex provides mutual
       
   165 exclusion between Symbian platform threads without the restrictions imposed
       
   166 by the fast mutex. </p> <p>The Symbian platform mutex is represented by a <codeph>DMutex</codeph> object. </p> <ul>
       
   167 <li id="GUID-AAE481BE-1ABB-5E0E-AB89-1D53393B0C5B"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-94F9C4EF-24D5-514A-BD21-B10B1A83CE28">Characteristics</xref> </p> </li>
       
   168 <li id="GUID-BDA5D5F8-B508-5D9D-97DC-65AE2166817F"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-61387415-4A5B-5C98-A028-F62DA7114790">How to use</xref>  </p> </li>
       
   169 <li id="GUID-7DF42A70-D80B-5883-B96D-3452A11CD137"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-EF2F2EBB-CDC2-5367-957A-2A004453F6C7">Example using DMutex to protect critical regions</xref>  </p> </li>
       
   170 </ul> <p id="GUID-94F9C4EF-24D5-514A-BD21-B10B1A83CE28"><b>Characteristics</b> </p> <p>Operations
       
   171 on a <codeph>DMutex</codeph> are more complicated, and therefore slower, than
       
   172 those on a <xref href="GUID-D5B555DA-3D17-3ED2-A931-CB35BD93A953.dita"><apiname>NFastMutex</apiname></xref>. However, a <codeph>DMutex</codeph> gives
       
   173 you the following: </p> <ul>
       
   174 <li id="GUID-62A9B213-D77A-5151-B50A-8DA2EBA88433"><p>it is possible to wait
       
   175 on a Symbian platform mutex multiple times, provided it is signalled the exact
       
   176 same number of times </p> </li>
       
   177 <li id="GUID-EEB436F1-3F54-50BC-9009-E1EAB055199A"><p>It is possible to hold
       
   178 several Symbian platform mutexes simultaneously, although care is needed to
       
   179 avoid deadlock situations </p> </li>
       
   180 <li id="GUID-324BD7DC-7CDB-57DD-879B-E88CEA7CD194"><p>A thread can block while
       
   181 holding a Symbian platform mutex </p> </li>
       
   182 <li id="GUID-EA7C07F8-58D3-59C9-9C2A-6D82D4F6FC3B"><p>A Symbian platform mutex
       
   183 provides priority inheritance, although there is a limit on the number of
       
   184 threads that can wait on any <codeph>DMutex</codeph> (currently this is 10). </p> </li>
       
   185 </ul> <p>When a Symbian platform mutex is created it is given an 'order' value.
       
   186 This is a deadlock prevention mechanism, although it is used only in debug
       
   187 builds. When waiting on a mutex the system checks that the order value is
       
   188 less than the order value of any mutex that the thread is already waiting
       
   189 on. </p> <p>In general, most code written for device drivers should use values
       
   190 which are greater than any used by the kernel itself. There are 8 constants
       
   191 defined in <filepath>kernel.h</filepath> that are available for this purpose: <xref href="GUID-815054D8-4894-3DAB-9272-C8AAF3A11FD1.dita"><apiname>KMutexOrdGeneral0</apiname></xref> through <xref href="GUID-52E535B0-67FC-3353-89F7-BC2AF3947635.dita"><apiname>KMutexOrdGeneral7</apiname></xref>. </p> <p>The kernel faults with “Mutex Ordering Violation” if you try to
       
   192 wait on a mutex that violates the ordering rules. </p> <p>Note: the only time
       
   193 when these values would not be suitable is when the kernel calls back into
       
   194 non-kernel code while a mutex is already held by the kernel. This occurs in
       
   195 only two cases: </p> <ul>
       
   196 <li id="GUID-BE5D7153-03EC-5E07-9E50-6A164ED7976F"><p>The debug event handler
       
   197 callback </p> </li>
       
   198 <li id="GUID-C13DA224-565F-582C-8255-872D87D31CC2"><p>The various timer classes
       
   199 like <xref href="GUID-342B7499-4702-3C0F-B42A-66A5CA515F85.dita"><apiname>TTimer</apiname></xref>. This should not be an issue because device
       
   200 drivers should use the <xref href="GUID-D8CF05A3-5C9B-3662-92DA-3290C6EE7FD2.dita"><apiname>NTimer</apiname></xref> class which does not callback
       
   201 while <codeph>DMutexes</codeph> are held. </p> </li>
       
   202 </ul> <p id="GUID-61387415-4A5B-5C98-A028-F62DA7114790"><b>How to use</b> </p> <p>Typically
       
   203 you declare the mutex in a class declaration, for example: </p> <codeblock id="GUID-1704CB00-7A0E-54AB-8197-23264A487621" xml:space="preserve">class DCrashHandler : public DKernelEventHandler
       
   204     {
       
   205     ...
       
   206 private:
       
   207     DMutex* iHandlerMutex;
       
   208     ...
       
   209     };
       
   210 
       
   211 </codeblock> <p>You do not create a <codeph>DMutex</codeph> object directly;
       
   212 instead you use the kernel function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-FEBBDA4F-412E-3AE5-9098-8E2F6BF3E969"><apiname>Kern::MutexCreate()</apiname></xref>.
       
   213 You pass a <codeph>DMutex*</codeph> type to the kernel function, which creates
       
   214 the <codeph>DMutex</codeph> object and returns a reference to it through the <codeph>DMutex</codeph> pointer. </p> <p>Getting
       
   215 and relinquishing the mutex is done using the kernel functions: </p> <ul>
       
   216 <li id="GUID-703EEF8E-D70F-57F6-8ED8-56CCC7EA00DB"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-1F0C28A8-9E9A-3AA3-A441-BA8406B3A06A"><apiname>Kern::MutexWait()</apiname></xref>  </p> </li>
       
   217 <li id="GUID-A80C8CA6-8E2C-5174-BC2A-EB3B1F18C49A"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B8080F86-1342-31EA-9A28-205354CA0CB9"><apiname>Kern::MutexSignal()</apiname></xref>  </p> </li>
       
   218 </ul> <p>respectively, passing a reference to the <codeph>DMutex</codeph> object
       
   219 created earlier. Note that although you pass a <codeph>DMutex</codeph> object
       
   220 around, the member functions and member data of the class are considered as
       
   221 internal to Symbian platform. However, you can call <codeph>Open()</codeph> and <codeph>Close()</codeph> on <codeph>DMutex</codeph> as
       
   222 they are members of the base class <xref href="GUID-E48F1435-14B6-37F1-BE47-2EA803AFE497.dita"><apiname>DObject</apiname></xref>. </p> <p id="GUID-EF2F2EBB-CDC2-5367-957A-2A004453F6C7"><b>Example
       
   223 using DMutex to protect critical regions</b> </p> <p>This example code fragment
       
   224 uses two <codeph>DMutex</codeph> objects to protect a critical region of code
       
   225 in a device driver. It implements a minimal debug agent in a device driver.
       
   226 When a channel is opened to the device driver, the <codeph>DoCreate()</codeph> function
       
   227 creates a crash handler (in 2 phases). The <codeph>DCrashHandler</codeph> class
       
   228 contains two <codeph>DMutex</codeph> objects: </p> <codeblock id="GUID-C8EE7472-E897-53EC-BAC5-C8C6299ED512" xml:space="preserve">class DCrashHandler : public DKernelEventHandler
       
   229     {
       
   230     ...
       
   231 private:
       
   232     DMutex* iHandlerMutex;    // serialise access to crash handler
       
   233     ...
       
   234     DMutex* iDataMutex;    // serialise access to following members
       
   235     ...
       
   236     };</codeblock> <p>The two <codeph>DMutex</codeph> objects are created
       
   237 in the second phase of the crash handler creation, i.e. when the member function <codeph>DCrashHandler::Create()</codeph> is
       
   238 called. Here's the code: </p> <codeblock id="GUID-A23289A3-3E5D-595A-A039-E4BE73A133D8" xml:space="preserve">TInt DCrashHandler::Create(DLogicalDevice* aDevice)
       
   239     {
       
   240     TInt r;
       
   241     ...
       
   242     r = Kern::MutexCreate(iHandlerMutex, KHandlerMutexName, KMutexOrdDebug);
       
   243     ...
       
   244     r = Kern::MutexCreate(iDataMutex, KDataMutexName, KMutexOrdDebug-1);
       
   245     ...
       
   246     }</codeblock> <p>The names of the mutexes are passed as the literal descriptors: <codeph>KHandlerMutexName</codeph> and <codeph>KDataMutexName</codeph>, and have the values <i>CtHandlerMutex</i> and <i>CtDataMutex</i> respectively. </p> <p>Notice
       
   247 that the data mutex has an order value less than the handler mutex. This guards
       
   248 against deadlock - we are asking the kernel to check that any thread waits
       
   249 on the handler mutex before it waits on the data mutex. </p> <p>When a thread
       
   250 panics, or an exception occurs, program control eventually reaches <codeph>DCrashHandler::HandleCrash()</codeph>.
       
   251 The device driver is derived from <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref>,
       
   252 and the current thread is the one that crashed and this is a Symbian platform
       
   253 thread, which means that it can wait on a <codeph>DMutex</codeph>. In fact,
       
   254 it waits on two mutexes, and does so in the order mentioned above. The mutexes
       
   255 are signalled further on in the same function. </p> <codeblock id="GUID-2F3C91C3-3323-5025-B7C3-2490595463FB" xml:space="preserve">void DCrashHandler::HandleCrash(TAny* aContext)
       
   256     {
       
   257     ...
       
   258     // Ensure that, at any time, at most one thread executes the
       
   259     // following code.  This simplifies user-side API.
       
   260     Kern::MutexWait(*iHandlerMutex);
       
   261     ...
       
   262     Kern::MutexWait(*iDataMutex);
       
   263     ...
       
   264     // access crash handler data &lt;-------------------------------------
       
   265     ...
       
   266     Kern::MutexSignal(*iDataMutex);
       
   267     ...
       
   268     Kern::MutexSignal(*iHandlerMutex);
       
   269     }</codeblock> <p> <codeph> iHandlerMutex</codeph> ensures that only one
       
   270 thread at a time uses the above code. <codeph>iDataMutex</codeph> protects
       
   271 a smaller critical region where the crash handler’s data is accessed. This
       
   272 data is also protected by <codeph>iDataMutex</codeph> in the <codeph>DCrashHandler::Trap()</codeph> function. </p> <codeblock id="GUID-D202D9A0-FB4B-5BD2-BE7A-5B843AC83A97" xml:space="preserve">void DCrashHandler::Trap(TRequestStatus* aRs, TAny* aCrashInfo)
       
   273     {
       
   274     ...
       
   275     Kern::MutexWait(*iDataMutex);
       
   276     ...
       
   277     // access crash handler data &lt;-------------------------------------
       
   278     ...
       
   279     Kern::MutexSignal(*iDataMutex);
       
   280     ...
       
   281     } 
       
   282 </codeblock> <p>A <codeph>DMutex</codeph> is a reference counting object,
       
   283 and is derived from <xref href="GUID-E48F1435-14B6-37F1-BE47-2EA803AFE497.dita"><apiname>DObject</apiname></xref>. This means that once you have
       
   284 finished with it, you must call <codeph>Close()</codeph> on it to reduce the
       
   285 number of open references. </p> <p>In this example, both <codeph>DMutex</codeph> objects
       
   286 are closed in the <codeph>DCrashHandler</codeph> destructor: </p> <codeblock id="GUID-9FAC3B34-D484-53FA-87D9-9AF5EC5C21D2" xml:space="preserve">DCrashHandler::~DCrashHandler()
       
   287     {
       
   288     ...
       
   289     if (iDataMutex)
       
   290         {
       
   291         iDataMutex-&gt;Close(NULL);
       
   292         }
       
   293     if (iHandlerMutex)
       
   294         {
       
   295         iHandlerMutex-&gt;Close(NULL);
       
   296         }
       
   297     ...
       
   298     }</codeblock> </section>
       
   299 <section id="GUID-00E1F006-3D2C-52A3-BFCB-4D6A59321B26"><title>Semaphores</title> <p>A
       
   300 semaphore is synchronisation primitive that you can use: </p> <ul>
       
   301 <li id="GUID-FDB08035-E850-54D3-8D4B-3F589AAC66EC"><p>to signal one thread
       
   302 from another thread </p> </li>
       
   303 <li id="GUID-A9E08C05-C149-5E6A-8062-D26A00BAFBA4"><p>to signal a thread from
       
   304 an Interrupt Service Routine using an IDFC. </p> </li>
       
   305 </ul> <p>In EKA2, there are two types of semaphore: the fast semaphore, and
       
   306 a more general semaphore - the Symbian platform semaphore. Which one you use
       
   307 depends on the needs of your code and the context in which it is runs. </p> <ul>
       
   308 <li id="GUID-381F815A-4B74-519E-AC95-2DF5983DAED2"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-371EE12E-56D6-5520-8FB9-B9B2CE8AB0E1">The fast semaphore</xref>  </p> </li>
       
   309 <li id="GUID-EF9B5D15-914F-5E6B-B47E-BE93612DC322"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-6132B7FF-C664-5E21-8BF5-1BC9BAF00061">The Symbian platform semaphore</xref>  </p> </li>
       
   310 </ul> <p id="GUID-371EE12E-56D6-5520-8FB9-B9B2CE8AB0E1"><b>The fast semaphore</b> </p> <p>A
       
   311 fast semaphore is a fast lightweight mechanism that a thread can use to wait
       
   312 for events. It provides a way of posting events to a single thread because
       
   313 the semaphore can keep count of the number of events posted. </p> <p>A fast
       
   314 semaphore is represented by a <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref> object, and
       
   315 this is implemented by the <i>nanokernel</i>. Remember that a Symbian platform
       
   316 thread, and a thread in a personality layer are also nanokernel threads. </p> <ul>
       
   317 <li id="GUID-F5F04369-2F0B-5FEA-B49A-E90C7C1CAF2D"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-DF231F3F-A702-50DC-9E98-199808D228FD">Rules</xref> </p> </li>
       
   318 <li id="GUID-4AF23A2C-FD0C-557F-93A9-BCDF9D8EC162"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-E75C6B54-64D2-5936-BF38-9AF40F9F7400">How to use</xref>  </p> </li>
       
   319 <li id="GUID-73BE532A-3A55-5995-8615-BE50C615C3BF"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-1F74B3EC-A2E3-5B1E-9C8E-FFF15084C6DF">Example using NFastSemaphore and the NKern functions</xref>  </p> </li>
       
   320 <li id="GUID-45269DDA-FE9C-5075-BEAB-8030A5DC2DC0"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-2C0E4009-3E15-5197-B327-06699BFE2221">Example using the NFastSemaphore::Signal() function</xref>  </p> </li>
       
   321 </ul> <p id="GUID-DF231F3F-A702-50DC-9E98-199808D228FD"><b>Rules</b> </p> <p>Because
       
   322 of its lightweight structure, only the <i>owning thread</i> is allowed to
       
   323 wait on it. </p> <p id="GUID-E75C6B54-64D2-5936-BF38-9AF40F9F7400"><b>How
       
   324 to use</b> </p> <p>Typically you declare a fast semaphore in a class declaration,
       
   325 for example: </p> <codeblock id="GUID-7C06D593-07EC-5A00-950A-FA71A0611753" xml:space="preserve">class DCrashHandler : public DKernelEventHandler
       
   326     {
       
   327     ...
       
   328 private:
       
   329     NFastSemaphore iSem;
       
   330     ...
       
   331     };
       
   332 
       
   333 </codeblock> <p>You need to initialise the <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref> by: </p> <ul>
       
   334 <li id="GUID-76AA23BF-787E-5F02-9293-651D6A2ABCD4"><p>constructing the semaphore </p> </li>
       
   335 <li id="GUID-9DCCF8D9-8196-540F-A843-3E8771CFBBDC"><p>setting the thread that
       
   336 owns the semaphore, i.e. the thread that will be allowed to wait in it. </p> </li>
       
   337 </ul> <p>The semaphore is initialised when its constructor is called. However,
       
   338 setting the owning thread requires explicit code. For example, the following
       
   339 code fragment is typical and sets the owning thread to be the current thread: </p> <codeblock id="GUID-CF5E165F-3512-57C1-9CC3-8EE3077904CA" xml:space="preserve">iSem.iOwningThread = (NThreadBase*)NKern::CurrentThread();</codeblock> <p>Waiting
       
   340 and signalling the fast semaphore is done by using the <codeph>Wait()</codeph> and <codeph>Signal()</codeph> functions
       
   341 of the <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref> class. However, you will normally
       
   342 use the nanokernel functions: </p> <ul>
       
   343 <li id="GUID-238D3B34-3E98-5388-8B33-F0FB47679CDD"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-D2691899-C802-3A4F-9E72-487B07E6E1D0"><apiname>NKern::FSWait()</apiname></xref>  </p> </li>
       
   344 <li id="GUID-94485609-3EAC-5986-ACE6-8485942D2273"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-B4B058FF-F077-3F0A-A344-F6FB36D987C6"><apiname>NKern::FSSignal()</apiname></xref>  </p> </li>
       
   345 </ul> <p>respectively, passing a pointer to your <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref> object. </p> <p>The
       
   346 kernel lock must be held when <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-F6262C01-5999-36D1-AF7D-F7E3741ED411"><apiname>NFastSemaphore::Wait()</apiname></xref> and <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-B1104DF4-7490-33D9-BB64-83E16D9BA723"><apiname>NFastSemaphore::Signal()</apiname></xref> are
       
   347 called. <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-D2691899-C802-3A4F-9E72-487B07E6E1D0"><apiname>NKern::FSWait()</apiname></xref> and <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-B4B058FF-F077-3F0A-A344-F6FB36D987C6"><apiname>NKern::FSSignal()</apiname></xref> do
       
   348 this for you. They make sure that the kernel lock is on while <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-F6262C01-5999-36D1-AF7D-F7E3741ED411"><apiname>NFastSemaphore::Wait()</apiname></xref> and <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-B1104DF4-7490-33D9-BB64-83E16D9BA723"><apiname>NFastSemaphore::Signal()</apiname></xref> are called by wrapping them in a pair of <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-7CBBF72B-4519-38DD-92CA-38AF636AFD8A"><apiname>NKern::Lock()</apiname></xref> and <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-A1A42137-906C-30F1-AF61-4F786FC372DE"><apiname>NKern::Unlock()</apiname></xref> calls. </p> <p>Although
       
   349 this sounds like you will be blocking while holding the kernel lock, in reality
       
   350 you do not because the thread is not blocked until after the kernel lock is
       
   351 released. </p> <p>Be aware however that there may be situations where you
       
   352 already have the kernel lock, or in the case of IDFCs, you do not need to
       
   353 acquire it as no preemption can occur. In these cases, you just call <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-F6262C01-5999-36D1-AF7D-F7E3741ED411"><apiname>NFastSemaphore::Wait()</apiname></xref> and <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-B1104DF4-7490-33D9-BB64-83E16D9BA723"><apiname>NFastSemaphore::Signal()</apiname></xref>. </p> <p>You can use use a fast semaphore to block a thread until an interrupt
       
   354 occurs, but you cannot signal the semaphore directly from the interrupt service
       
   355 routine (ISR) that services that interrupt; instead, you must queue an IDFC,
       
   356 and signal from there. </p> <p id="GUID-1F74B3EC-A2E3-5B1E-9C8E-FFF15084C6DF"><b>Example
       
   357 using NFastSemaphore and the NKern functions</b> </p> <p>This is an example
       
   358 that synchronises threads using the <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref> class,
       
   359 and is part of code that implements a minimal debug agent in a device driver.
       
   360 The full code for this can be found in <filepath>...\e32utils\d_exc\minkda.cpp</filepath>. </p> <p>When
       
   361 a channel is opened, the <codeph>DoCreate()</codeph> function creates a crash
       
   362 handler (in 2 phases).This is a <codeph>DCrashHandler</codeph> object, and
       
   363 importantly, contains a <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref>. </p> <codeblock id="GUID-C092DA58-C4AF-528C-B648-481A3B6EC5A6" xml:space="preserve">class DCrashHandler : public DKernelEventHandler
       
   364     {
       
   365     ...
       
   366 private:
       
   367     NFastSemaphore iSuspendSem; // for suspending crashed thread
       
   368     ...
       
   369     };</codeblock> <p>When a thread panics, or an exception occurs, program
       
   370 control eventually reaches <codeph>DCrashHandler::HandleCrash()</codeph>.
       
   371 It is in this function that the owning thread is set – to the current nanokernel
       
   372 thread (i.e. the one that crashed). This is the only thread allowed to wait
       
   373 on the semaphore. The wait is just a few lines further down in the same function: </p> <codeblock id="GUID-B3543353-C441-542E-B0AA-737F5DFA1ADA" xml:space="preserve">void DCrashHandler::HandleCrash(TAny* aContext)
       
   374     {
       
   375     DThread* pC = &amp;Kern::CurrentThread();
       
   376     ...
       
   377     if (iTrapRq != NULL)
       
   378         {
       
   379         iCrashedThread = pC;
       
   380         iSuspendSem.iOwningThread = &amp;(iCrashedThread-&gt;iNThread);
       
   381         ...
       
   382         }
       
   383     ...
       
   384     if (iCrashedThread)
       
   385         {
       
   386         ...
       
   387         NKern::FSWait(&amp;(iSuspendSem)); // Waits on the semaphore
       
   388         ...
       
   389         }
       
   390     ...
       
   391     }</codeblock> <p>At a later time, the debugger calls the driver’s <codeph>Request()</codeph> function
       
   392 with either the <codeph>ECancelTrap</codeph> or <codeph>EKillCrashedThread</codeph> parameters.
       
   393 One or other of the corresponding functions is called; each function is implemented
       
   394 to signal the semaphore. </p> <codeblock id="GUID-E1D04D58-4614-58B1-B5A4-CA898B58B0E6" xml:space="preserve">void DCrashHandler::CancelTrap()
       
   395     {
       
   396     ...
       
   397     if (iCrashedThread != NULL)
       
   398         {
       
   399         NKern::FSSignal(&amp;(iSuspendSem));
       
   400         }
       
   401     ...
       
   402     }</codeblock> <codeblock id="GUID-FB4B9BE1-272B-5F62-8C88-13FAF89BAE88" xml:space="preserve">void DCrashHandler::KillCrashedThread()
       
   403     {
       
   404     ...
       
   405     NKern::FSSignal(&amp;iSuspendSem);
       
   406     }</codeblock> <p id="GUID-2C0E4009-3E15-5197-B327-06699BFE2221"><b>Example
       
   407 using the NFastSemaphore::Signal() function</b> </p> <p>This is an example
       
   408 code fragment taken from <filepath>...\e32test\misc\d_rndtim.cpp</filepath>. </p> <p>This
       
   409 a device driver that uses a timer. The driver's logical channel can start
       
   410 the timer, and it can wait for the timer to expire. The expiry of the timer
       
   411 results in an interrupt; this results in a call to an ISR that schedules an
       
   412 IDFC, which, in turn, signals the driver's logical channel. </p> <p>Because
       
   413 the kernel is implicitly locked when the IDFC runs, there is no need to explicitly
       
   414 lock the kernel, and <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-B1104DF4-7490-33D9-BB64-83E16D9BA723"><apiname>NFastSemaphore::Signal()</apiname></xref> can be called
       
   415 instead of <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-B4B058FF-F077-3F0A-A344-F6FB36D987C6"><apiname>NKern::FSSignal()</apiname></xref>. </p> <p>The relevant part
       
   416 of the driver's logical channel class is: </p> <codeblock id="GUID-30E361DA-817C-5792-8E61-6CEB37F28FB3" xml:space="preserve">class DRndTim : public DLogicalChannelBase
       
   417     {
       
   418     ...
       
   419 public:
       
   420     NFastSemaphore iSem;
       
   421     ...
       
   422     };</codeblock> <p>The semaphore's owning thread is set in the logical
       
   423 channel's constructor. Note that the constructor is called in the context
       
   424 of the client thread, and it is this thread that is the owner of the semaphore.
       
   425 This must also be the thread that waits for the semaphore, which it does when
       
   426 at some later time it sends an <codeph>EControlWait</codeph> request to the
       
   427 device driver to wait for the timer to expire. </p> <codeblock id="GUID-D32ABAEB-32C2-5D68-B76E-7C45D5828EED" xml:space="preserve">DRndTim::DRndTim()
       
   428     {
       
   429     iThread=&amp;Kern::CurrentThread();
       
   430     iThread-&gt;Open();
       
   431     iSem.iOwningThread = &amp;iThread-&gt;iNThread;
       
   432     ...
       
   433     }</codeblock> <p>The following code shows the implementation of this wait.
       
   434 Note that it assumes that the timer has already been started, which we have
       
   435 not shown here. </p> <p>The wait is initiated using the <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-D2691899-C802-3A4F-9E72-487B07E6E1D0"><apiname>NKern::FSWait()</apiname></xref> function
       
   436 as the kernel must be locked when the wait operation is done on the <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita"><apiname>NFastSemaphore</apiname></xref>. </p> <codeblock id="GUID-52D3817F-3214-5166-A998-35C468CC9BBE" xml:space="preserve">TInt DRndTim::Request(TInt aFunction, TAny* a1, TAny* a2)
       
   437     {
       
   438     TInt r = KErrNotSupported;
       
   439     switch (aFunction)
       
   440         {
       
   441     case RRndTim::EControlWait:
       
   442         NKern::FSWait(&amp;iSem);
       
   443         r = KErrNone;
       
   444         break;
       
   445         ...
       
   446         }
       
   447     ...
       
   448     }</codeblock> <p>When the timer expires, the ISR runs, and this schedules
       
   449 the IDFC, which in turn signals the client thread. The following code is the
       
   450 IDFC implementation. </p> <codeblock id="GUID-907D7F1C-BEE5-5651-9F2A-F7E3421E4BA0" xml:space="preserve">void DRndTim::IDfcFn(TAny* aPtr)
       
   451     {
       
   452     DRndTim* d = (DRndTim*)aPtr;
       
   453     d-&gt;iSem.Signal();
       
   454     }</codeblock> <p>Note that this calls <xref href="GUID-22982E51-E746-37CB-9672-97B58C2672BF.dita#GUID-22982E51-E746-37CB-9672-97B58C2672BF/GUID-B1104DF4-7490-33D9-BB64-83E16D9BA723"><apiname>NFastSemaphore::Signal()</apiname></xref> rather
       
   455 that <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-B4B058FF-F077-3F0A-A344-F6FB36D987C6"><apiname>NKern::FSSignal()</apiname></xref> because IDFCs are called with the
       
   456 kernel locked. </p> <p id="GUID-6132B7FF-C664-5E21-8BF5-1BC9BAF00061"><b>The
       
   457 Symbian platform semaphore</b> </p> <p>Symbian platform semaphores are standard
       
   458 counting semaphores that can be used by one or more Symbian platform threads.
       
   459 The most common use of semaphores is to synchronise processing between threads,
       
   460 i.e. to force a thread to wait until some processing is complete in one or
       
   461 more other threads or until one or more events have occurred. </p> <p>The
       
   462 Symbian platform semaphore is represented by a <xref href="GUID-48D9A672-11AA-3F21-8AB6-AB01032C52A5.dita"><apiname>DSemaphore</apiname></xref> object. </p> <ul>
       
   463 <li id="GUID-FE9B937B-9B60-5C92-A1CA-6FDE7E1623EE"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-A396E34A-2B84-5EFC-8FE8-6DBE68A21A80">Characteristics</xref> </p> </li>
       
   464 <li id="GUID-3880A591-1512-518E-8607-E5737C7B84A5"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-6131CDB0-6249-5B9A-A969-9B25F8BCECF5">Rules</xref> </p> </li>
       
   465 <li id="GUID-B97B8B09-CD5B-57E2-9E7F-AD1DD90847AA"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-915A061E-C85E-5165-A12F-B3B214756AE0">How to use</xref>  </p> </li>
       
   466 </ul> <p id="GUID-A396E34A-2B84-5EFC-8FE8-6DBE68A21A80"><b>Characteristics</b> </p> <p>A
       
   467 Symbian platform semaphore is based on the value of a count, which the <codeph>DSemaphore</codeph> object
       
   468 maintains. The value of the count indicates whether there are any threads
       
   469 waiting on it. The general behaviour is: </p> <ul>
       
   470 <li id="GUID-D71A8532-4D3B-5748-81C5-8E40C91FB4D3"><p>if the count is positive
       
   471 or zero, then there are no threads waiting </p> </li>
       
   472 <li id="GUID-8C86A1DF-14D4-55DD-8511-FA51C4706FBF"><p>if the count is negative,
       
   473 the magnitude of the value is the number of threads that are waiting on it. </p> </li>
       
   474 </ul> <p>There are two basic operations on semaphores: </p> <ul>
       
   475 <li id="GUID-4193B915-82FB-5648-AD41-C1D5E345A8F1"><p>WAIT - this decrements
       
   476 the count atomically. If the count remains non-negative the calling thread
       
   477 continues to run; if the count becomes negative the calling thread is blocked. </p> </li>
       
   478 <li id="GUID-F39A0E98-8662-5B7B-B266-027885DB3F6A"><p>SIGNAL - this increments
       
   479 the count atomically. If the count was originally negative the next highest
       
   480 priority waiting thread is released. </p> </li>
       
   481 </ul> <p>Waiting threads are released in descending order of priority. Note
       
   482 however that threads that are explicitly suspended as well as waiting on a
       
   483 semaphore, are not kept on the semaphore wait queue; instead they are kept
       
   484 on a separate suspended queue. Such threads are not regarded as waiting for
       
   485 the semaphore; this means that if the semaphore is signalled, they will not
       
   486 be released, and the semaphore count will just increase and may become positive. </p> <p>Symbian
       
   487 platform semaphore operations are protected by the <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-A0FB7718-F39C-5FB3-B67C-430B490F6430">system lock</xref> fast mutex rather than by locking the kernel. To guarantee
       
   488 this, semaphore operations are done through kernel functions. </p> <p>Although
       
   489 somewhat artificial, and not based on real code, the following diagram nevertheless
       
   490 shows the basic idea behind Symbian platform semaphores. </p> <fig id="GUID-505BC4A5-BBCB-5A63-9795-C751719661BB">
       
   491 <title>Symbian platform semaphore</title>
       
   492 <image href="GUID-0FE0B646-A62F-55A8-A6E6-587D0909CE19_d0e74784_href.png" placement="inline"/>
       
   493 </fig> <p id="GUID-6131CDB0-6249-5B9A-A969-9B25F8BCECF5"><b>Rules</b> </p> <p>There
       
   494 are a few rules about the use of Symbian platform semaphores: </p> <ul>
       
   495 <li id="GUID-B850F00A-D7E6-5542-9D9D-F07F2625E29B"><p>Only Symbian platform
       
   496 threads are allowed to use Symbian platform semaphores </p> </li>
       
   497 <li id="GUID-C848306E-7407-5397-8638-DB6AB7250A4E"><p>An IDFC is not allowed
       
   498 to signal a Symbian platform semaphore. </p> </li>
       
   499 </ul> <p id="GUID-915A061E-C85E-5165-A12F-B3B214756AE0"><b>How to use</b> </p> <p>Typically
       
   500 you declare the Symbian platform semaphore in a class declaration, for example: </p> <codeblock id="GUID-19168C17-C570-5FEE-9339-FEA37E6D0043" xml:space="preserve">class X
       
   501     {
       
   502     ...
       
   503 private:
       
   504     DSemaphore* iSemaphore;
       
   505     ...
       
   506     };
       
   507 
       
   508 </codeblock> <p>You cannot create a <codeph>DSemaphore</codeph> object directly;
       
   509 instead you must use the kernel function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-8D0C749E-BB1E-3DC1-85CD-945313F07146"><apiname>Kern::SemaphoreCreate()</apiname></xref>.
       
   510 You pass a <codeph>DSemaphore*</codeph> type to the kernel function, which
       
   511 creates the <codeph>DSemaphore</codeph> object and returns a reference to
       
   512 it through the <codeph>DSemaphore</codeph> pointer. </p> <p>Waiting on the
       
   513 semaphore and signalling the semaphore are done using the kernel functions: </p> <ul>
       
   514 <li id="GUID-258E8300-3E13-502F-95C4-42DBA956BA0E"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B7442064-FD21-3DCE-A412-4233D36A8D10"><apiname>Kern::SemaphoreWait()</apiname></xref>  </p> </li>
       
   515 <li id="GUID-4FF62788-06FB-5F71-A8AE-3539E498E05A"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-F25FACED-5030-304D-95FA-8A1AE48565F3"><apiname>Kern::SemaphoreSignal()</apiname></xref>  </p> </li>
       
   516 </ul> <p>respectively, passing a reference to the <codeph>DSemaphore</codeph> object
       
   517 created earlier. Note that although you pass a <codeph>DSemaphore</codeph> object
       
   518 around, the member functions and member data of the class are considered as
       
   519 internal to Symbian platform, and indeed the member functions are not exported
       
   520 and are not accessible except to the kernel itself. However, you can call <codeph>Open()</codeph> and <codeph>Close()</codeph> on <codeph>DSemaphore</codeph> as they are members of the base class <xref href="GUID-E48F1435-14B6-37F1-BE47-2EA803AFE497.dita"><apiname>DObject</apiname></xref>. </p> </section>
       
   521 <section id="GUID-7E632FD5-03B6-5D39-8A97-8F1948F2BB5B"><title>Thread critical
       
   522 section</title> <p>Putting a thread into a thread critical section prevents
       
   523 it being killed or panicked. Any kill or panic request is deferred until the
       
   524 thread leaves the critical section. </p> <p>A thread critical section is used
       
   525 to protect a section of code that is changing a global data structure or some
       
   526 other global resource. Killing a thread that is in the middle of manipulating
       
   527 such a global data structure might leave it in a corrupt state, or marked
       
   528 is being "in use". </p> <p>A thread critical section only applies to code
       
   529 that is running on the kernel side but in the context of a user thread. Only
       
   530 user threads can be terminated or panicked by another thread. </p> <p>In practice,
       
   531 a thread critical section only applies to code implementing a <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita#GUID-E7550422-5121-3393-A85E-BB797969CD2A/GUID-FD4DA73F-45E7-37BE-9380-1D8ED36114F7"><apiname>DLogicalChannelBase::Request()</apiname></xref> function
       
   532 or a HAL function handler. </p> <p id="GUID-F66BB67F-DFC4-5580-966B-C9F94359474A"><b>How
       
   533 to use</b> </p> <p>Enter a thread critical section by calling: <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-841D587C-E9E6-34EE-8ED0-E9A206F64379"><apiname>NKern::ThreadEnterCS()</apiname></xref>. </p> <p>Exit
       
   534 a thread critical section by calling: <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-2C897BA5-2BD7-3ABA-9F2B-F0B1AC14D1AE"><apiname>NKern::ThreadLeaveCS()</apiname></xref>. </p> <p>Note: </p> <ul>
       
   535 <li id="GUID-370A2F89-8D66-5328-8805-211EF1E46601"><p>it is important that
       
   536 you only hold a thread critical section for the absolute minimum amount of
       
   537 time it takes to access and change the resource. </p> </li>
       
   538 <li id="GUID-85613CB2-247E-5030-A971-2942B948FF09"><p>you do not need to be
       
   539 in a critical section to hold a <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-09377BC3-770A-5558-B3A9-A7E2CE11EBC3">fast
       
   540 mutex</xref> because a thread holding a fast mutex is implicitly in a critical
       
   541 section. </p> </li>
       
   542 </ul> <p>There are a large number of examples scattered throughout Symbian
       
   543 platform source code. </p> </section>
       
   544 <section id="GUID-7AECE882-9D48-5109-AE38-38BF0F8F717F"><title>Atomic operations</title> <p>There
       
   545 are a number of functions provided by the <i>nanokernel</i> that allow you
       
   546 to do atomic operations, and may be useful when synchronising processing or
       
   547 ensuring that data is safely read and/or updated. </p> <p>This is a list of
       
   548 the functions that are available. The function descriptions provide sufficient
       
   549 information for their use. </p> <ul>
       
   550 <li id="GUID-24420BA8-DC26-5B60-86B5-6D5511C7212E"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-D8F0CA07-9810-3AE0-8473-546D91D43572"><apiname>NKern::SafeSwap()</apiname></xref>  </p> </li>
       
   551 <li id="GUID-105922AC-FC67-59B8-A945-E7CEF77B3DEF"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-D953B3A2-5C7A-30E2-9917-3C4DD33DCEF4"><apiname>NKern::SafeSwap8()</apiname></xref>  </p> </li>
       
   552 <li id="GUID-D71AF10C-7251-58A7-A4C5-0B3D54CD518C"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-605C9857-3E5F-3202-B0CC-02F5C717B872"><apiname>NKern::LockedInc()</apiname></xref>  </p> </li>
       
   553 <li id="GUID-AE5C0560-D159-5AC9-804E-11F8EB9F9677"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-91FFC47D-2350-35A9-B3EA-F045902B68FE"><apiname>NKern::LockedDec()</apiname></xref>  </p> </li>
       
   554 <li id="GUID-414F83A6-6934-567C-BD90-AB5818BE76A5"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-2E36C0A3-D0EC-36AF-A018-4F4C793C1EF4"><apiname>NKern::LockedAdd()</apiname></xref>  </p> </li>
       
   555 <li id="GUID-DB617589-FED2-53A4-83A8-97089AC6F67E"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-0B55EEDB-942D-3F5F-BF81-6FD52EEBBE0F"><apiname>NKern::LockedSetClear()</apiname></xref>  </p> </li>
       
   556 <li id="GUID-18F0D485-0FD6-5532-94C8-3A1B7182CE66"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-0AD0756E-41BE-33CF-A3D3-7802A15534B4"><apiname>NKern::LockedSetClear8()</apiname></xref>  </p> </li>
       
   557 </ul> </section>
       
   558 <section id="GUID-A0FB7718-F39C-5FB3-B67C-430B490F6430"><title>The system
       
   559 lock</title> <p>The system lock is a specific fast mutex that only provides
       
   560 exclusion against other threads acquiring the same fast mutex. Setting, and
       
   561 acquiring the system lock means that a thread enters an implied critical section. </p> <p>The
       
   562 major items protected by the system lock are: </p> <ul>
       
   563 <li id="GUID-F7AF7E09-EE89-5B0E-B220-355E19F2C5DD"><p> <codeph>DThread</codeph> member
       
   564 data related to thread priority and status. </p> </li>
       
   565 <li id="GUID-BFF35EE1-7173-5827-BCE1-0A6AF9473289"><p>the consistency of the
       
   566 memory map. On the kernel side, the state of user side memory or the mapping
       
   567 of a process is not guaranteed unless one or other of the following conditions
       
   568 is true: </p> <ul>
       
   569 <li id="GUID-1A853DAF-83D9-5787-BD55-E33153248B0B"><p>you are a thread belonging
       
   570 to the process that owns the memory. </p> </li>
       
   571 <li id="GUID-2ADC2FDE-75F8-5E50-B4E7-9699559CADEB"><p>you hold the system
       
   572 lock. </p> </li>
       
   573 </ul> </li>
       
   574 <li id="GUID-6F41B4EB-C060-5FC6-BF74-DBFDFA0E3343"><p>the lifetime of <codeph>DObject</codeph> type
       
   575 objects and references to them, including handle translation in Exec dispatch. </p> </li>
       
   576 </ul> <p>Note that the system lock is different from the kernel lock; the
       
   577 kernel lock protects against any rescheduling. When the system lock is set,
       
   578 the calling thread can still be preempted, even in the locked section. </p> <ul>
       
   579 <li id="GUID-CD6EB1A4-E0D1-5D3B-8351-954C2612E1E8"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-87724201-9A89-5AFB-A035-D07A7DC0510F">How to use</xref>  </p> </li>
       
   580 <li id="GUID-9B6B6A29-9AC7-5048-A1CF-0F4EC6C929E8"><p> <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-3337309D-C048-57D5-9A86-7F3BFF5E239C">When to use</xref>  </p> </li>
       
   581 </ul> <p id="GUID-87724201-9A89-5AFB-A035-D07A7DC0510F"><b>How to use</b> </p> <p>The
       
   582 system lock is set by a call to <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-B3837744-B8CC-3DC0-BA1D-417016E88EE9"><apiname>NKern::LockSystem()</apiname></xref>. </p> <p>The
       
   583 system lock is unset by a call to <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-63B882C8-C5D0-3595-BBF1-74E942A5060A"><apiname>NKern::UnlockSystem()</apiname></xref>  </p> <p id="GUID-3337309D-C048-57D5-9A86-7F3BFF5E239C"><b>When to use</b> </p> <p>Only
       
   584 use the system lock when you access a kernel resource that is protected by
       
   585 the system lock. Generally you will not access these directly but will use
       
   586 a kernel function, and the preconditions will tell you whether you need to
       
   587 hold the system lock. </p> </section>
       
   588 <section id="GUID-1806CDC5-9941-5CFC-B1F1-82BBA8D4F65B"><title>The kernel
       
   589 lock</title> <p>The kernel lock disables the scheduler so that the currently
       
   590 running thread cannot be pre-empted. It also prevent IDFCs from running. If
       
   591 the kernel lock is not set, then IDFCs can run immediately after ISRs </p> <p>Its
       
   592 main purpose is to prevent code from being reentered and corrupting important
       
   593 global structures such as the thread-ready list. </p> <p id="GUID-493A2BEA-E268-5476-90DE-3C12DB91E25C"><b>How
       
   594 to use</b> </p> <p>The kernel lock is set by a call to <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-7CBBF72B-4519-38DD-92CA-38AF636AFD8A"><apiname>NKern::Lock()</apiname></xref>. </p> <p>The
       
   595 kernel lock is unset by a call to <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-A1A42137-906C-30F1-AF61-4F786FC372DE"><apiname>NKern::Unlock()</apiname></xref>  </p> <p id="GUID-6B734C56-8473-5C3C-803D-24D6E8CBEFAD"><b>When to use</b> </p> <p> <b> ALMOST
       
   596 NEVER</b>. </p> <p>The kernel exports this primarily for use by personality
       
   597 layers, which need to modify the thread-ready list. In general, you should
       
   598 use a <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-09377BC3-770A-5558-B3A9-A7E2CE11EBC3">fast
       
   599 mutex</xref> for thread synchronisation. </p> </section>
       
   600 <section id="GUID-961912E5-2D89-518A-A6EA-3AAC15D17B81"><title>Disabling interrupts</title> <p>This
       
   601 is the most drastic form of synchronisation. With interrupts disabled, timeslicing
       
   602 cannot occur. If interrupts are disabled for any length of time, the responsiveness
       
   603 of the whole system may be threatened, and real time guarantees may be invalidated. </p> <p><b>How
       
   604 to use</b> </p> <p>There are three functions supplied by the <i>nanokernel</i> involved
       
   605 in disabling and enabling interrupts. </p> <ul>
       
   606 <li id="GUID-3D0B9AC3-8033-5E65-AE05-21042D11C2B5"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-CA1C36B7-02EE-31D5-B700-27DE4769ECCF"><apiname>NKern::DisableInterrupts()</apiname></xref>  </p> </li>
       
   607 <li id="GUID-EFFAF15F-180B-5A0E-B4E2-106917125E27"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-8C251C65-FDE7-3161-8D2B-61401FB6487F"><apiname>NKern::DisableAllInterrupts()</apiname></xref>  </p> </li>
       
   608 <li id="GUID-A0575FE2-E5B3-5C72-A99A-F017AEE580CD"><p> <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-2D328082-3A9F-3467-81CF-B1C68866E163"><apiname>NKern::RestoreInterrupts()</apiname></xref>  </p> </li>
       
   609 </ul> <p><b>When to use</b> </p> <p> <b> NEVER</b>. </p> <p>Unless there is
       
   610 absolutely no other suitable technique. You would probably only use this to
       
   611 protect some data that is shared between an interrupt service routine and
       
   612 a thread (or a DFC). Nevertheless, you may find that <xref href="GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5.dita#GUID-EAA6A9FB-A470-550C-B7B4-FF68A733A2D5/GUID-7AECE882-9D48-5109-AE38-38BF0F8F717F">atomic operations</xref> are more suitable. </p> </section>
       
   613 </conbody></concept>