Symbian3/PDK/Source/GUID-42F8FA5A-BBE4-50DE-917E-D05755019FEC.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     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-42F8FA5A-BBE4-50DE-917E-D05755019FEC" xml:lang="en"><title>Personality
       
    13 Layer Design</title><shortdesc>Provides some guidelines for the design of a personality layer
       
    14 for real time Applications for the Kernel.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <section id="GUID-A0EC87BF-170D-46B4-AEFF-F21D7483149B"><title>Memory management</title> <p>The personality layer assumes
       
    16 that the RTA will run in a single flat address space in which there is neither
       
    17 protection between different parts of the application nor protection of any
       
    18 hardware or CPU resource from any part of the application. For example, any
       
    19 part of the application code can access any I/O port, and can disable interrupts. </p> <p>To
       
    20 get this behaviour under the Kernel Architecture 2, the RTA must run in supervisor
       
    21 mode in the kernel address space. The obvious way to do this is to make the
       
    22 RTA together with the personality layer a kernel extension. This also ensures
       
    23 that it is started automatically early on in the boot process. </p> <p>In
       
    24 general the RTA will have its own memory management strategy and will not
       
    25 wish to use the standard Symbian platform memory management system. To achieve
       
    26 this, the personality layer will allocate a certain fixed amount of RAM for
       
    27 use by the real time application at boot time. For a telephony stack this
       
    28 will be around 128K - 256K. This can be done either by including it in the
       
    29 kernel extension's <filepath>.bss</filepath> section, or by making a one-time
       
    30 allocation on the kernel heap at boot time. Depending on the RTA requirements,
       
    31 the personality layer can manage this area of RAM (if the RTOS being emulated
       
    32 provides memory management primitives) or the RTA can manage it. </p> </section>
       
    33 <section id="GUID-FAA30849-282F-4E2D-ABDA-63E130A2D2FB"><title>Threads and mapping thread priorities</title> <p>A nanokernel
       
    34 thread will be used for each RTOS thread </p> <p>A priority mapping scheme
       
    35 will be required to map RTOS priorities, of which there are typically 64 to
       
    36 256 distinct values, to nanokernel priorities. As long as the RTA does not
       
    37 use more than 35 threads running simultaneously, which is usually the case,
       
    38 it should be possible to produce a mapping scheme that allows each thread
       
    39 to have a distinct priority, if needed. If this limit is exceeded, it will
       
    40 be necessary to fold some priorities together. </p> <p>Note that any attempt
       
    41 to increase the number of priorities supported by both the nanokernel and
       
    42 the Symbian platform kernel would be <i>prohibitively</i> expensive in terms
       
    43 of RAM usage. </p> </section>
       
    44 <section id="GUID-169604BD-A22A-5B56-8279-13F875AB4AB6"><title>Communication
       
    45 between Symbian platform and the RTOS Environments</title> <p>To allow the
       
    46 functionality of the RTA to be available to Symbian platform applications,
       
    47 it is necessary that a mechanism exist by which Symbian platform code and
       
    48 the RTA may communicate with each other. In practice this means: </p> <ul>
       
    49 <li id="GUID-DC8AF97D-EA8A-5852-96FF-CCA19D69F614"><p>it must be possible
       
    50 for a Symbian platform thread to cause an RTOS thread to be scheduled and
       
    51 vice-versa </p> </li>
       
    52 <li id="GUID-EF671D7A-28B6-505D-823C-5B51C378225E"><p>it must be possible
       
    53 for data to be transferred between Symbian platform and RTOS threads in both
       
    54 directions. </p> </li>
       
    55 </ul> <p>It will usually be possible for a Symbian platform thread to make
       
    56 standard personality layer calls (the same calls that RTOS threads would make)
       
    57 in order to cause an RTOS thread to be scheduled. This is because the nanokernel
       
    58 underlies both types of thread and most 'signal' type operations (i.e. those
       
    59 that make threads ready rather than blocking them) can be implemented using
       
    60 operations which make no reference to the calling thread, and which are therefore
       
    61 not sensitive to which type of thread they are called from. </p> <p>The standard
       
    62 personality layer calls will not work in the other direction, since it will
       
    63 not be possible for a Symbian platform thread to wait on a personality layer
       
    64 wait object. The most straightforward way for RTOS threads to trigger scheduling
       
    65 of a Symbian platform thread would be to enque a DFC on a queue operated by
       
    66 a Symbian platform thread. Another possibility would be for the Symbian platform
       
    67 thread to wait on a fast semaphore which could then be signalled by the RTOS
       
    68 thread. However the DFC method fits better with the way device drivers are
       
    69 generally written. A device driver will be necessary to mediate communication
       
    70 between Symbian platform user mode processes and the RTA since the latter
       
    71 runs kernel side. </p> <p>All data transfer between the two environments must
       
    72 occur kernel side. It will not be possible for any RTOS thread to access normal
       
    73 user side memory since the functions provided for doing so access parts of
       
    74 the <xref href="GUID-38D1534C-AA01-33AF-9937-CDD818A85F97.dita"><apiname>DThread</apiname></xref> structure representing the Symbian platform
       
    75 calling thread, for example to perform exception trapping. Some possibilities
       
    76 for the data transfer mechanism are: </p> <ul>
       
    77 <li id="GUID-96A247AA-BA1C-50E5-8400-5487DFF5991D"><p>A fairly common architecture
       
    78 for real time applications involves a fixed block size memory manager and
       
    79 message queues for inter-thread communication. The memory manager supports
       
    80 allocation and freeing of memory in constant time. The sending thread allocates
       
    81 a memory block, places data in it and posts it to the receiving thread's message
       
    82 queue. The receiving thread then processes the data and frees the memory block,
       
    83 or possibly passes the block to yet another thread. It would be a simple proposition
       
    84 to produce such a system in which the memory manager could be used by any
       
    85 thread. In that case a Symbian platform thread could pass messages to RTOS
       
    86 threads in the same way as other RTOS threads. Passing data back would involve
       
    87 a special type of message queue implemented in the personality layer. When
       
    88 a message was sent to a Symbian platform thread a DFC would be enqueued. That
       
    89 DFC would then process the message data and free the memory block as usual.
       
    90 This scheme combines the data transfer and scheduling aspects of communication. </p> </li>
       
    91 <li id="GUID-1D2B6085-7B3A-51EF-BFF6-865D4AF94E5A"><p>Any standard buffering
       
    92 arrangement could be used between the RTA and the device driver (e.g. circular
       
    93 buffers). Contention between threads could be prevented using nanokernel fast
       
    94 mutexes, on which any thread can wait, or by the simpler means of disabling
       
    95 preemption or disabling interrupts. It will also be possible for RTOS threads
       
    96 to make use of shared I/O buffers for transfer direct to user mode clients,
       
    97 provided that these buffers are set up by the Symbian platform device driver
       
    98 thread. This may be useful as a way to reduce copying overhead if bulk data
       
    99 transfer is necessary between the two domains. </p> </li>
       
   100 </ul> </section>
       
   101 <section id="GUID-09CC8168-50FD-49ED-8376-05C00C3243FA"><title>Synchronisation/communication primitives</title> <p>The nanokernel
       
   102 does not support most of the synchronisation and communication primitives
       
   103 provided by a standard RTOS. Any such primitives required by the RTA will
       
   104 have to be implemented in the personality layer. This means that the personality
       
   105 layer needs to define new types of object on which threads can wait. This
       
   106 in turn means that new nanokernel thread states (N-state) must be defined
       
   107 to signify that a thread is waiting on an object of the new type. In general,
       
   108 each new type of wait object requires an accompanying new nanokernel thread
       
   109 state. </p> <p><b>Blocking
       
   110 a thread on a wait object</b> </p> <p>To make a thread block on a new type
       
   111 of wait object, call the nanokernel function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-72F2E4E0-B498-32D2-BB24-E79AC66EFDDB"><apiname>Kern::NanoBlock()</apiname></xref>,
       
   112 passing the maximum time for which the thread should block, the new N-state
       
   113 value, and a pointer to the wait object. </p> <p>Use the <codeph>TPriListLink</codeph> base
       
   114 class of <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita"><apiname>NThreadBase</apiname></xref> to attach the thread to a list of
       
   115 threads waiting on the object. Note that this must be done after calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-72F2E4E0-B498-32D2-BB24-E79AC66EFDDB"><apiname>Kern::NanoBlock()</apiname></xref>.
       
   116 As preemption is disabled before this function is called, a reschedule will
       
   117 not occur immediately, but will be deferred until preemption is reenabled. </p> <p id="GUID-5017FB0A-5C1E-5C88-9315-E12C12D9639F"><b>State handler</b> </p> <p>Every
       
   118 thread that can use a new type of wait object, must have a nanokernel state
       
   119 handler installed to handle operations on that thread when it is waiting on
       
   120 that wait object. A nanokernel state handler is a function that has the following
       
   121 signature: </p> <codeblock id="GUID-31E807F7-250B-552D-8480-5F282C151565" xml:space="preserve">void StateHandler(NThread* aThread, TInt aOp, TInt aParam);</codeblock> <ul>
       
   122 <li id="GUID-B8ECADB3-0345-56CB-8C7A-6D4E8CE15726"><p> <codeph> aThread</codeph> is
       
   123 a pointer to the thread involved. </p> </li>
       
   124 <li id="GUID-711957A1-4D01-5F8B-BF67-70EB8F39D20B"><p> <codeph> aOp</codeph> is
       
   125 one of the <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-FF52640A-87C9-319B-B4C6-F6B860171229"><apiname>NThreadBase::NThreadOperation</apiname></xref> values that indicates
       
   126 which operation is being performed on the thread. </p> </li>
       
   127 <li id="GUID-FF54386A-D163-5F53-B230-296BE402C9E6"><p> <codeph> aParam</codeph> is
       
   128 a parameter that depends on <codeph>aOp</codeph>. </p> </li>
       
   129 </ul> <p>Note that the state handler is always called with preemption disabled. </p> <p>The
       
   130 possible values of <codeph>aOp</codeph> are: </p> <table id="GUID-F4372C47-F491-55E2-B06E-2C68628B5BC5">
       
   131 <tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
       
   132 <tbody>
       
   133 <row>
       
   134 <entry><p> <codeph>aOp</codeph> value </p> </entry>
       
   135 <entry><p>Description </p> </entry>
       
   136 </row>
       
   137 <row>
       
   138 <entry><p> <codeph>ESuspend</codeph>  </p> </entry>
       
   139 <entry><p>Called if the thread is suspended while not in a critical section
       
   140 and not holding a fast mutex. Called in whichever context <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-FF94D458-C2D0-3D20-ADD6-AAE68A3296C3"><apiname>NThreadBase::Suspend()</apiname></xref> is
       
   141 called from. </p> <p> <codeph>aParam</codeph> contains the requested suspension
       
   142 count. </p> </entry>
       
   143 </row>
       
   144 <row>
       
   145 <entry><p> <codeph>EResume</codeph>  </p> </entry>
       
   146 <entry><p>Called if the thread is resumed while actually suspended, and the
       
   147 last suspension has been removed. Called in whichever context <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-C0A6E734-7DE6-37B9-AAB2-A2A0E2664731"><apiname>NThreadBase::Resume()</apiname></xref> is
       
   148 called from. </p> <p> <codeph>aParam</codeph> contains no additional information. </p> </entry>
       
   149 </row>
       
   150 <row>
       
   151 <entry><p> <codeph>EForceResume</codeph>  </p> </entry>
       
   152 <entry><p>Called if the thread has all suspensions cancelled while actually
       
   153 suspended. Called in whichever context <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-BE92FBC3-A7D9-3576-A1A9-7BBA6EE64226"><apiname>NThreadBase::ForceResume()</apiname></xref> is
       
   154 called from. </p> <p> <codeph>aParam</codeph> contains no additional information. </p> </entry>
       
   155 </row>
       
   156 <row>
       
   157 <entry><p> <codeph>ERelease</codeph>  </p> </entry>
       
   158 <entry><p>Called if the thread is released from its wait. This call should
       
   159 make the thread ready if necessary. Called in whichever context <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-1B24AC4E-C4A1-32AE-BC6E-DC3131116EF8"><apiname>NThreadBase::Release()</apiname></xref> was
       
   160 called from. </p> <p> <codeph>aParam</codeph> is the value passed into <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-1B24AC4E-C4A1-32AE-BC6E-DC3131116EF8"><apiname>NThreadBase::Release()</apiname></xref> to
       
   161 be used as a return code. </p> <p>If <codeph>aParam</codeph> is non-negative,
       
   162 this indicates normal termination of the wait condition. </p> <p>If <codeph>aParam</codeph> is
       
   163 negative, it indicates early or abnormal termination of the wait; in this
       
   164 case the wait object should be rolled back as if the wait had never occurred.
       
   165 For example, a semaphore's count needs to be incremented if <codeph>aParam</codeph> is
       
   166 negative, since in that case the waiting thread never acquired the semaphore. </p> </entry>
       
   167 </row>
       
   168 <row>
       
   169 <entry><p> <codeph>EChangePriority</codeph>  </p> </entry>
       
   170 <entry><p>Called if the thread's priority is changed. Called in whichever
       
   171 context <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-A92E7B01-C1D0-3997-B3E1-2E54229FFA75"><apiname>NThreadBase::SetPriority()</apiname></xref> is called from. This
       
   172 function should set the <codeph>iPriority</codeph> field of the thread, after
       
   173 doing any necessary priority queue manipulations. </p> <p> <codeph>aParam</codeph> contains
       
   174 the new priority. </p> </entry>
       
   175 </row>
       
   176 <row>
       
   177 <entry><p> <codeph>ELeaveCS</codeph>  </p> </entry>
       
   178 <entry><p>Called in the context of the thread concerned if the thread calls <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> with
       
   179 an unknown <codeph>iCsFunction</codeph> that is negative but not equal to <codeph>ECsExitPending</codeph>. </p> <p>aParam
       
   180 contains the value of <codeph>iCsFunction</codeph>. </p> </entry>
       
   181 </row>
       
   182 <row>
       
   183 <entry><p> <codeph>ETimeout</codeph>  </p> </entry>
       
   184 <entry><p>Called if the thread's wait time-out expires and no time-out handler
       
   185 is defined for that thread. Called in the context of the nanokernel timer
       
   186 thread (DfcThread1). This should cancel the wait and arrange for an appropriate
       
   187 error code to be returned. The handler for this condition will usually do
       
   188 the same thing as the handler for <codeph>ERelease</codeph> with a parameter
       
   189 of <xref href="GUID-BAC2386E-8168-3CDB-9F9F-180319EF6920.dita"><apiname>KErrTimedOut</apiname></xref>. </p> <p> <codeph>aParam</codeph> contains
       
   190 no additional information. </p> </entry>
       
   191 </row>
       
   192 </tbody>
       
   193 </tgroup>
       
   194 </table> <p>See the code in <filepath>...\e32\personality\example\...</filepath> for
       
   195 practical examples. </p> <p><b>Releasing
       
   196 the thread</b> </p> <p>When a thread's wait condition is resolved, the nanokernel
       
   197 function <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-1B24AC4E-C4A1-32AE-BC6E-DC3131116EF8"><apiname>NThreadBase::Release()</apiname></xref> should be called. This
       
   198 takes a single <xref href="GUID-7A2A43EC-6125-3BFE-834B-23C37F7B40D5.dita"><apiname>TInt</apiname></xref> parameter. </p> <p>The parameter is
       
   199 usually <xref href="GUID-6CA4F1ED-7947-3087-B618-D35858FAA3BC.dita"><apiname>KErrNone</apiname></xref>, if the wait condition is resolved normally.
       
   200 A typical example is where the semaphore on which the thread is waiting, is
       
   201 signalled. A negative parameter value is used for an abnormal termination,
       
   202 and in this case, the wait object may need to be rolled back. </p> <p> <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-1B24AC4E-C4A1-32AE-BC6E-DC3131116EF8"><apiname>NThreadBase::Release()</apiname></xref> should
       
   203 be called with preemption disabled. It performs the following actions: </p> <ul>
       
   204 <li id="GUID-6697024F-ED05-5C5A-A834-EA89402AE173"><p>sets the <codeph>NThreadBase::iWaitObj</codeph> field
       
   205 to NULL </p> </li>
       
   206 <li id="GUID-C1DF3120-4FD3-5B6C-90F8-6D8C7CAD0B88"><p>cancels the wait timer
       
   207 if it is still running </p> </li>
       
   208 <li id="GUID-6E346E2B-4F94-56FB-8372-8260BCC4CA8C"><p>stores the supplied
       
   209 return code in <codeph>NThreadBase::iReturnCode</codeph>  </p> </li>
       
   210 <li id="GUID-3AF577DB-41A9-553E-9EFD-6F0DA2FADCEA"><p>calls the <xref href="GUID-42F8FA5A-BBE4-50DE-917E-D05755019FEC.dita#GUID-42F8FA5A-BBE4-50DE-917E-D05755019FEC/GUID-5017FB0A-5C1E-5C88-9315-E12C12D9639F">state handler</xref> passing <codeph>ERelease</codeph> and the return code.
       
   211 If the return code is negative this should remove the thread from any wait
       
   212 queues and roll back the state of the wait object. In any case it should call <xref href="GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC.dita#GUID-379D9320-AC3C-3206-8A5D-EE6E5983EBDC/GUID-82E43D79-721D-31A9-B9ED-1277F2300914"><apiname>NThreadBase::CheckSuspendThenReady()</apiname></xref> to
       
   213 make the thread ready again if necessary. </p> </li>
       
   214 </ul> </section>
       
   215 <section id="GUID-1FF1CFE8-41E3-4912-AE28-39D289442BB7"><title>Thread scheduling following a hardware interrupt</title> <p>Most
       
   216 RTOS allow interrupt service routines (ISRs) to perform operations such as
       
   217 semaphore signal, queue post, set event flag directly, usually using the same
       
   218 API as would be used in a thread context. The Kernel Architecture 2 nanokernel
       
   219 does not allow this; ISRs can only queue an IDFC or DFC. </p> <p>The way to
       
   220 get round this limitation is to incorporate an IDFC into each personality
       
   221 layer wait object. The personality layer API involved then needs to check
       
   222 whether it is being invoked from an ISR or a thread and, in the first case,
       
   223 it queues the IDFC. It may need to save some other information for use by
       
   224 the IDFC, for example, it may need to maintain a list of messages queued from
       
   225 ISRs, a count of semaphore signals from ISRs or a bit mask of event flags
       
   226 set by ISRs. Checking for invocation from an ISR can be done either by using <xref href="GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02.dita#GUID-3A3C08F3-3D33-3D9E-80E7-7855C7B21E02/GUID-9542588A-2920-3CB0-A2C0-A55FA6BC29A2"><apiname>NKern::CurrentContext()</apiname></xref>,
       
   227 or by checking the CPSR directly; if doing the latter note that any mode other
       
   228 than USR or SVC on the ARM counts as interrupt context. </p> <p>Hardware interrupts
       
   229 serviced by the RTA will need to conform to the same pattern as those serviced
       
   230 by Symbian platform extensions or device drivers. This means that the standard
       
   231 preamble must run before the actual service routine and the nanokernel interrupt
       
   232 postamble must run after the service routine to enable reschedules to occur
       
   233 if necessary. This can be done by calling <codeph>Interrupt::Bind()</codeph> as
       
   234 provided by the base port during RTA initialisation (possibly via a personality
       
   235 layer call if it must be called from C code). See also <xref href="GUID-3C34724F-B476-5329-B0B1-6D5A34294979.dita">Interrupt
       
   236 Dispatcher Tutorial</xref>. </p> </section>
       
   237 </conbody><related-links>
       
   238 <link href="GUID-5B1D8D9C-90EF-5FCC-8D7D-01B13D6C2E68.dita"><linktext>Nanokernel</linktext>
       
   239 </link>
       
   240 <link href="GUID-2700AAC8-A034-5E7D-B0E0-26B49E68BB18.dita"><linktext>Personality
       
   241 Layer for Real                 Time Applications</linktext></link>
       
   242 </related-links></concept>