Symbian3/PDK/Source/GUID-5BDE6462-E6CA-5738-A587-C7D875574789.dita
changeset 3 46218c8b8afa
parent 1 25a17d01db0c
child 5 f345bda72bc4
--- a/Symbian3/PDK/Source/GUID-5BDE6462-E6CA-5738-A587-C7D875574789.dita	Thu Mar 11 15:24:26 2010 +0000
+++ b/Symbian3/PDK/Source/GUID-5BDE6462-E6CA-5738-A587-C7D875574789.dita	Thu Mar 11 18:02:22 2010 +0000
@@ -1,252 +1,252 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
-<!-- This component and the accompanying materials are made available under the terms of the License 
-"Eclipse Public License v1.0" which accompanies this distribution, 
-and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
-<!-- Initial Contributors:
-    Nokia Corporation - initial contribution.
-Contributors: 
--->
-<!DOCTYPE concept
-  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
-<concept id="GUID-5BDE6462-E6CA-5738-A587-C7D875574789" xml:lang="en"><title>Static
-Data</title><prolog><metadata><keywords/></metadata></prolog><conbody>
-<p>Symbian developers used to PC operating systems, such as Windows, may be
-used to using writeable static data (typically meaning global variables) in
-DLLs. On the Symbian platform, this is possible, but not recommended, because
-it is expensive in memory, and has limited support in the Symbian platform
-Emulator. </p>
-<p>This page describes writeable static data (WSD), the alternatives to using
-WSD, and the costs and issues associated with its use. </p>
-<section><title>Global writeable static data</title> <p>Global writeable static
-data (WSD) is any per-process variable which exists for the lifetime of the
-process. In practice, this means any globally scoped data: data that is declared
-outside of a function, struct, or class, and function scoped static variables. </p> <codeblock id="GUID-C7F90E06-286B-5E64-B94A-7683AA0DA0FB" xml:space="preserve">TBufC&lt;20&gt; fileName; //WSD 
-void SetFileName()
- {
- static Tint iCount; //WSD ...
- }</codeblock> <p>Sometimes writeable static data appears in a non-obvious
-way. It is not always the case that <codeph>const</codeph> global variables
-are read-only data rather than global writeable static data. This is true
-for <codeph>const</codeph> objects with trivial constructors, such as integers.
-However if a <codeph>const</codeph> class has a non-trivial constructor, the <codeph>const</codeph> object
-will require a real variable and must be stored as WSD. For example: </p> <codeblock id="GUID-897D2E68-5AF6-5C69-A5AA-276A9FB89DEC" xml:space="preserve">const TInt myVariable=…; //OK – truly const
-const TPtrC KSomeConstPtr=...; //NOT OK – non trivial constructor 
-const TRgb KSomeConstCol=...; //NOT OK – non trivial constructor</codeblock> </section>
-<section><title>Support for global writeable static data on Symbian</title> <p>The
-Symbian platform supports global writeable static data in EXEs on all versions
-and handsets. </p> <p>Versions of Symbian OS based on the EKA2 kernel (8.1b
-and later) support WSD in DLLs on target hardware. Versions 8.1a and earlier,
-based on the EKA1 kernel, do not support global WSD in DLLs. </p> </section>
-<section><title>Clean up of global writeable static data</title> <p>Your program
-must make sure that global writeable static data that the program allocates
-is cleaned up. </p> <p>The clean up rules are as follows: </p> <ul>
-<li id="GUID-1D25BA8E-1A8E-5502-8FD9-7F74DBB39EF4"><p>Your program must clean
-up WSD objects that are defined in the process EXE or its statically-loaded
-DLLs. When a process exits, the Symbian platform does not automatically call
-the destructors of these WSD objects. </p> </li>
-<li id="GUID-7F1EB6D6-2EAD-5318-A066-DC9128A48EAF"><p>Your program does not
-need to clean up WSD objects defined in DLLs that the process has dynamically
-loaded using <xref href="GUID-25327159-83D6-3507-B187-09EA4BB3727F.dita"><apiname>RLibrary</apiname></xref>. The Symbian platform automatically
-calls destructors of these objects. </p> </li>
-</ul> </section>
-<section><title>Alternatives to using global writeable static data</title> <p>Native
-Symbian platform C++ code rarely uses WSD. </p> <p>However, code ported from
-other operating systems may contain large amounts of static data. For example,
-code written in the C programming language often makes use of WSD as the "glue"
-between C function calls. </p> <p>In EKA1, WSD is not supported, so there
-is no choice but to use the alternative mechanisms provided by the Symbian
-platform to port such code. Even in EKA2 where global data is supported, Symbian
-recommends that it only be used as a last resort. </p> <p>The following sections
-describe the alternatives that can be used to port code that makes use of
-global writeable static data. </p> <p><b>Use
-thread-local storage (TLS)</b> </p> <p>Thread Local Storage (TLS) is a single
-per-thread word that can be used to simulate global writeable static data. </p> <p>All
-the static data in the DLL is grouped into a single struct or class. On creation
-of the thread, an instance of the thread is allocated on the heap and a pointer
-to this data is saved to TLS (using <codeph>Dll::SetTls()</codeph>). On destruction
-of the thread, the data is destroyed. Throughout the DLL the code references
-the TLS data (using <codeph>Dll::Tls()</codeph>) rather than the original
-global writeable static data. </p> <p><b>Wrap
-in a server</b> </p> <p>The Symbian platform supports writeable global static
-data in EXEs. A common porting strategy is therefore to wrap the code in a
-Symbian server (which is an EXE), and expose its API as a client interface. </p> <p><b>Move global variables into your classes</b> </p> <p>With relatively small
-amounts of code, it may be possible to move most global data inside classes. </p> </section>
-<section><title>Enabling global writeable static data</title> <p>In order
-to enable global writeable static data, simply add a statement <codeph>epocallowdlldata</codeph> (case
-insensitive) to the project's MMP file: </p> <codeblock id="GUID-0E673C33-569E-5F7B-9E51-55C2FC233D70" xml:space="preserve">TARGET my.dll 
-TARGETTYPE dll 
-EPOCALLOWDLLDATA 
-… </codeblock> </section>
-<section><title>Costs and limitations</title> <p><b>Emulator
-only allows a DLL with WSD to load into a single process</b> </p> <p>The Symbian
-platform EKA2 Emulator only allows a DLL with WSD to be loaded into a single
-process. </p> <p>This is a very serious restriction. If you have a shared
-DLL with WSD, then the second process that attempts to load it in the emulator
-will fail with <codeph>KErrNotSupported</codeph>. </p> <p><b>Emulator allows WSD by default</b> </p> <p>The Emulator will allow WSD
-in DLLs even if <codeph>epocallowdlldata</codeph> is not declared in the mmp
-file. However the data will be truly global: there will be one copy for the
-entire emulator, rather than one copy for each emulated process. The only
-restriction is that if the data's initialisers call any Symbian platform kernel
-functions (i.e. executive calls), then the emulator will fault. </p> <p><b>RAM usage for WSD data chunk </b> </p> <p>When a process loads its first
-DLL containing WSD, it creates a single chunk to store the data. The data
-for subsequent WSD-enabled DLLs is loaded into the same chunk. </p> <p>The
-data chunk will occupy at least one 4K RAM page (the smallest possible RAM
-allocation), irrespective of how much static data is required. Any memory
-not used for WSD will be wasted. Since the memory is per-process, the memory
-wastage on the machine is: </p> <codeblock id="GUID-005105EF-A09A-5FF7-8056-7316AFCE1894" xml:space="preserve">(4Kb - WSD Bytes) × number-client-processes</codeblock> <p>It is very easy for a developer to add a few words of WSD to their DLL thinking
-that's all the memory that they are using. However, the cost is actually 4K
-for every process if a DLL with WSD has not already been loaded into the process.
-If for example the DLL is used by 4 processes, that's potentially an "invisible"
-cost of 16K. </p> <p><b>Chunks
-are a finite resource</b> </p> <p>EKA2 has a hard coded limit of 16 chunks
-per process; a limit that is required to ensure real-time behaviour. Every
-process loading WSD-enabled DLLs uses a chunk to hold the data, reducing the
-number of chunks available for other uses. </p> <p><b>ARM architecture 4 and 5 specific costs and limitations</b> </p> <p>There
-are other significant costs that apply only to DLLs that link against "fixed
-processes". Fixed processes are a feature of ARM v4 or v5 architecture only;
-the following behaviour does not apply to devices based on the ARMv6 architecture. </p> <p> <b>Case
-1: Non Execute-in-place DLLs</b>  </p> <p>For non-execute-in-place (non XIP)
-DLLs, an additional code chunk is required for every fixed process which links
-against the DLL. </p> <p>So imagine a 20Kb DLL (with a few bytes of WSD) that
-is loaded into 4 normal "non-fixed" processes, and 2 fixed processes. The
-(static) memory consumed is: </p> <ul>
-<li id="GUID-57F9041D-240C-5B75-BC0C-EFA66AB411B6"><p>Code chunk shared by
-all moving processes = 20 Kb </p> </li>
-<li id="GUID-1FCC1ED4-0A60-5983-AF5A-2F7C8622BC80"><p>Code chunk for each
-fixed process loading the DLL = 40 Kb </p> </li>
-<li id="GUID-6CD0DBDD-E406-5F7D-9207-8E55B4043779"><p>Data chunk for each
-process loading the DLL = 6×4Kb = 24 Kb </p> </li>
-</ul> <p>So to allow a few bytes of WSD there is a 64Kb increase in consumed
-memory. Note that the 20Kb code chunk shared by all processes is consumed
-whether or not WSD is enabled. </p> <p> <b>Case 2: Execute-in-place DLLs</b>  </p> <p>For
-XIP DLLs, there is no additional RAM cost other than the size of the WSD itself,
-rounded up to the next multiple of 4KB. However: </p> <ul>
-<li id="GUID-8B1EDEA4-8082-5DB1-87A8-E7B0FE5BB802"><p>An XIP DLL can be loaded
-by any non-fixed process, OR it may be loaded by a single fixed process (and
-therefore cannot be loaded by any other processes whatsoever) </p> </li>
-<li id="GUID-BA2D82B1-A036-5281-95EB-A46A7976605B"><p>The ROM build fails
-if a DLL with static data links to a fixed process <i>and</i> any other process. </p> </li>
-</ul> <p> <b>A few specific DLLs cannot have WSD</b>  </p> <p>DLLs that are
-required to initialise the file server cannot have WSD, e.g. HAL.DLL, EUSER.DLL,
-EFSRV.DLL. </p> </section>
-<section><title>Frequently asked questions</title> <p><b>How
-does Symbian's WSD implementation work ?</b> </p> <p> <b>Case 1. For moving
-processes:</b>  </p> <p>The Symbian platform supports a moving memory model,
-in which the data for a process is moved into a fixed virtual address space
-(the "run section") when the process is active, and then back into the processes
-"home" section when another process is active: </p> <ul>
-<li id="GUID-26E98921-9094-5260-BA99-2F7FA4F7D6A7"><p>The data of processes
-in the "home section" is uniquely addressed both in terms of physical RAM
-pages, and in the MMU virtual address space. The data is protected from other
-processes, except for the Kernel. </p> </li>
-<li id="GUID-BBE7C17A-6FF7-5329-91C5-DEAF88A61B69"><p>The data of processes
-in the run section occupies the same virtual address space as all other processes
-when they run (the MMU moves the physical RAM pages into the appropriate virtual
-address space). </p> </li>
-</ul> <p>When a DLL with WSD is loaded (or at ROM build time), its code is
-fixed to point to static data at specific addresses. In order to ensure that
-only a single copy of the DLL code is required, Symbian's moving-process WSD
-implementation ensures that the virtual addresses of static data is the same
-across every running process. </p> <p>The way this works is: </p> <ol id="GUID-66A040C2-7B0F-56E0-A634-501D3E133A12">
-<li id="GUID-964A78E1-D86E-50D0-8AA0-D3D9346A43E7"><p>A specific address space
-is reserved for a per-process static data chunk. This chunk is used to hold
-all the static data for all the DLLs loaded into the process. </p> </li>
-<li id="GUID-0A528F28-55B2-5B8B-A337-8B2377241CF0"><p>At ROM build time the
-kernel reserves specific addresses within the static data chunk for all the
-WSD in all the ROM loaded DLLs. The addresses for ROM based DLLs are reserved
-from the top of the static data chunk address space to the bottom. Note that
-static data addresses for RAM based DLLs are reserved when the DLL is first
-loaded into any process. In this case, addresses are reserved from the bottom
-of the static data chunk address space. </p> </li>
-<li id="GUID-1898478C-2E24-53B4-BDEB-765FEEDC539C"><p>When the first DLL with
-WSD is loaded into a process, a static data chunk is created to hold the static
-data for all DLLs that are loaded into the process. </p> </li>
-<li id="GUID-7A88C9EB-31F9-559E-8DBD-221848CA2A46"><p>Any global static data
-in the DLL is written to its specific reserved addresses. Note that addresses
-are reserved for that particular static data across all processes; if the
-DLL is loaded into another process, any static data will get the same virtual
-address. </p> </li>
-</ol> <p> <b>Case 2. For fixed processes:</b>  </p> <p>A fixed process is
-one in which the process data does not move; code is run on process data stored
-in the process "home section". </p> <p>Since the static data for every fixed
-process is uniquely addressed, and a DLL can only point to a single address
-for its data, the implication is that a separate copy of the DLL code is required
-for every fixed process that loads the DLL. </p> <p>The restrictions listed
-above for ARM architecture 4 and 5 directly result. </p> <ul>
-<li id="GUID-125EDB37-4540-5EDB-9C19-6F92A307627F"><p>For XIP based devices
-the DLL code chunk address is fixed at ROM build time, and there can only
-be one copy of the DLL code. Therefore the DLL code can address the data in
-either a single fixed process or the virtual address used by all moveable
-addresses. </p> </li>
-<li id="GUID-BC66EA5A-252D-5E37-80F6-BEC82C03DABA"><p>For non-XIP based devices
-the DLL is run from RAM, and the loader is able to fix-up the address that
-a DLL expects its data at load time (rather than ROM build time). Therefore
-in this case the loader creates a separate copy of DLL code for each fixed
-process that loads the DLL and a single copy shared by all moving processes. </p> </li>
-</ul> <p>Notes: Fixed processes are not supported or required on ARM v6 architectures.
-This discussion only applies to devices based on ARMv4 or v5. On ARM architecture
-6 each DLL with WSD has a reserved address, similar to the ARMv5 moving process
-case. However there is no 'home section' and memory is not relocated between
-low and high addresses on a context switch. Instead, each process uses its
-own set of page tables for the bottom half of virtual address space. </p> <p><b>Why does the EKA2 Emulator only allow a DLL with WSD to load into a single
-process?</b> </p> <p>The Symbian platform permits a DLL with global data to
-be loaded into only one Symbian platform process on the emulator. This limitation
-is a result of the way the Emulator is implemented on top of the Windows process
-model. </p> <p>On EKA2, separate Symbian platform processes are emulated within
-a single Windows process. To preserve Symbian platform semantics there should
-be one copy of the global data for each emulated process. However, this is
-not possible since a DLL on the emulator is just a Windows DLL; Windows gives
-it a single copy of any global data it needs when it is loaded. </p> <p><b>What happens if epocallowdlldata isn't declared for a DLL with WSD?</b> </p> <p> <b>Case
-1: On the EKA2 Emulator:</b>  </p> <p>Most constant data should be treated
-by the compiler as read-only rather than writeable static data (the exception
-is when the const data has a non-trivial constructor, so a real variable is
-required during initialisation). </p> <p>Unfortunately, different compilers
-sometimes treat const data as WSD. For example, CodeWarrior puts it in writeable
-data and initialises it at run time. MSVC generally puts it into read-only
-data, but occasionally puts it into writeable data. </p> <p>As most DLLs have
-const data, this means that the compilers have "accidentally" created WSD
-in almost every DLL. Symbian cannot therefore rigorously enforce the "single
-process can load a DLL with WSD" rule, as the Emulator would not work. </p> <p>On
-the EKA2 Emulator, the workaround Symbian have implemented is to recognise
-two types of DLL global data: </p> <ul>
-<li id="GUID-6AD2E89F-6361-5F1F-8EC1-A203801BCC8F"><p>'Deliberate' global
-data is where the programmer specifies that they want DLL global data (using
-the <codeph>epocallowdlldata</codeph> keyword in the MMP file. In this case
-any global data in the DLL is assumed to be deliberate, and the "DLL loaded
-into one-emulated-process" rule applies. </p> </li>
-<li id="GUID-225E44BE-434E-5C2A-8503-318E31B17EF0"><p>'Accidental' global
-data is the data introduced by the compiler with no encouragement from the
-programmer. If <codeph>epocallowdlldata</codeph> is absent, global data is
-assumed to be accidental and the rule does not apply. Note that the global
-data includes both const and non-const static data; there is no way to tell
-the compilers to only apply it to non-const data - if we could do that then
-we could force correct handling of const static data. </p> </li>
-</ul> <p>In order to prevent abuse of this workaround, there are restrictions
-on what can be done with accidental global data; specifically, the Emulator
-will fault if any of the global data's initialisers attempt to call the Symbian
-platform kernel functions (i.e. executive calls). </p> <p>Note that there
-is only one copy of the global data. Therefore it is possible for two processes
-to write to the same 'accidental' global data (causing undefined behaviour).
-The "DLL loaded into one-emulated-process" rule prevents this being a problem
-for deliberate global data. </p> <p> <b>Case 2: On the EKA1 Emulator</b>  </p> <p>The
-EKA1 emulator has no concept of separate Symbian platform processes. Global
-data is allowed on the Emulator as there is only one copy of any global data. </p> <p>Symbian
-developers often have problems when porting to real hardware, which does not
-support this type of data. This is discussed in the following section. </p> <p> <b>Case
-3: On native target builds</b>  </p> <p>On either EKA1 or EKA2, target compilers
-will fail the build with an error indicating that the code has initialised
-or un-initialised data. </p> <p>The error message does not specify the symbol(s)
-that are causing the problem. The <filepath>.map</filepath> files output by
-the linker can however be helpful in finding the problem symbol. The RVCT
-map files provide a list of global symbols and the object files in which they
-occur. FAQ-0329 on the <xref href="http://developer.symbian.org/wiki/index.php/Symbian_C++_Knowledgebase_Q&amp;As#How_can_I_find_the_.22uninitialised_data.22_in_my_DLL.3F" scope="external">DevNet knowledgebase</xref> works through an example of using
-a map file using the GCC compiler used on older Symbian platform releases. </p> <p><b>Can Kernel DLLs have WSD ?</b> </p> <p>Yes, WSD is supported for kernel
-DLLs in both EKA1 and EKA2 (through alternative mechanisms to those described
-here). </p> <p>Of course, kernel DLLs are guaranteed to be loaded into only
-one process, so the per-process multiplication of RAM usage does not apply.
-EKA2 will work correctly with global data in any kernel DLL. However EKA1
-does not call constructors for global C++ objects in kernel extensions or
-device drivers, and does not call destructors for global C++ objects in device
-drivers at driver unload time. </p> </section>
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-5BDE6462-E6CA-5738-A587-C7D875574789" xml:lang="en"><title>Static
+Data</title><prolog><metadata><keywords/></metadata></prolog><conbody>
+<p>Symbian developers used to PC operating systems, such as Windows, may be
+used to using writeable static data (typically meaning global variables) in
+DLLs. On the Symbian platform, this is possible, but not recommended, because
+it is expensive in memory, and has limited support in the Symbian platform
+Emulator. </p>
+<p>This page describes writeable static data (WSD), the alternatives to using
+WSD, and the costs and issues associated with its use. </p>
+<section><title>Global writeable static data</title> <p>Global writeable static
+data (WSD) is any per-process variable which exists for the lifetime of the
+process. In practice, this means any globally scoped data: data that is declared
+outside of a function, struct, or class, and function scoped static variables. </p> <codeblock id="GUID-C7F90E06-286B-5E64-B94A-7683AA0DA0FB" xml:space="preserve">TBufC&lt;20&gt; fileName; //WSD 
+void SetFileName()
+ {
+ static Tint iCount; //WSD ...
+ }</codeblock> <p>Sometimes writeable static data appears in a non-obvious
+way. It is not always the case that <codeph>const</codeph> global variables
+are read-only data rather than global writeable static data. This is true
+for <codeph>const</codeph> objects with trivial constructors, such as integers.
+However if a <codeph>const</codeph> class has a non-trivial constructor, the <codeph>const</codeph> object
+will require a real variable and must be stored as WSD. For example: </p> <codeblock id="GUID-897D2E68-5AF6-5C69-A5AA-276A9FB89DEC" xml:space="preserve">const TInt myVariable=…; //OK – truly const
+const TPtrC KSomeConstPtr=...; //NOT OK – non trivial constructor 
+const TRgb KSomeConstCol=...; //NOT OK – non trivial constructor</codeblock> </section>
+<section><title>Support for global writeable static data on Symbian</title> <p>The
+Symbian platform supports global writeable static data in EXEs on all versions
+and handsets. </p> <p>Versions of Symbian OS based on the EKA2 kernel (8.1b
+and later) support WSD in DLLs on target hardware. Versions 8.1a and earlier,
+based on the EKA1 kernel, do not support global WSD in DLLs. </p> </section>
+<section><title>Clean up of global writeable static data</title> <p>Your program
+must make sure that global writeable static data that the program allocates
+is cleaned up. </p> <p>The clean up rules are as follows: </p> <ul>
+<li id="GUID-1D25BA8E-1A8E-5502-8FD9-7F74DBB39EF4"><p>Your program must clean
+up WSD objects that are defined in the process EXE or its statically-loaded
+DLLs. When a process exits, the Symbian platform does not automatically call
+the destructors of these WSD objects. </p> </li>
+<li id="GUID-7F1EB6D6-2EAD-5318-A066-DC9128A48EAF"><p>Your program does not
+need to clean up WSD objects defined in DLLs that the process has dynamically
+loaded using <xref href="GUID-25327159-83D6-3507-B187-09EA4BB3727F.dita"><apiname>RLibrary</apiname></xref>. The Symbian platform automatically
+calls destructors of these objects. </p> </li>
+</ul> </section>
+<section><title>Alternatives to using global writeable static data</title> <p>Native
+Symbian platform C++ code rarely uses WSD. </p> <p>However, code ported from
+other operating systems may contain large amounts of static data. For example,
+code written in the C programming language often makes use of WSD as the "glue"
+between C function calls. </p> <p>In EKA1, WSD is not supported, so there
+is no choice but to use the alternative mechanisms provided by the Symbian
+platform to port such code. Even in EKA2 where global data is supported, Symbian
+recommends that it only be used as a last resort. </p> <p>The following sections
+describe the alternatives that can be used to port code that makes use of
+global writeable static data. </p> <p><b>Use
+thread-local storage (TLS)</b> </p> <p>Thread Local Storage (TLS) is a single
+per-thread word that can be used to simulate global writeable static data. </p> <p>All
+the static data in the DLL is grouped into a single struct or class. On creation
+of the thread, an instance of the thread is allocated on the heap and a pointer
+to this data is saved to TLS (using <codeph>Dll::SetTls()</codeph>). On destruction
+of the thread, the data is destroyed. Throughout the DLL the code references
+the TLS data (using <codeph>Dll::Tls()</codeph>) rather than the original
+global writeable static data. </p> <p><b>Wrap
+in a server</b> </p> <p>The Symbian platform supports writeable global static
+data in EXEs. A common porting strategy is therefore to wrap the code in a
+Symbian server (which is an EXE), and expose its API as a client interface. </p> <p><b>Move global variables into your classes</b> </p> <p>With relatively small
+amounts of code, it may be possible to move most global data inside classes. </p> </section>
+<section><title>Enabling global writeable static data</title> <p>In order
+to enable global writeable static data, simply add a statement <codeph>epocallowdlldata</codeph> (case
+insensitive) to the project's MMP file: </p> <codeblock id="GUID-0E673C33-569E-5F7B-9E51-55C2FC233D70" xml:space="preserve">TARGET my.dll 
+TARGETTYPE dll 
+EPOCALLOWDLLDATA 
+… </codeblock> </section>
+<section><title>Costs and limitations</title> <p><b>Emulator
+only allows a DLL with WSD to load into a single process</b> </p> <p>The Symbian
+platform EKA2 Emulator only allows a DLL with WSD to be loaded into a single
+process. </p> <p>This is a very serious restriction. If you have a shared
+DLL with WSD, then the second process that attempts to load it in the emulator
+will fail with <codeph>KErrNotSupported</codeph>. </p> <p><b>Emulator allows WSD by default</b> </p> <p>The Emulator will allow WSD
+in DLLs even if <codeph>epocallowdlldata</codeph> is not declared in the mmp
+file. However the data will be truly global: there will be one copy for the
+entire emulator, rather than one copy for each emulated process. The only
+restriction is that if the data's initialisers call any Symbian platform kernel
+functions (i.e. executive calls), then the emulator will fault. </p> <p><b>RAM usage for WSD data chunk </b> </p> <p>When a process loads its first
+DLL containing WSD, it creates a single chunk to store the data. The data
+for subsequent WSD-enabled DLLs is loaded into the same chunk. </p> <p>The
+data chunk will occupy at least one 4K RAM page (the smallest possible RAM
+allocation), irrespective of how much static data is required. Any memory
+not used for WSD will be wasted. Since the memory is per-process, the memory
+wastage on the machine is: </p> <codeblock id="GUID-005105EF-A09A-5FF7-8056-7316AFCE1894" xml:space="preserve">(4Kb - WSD Bytes) × number-client-processes</codeblock> <p>It is very easy for a developer to add a few words of WSD to their DLL thinking
+that's all the memory that they are using. However, the cost is actually 4K
+for every process if a DLL with WSD has not already been loaded into the process.
+If for example the DLL is used by 4 processes, that's potentially an "invisible"
+cost of 16K. </p> <p><b>Chunks
+are a finite resource</b> </p> <p>EKA2 has a hard coded limit of 16 chunks
+per process; a limit that is required to ensure real-time behaviour. Every
+process loading WSD-enabled DLLs uses a chunk to hold the data, reducing the
+number of chunks available for other uses. </p> <p><b>ARM architecture 4 and 5 specific costs and limitations</b> </p> <p>There
+are other significant costs that apply only to DLLs that link against "fixed
+processes". Fixed processes are a feature of ARM v4 or v5 architecture only;
+the following behaviour does not apply to devices based on the ARMv6 architecture. </p> <p> <b>Case
+1: Non Execute-in-place DLLs</b>  </p> <p>For non-execute-in-place (non XIP)
+DLLs, an additional code chunk is required for every fixed process which links
+against the DLL. </p> <p>So imagine a 20Kb DLL (with a few bytes of WSD) that
+is loaded into 4 normal "non-fixed" processes, and 2 fixed processes. The
+(static) memory consumed is: </p> <ul>
+<li id="GUID-57F9041D-240C-5B75-BC0C-EFA66AB411B6"><p>Code chunk shared by
+all moving processes = 20 Kb </p> </li>
+<li id="GUID-1FCC1ED4-0A60-5983-AF5A-2F7C8622BC80"><p>Code chunk for each
+fixed process loading the DLL = 40 Kb </p> </li>
+<li id="GUID-6CD0DBDD-E406-5F7D-9207-8E55B4043779"><p>Data chunk for each
+process loading the DLL = 6×4Kb = 24 Kb </p> </li>
+</ul> <p>So to allow a few bytes of WSD there is a 64Kb increase in consumed
+memory. Note that the 20Kb code chunk shared by all processes is consumed
+whether or not WSD is enabled. </p> <p> <b>Case 2: Execute-in-place DLLs</b>  </p> <p>For
+XIP DLLs, there is no additional RAM cost other than the size of the WSD itself,
+rounded up to the next multiple of 4KB. However: </p> <ul>
+<li id="GUID-8B1EDEA4-8082-5DB1-87A8-E7B0FE5BB802"><p>An XIP DLL can be loaded
+by any non-fixed process, OR it may be loaded by a single fixed process (and
+therefore cannot be loaded by any other processes whatsoever) </p> </li>
+<li id="GUID-BA2D82B1-A036-5281-95EB-A46A7976605B"><p>The ROM build fails
+if a DLL with static data links to a fixed process <i>and</i> any other process. </p> </li>
+</ul> <p> <b>A few specific DLLs cannot have WSD</b>  </p> <p>DLLs that are
+required to initialise the file server cannot have WSD, e.g. HAL.DLL, EUSER.DLL,
+EFSRV.DLL. </p> </section>
+<section><title>Frequently asked questions</title> <p><b>How
+does Symbian's WSD implementation work ?</b> </p> <p> <b>Case 1. For moving
+processes:</b>  </p> <p>The Symbian platform supports a moving memory model,
+in which the data for a process is moved into a fixed virtual address space
+(the "run section") when the process is active, and then back into the processes
+"home" section when another process is active: </p> <ul>
+<li id="GUID-26E98921-9094-5260-BA99-2F7FA4F7D6A7"><p>The data of processes
+in the "home section" is uniquely addressed both in terms of physical RAM
+pages, and in the MMU virtual address space. The data is protected from other
+processes, except for the Kernel. </p> </li>
+<li id="GUID-BBE7C17A-6FF7-5329-91C5-DEAF88A61B69"><p>The data of processes
+in the run section occupies the same virtual address space as all other processes
+when they run (the MMU moves the physical RAM pages into the appropriate virtual
+address space). </p> </li>
+</ul> <p>When a DLL with WSD is loaded (or at ROM build time), its code is
+fixed to point to static data at specific addresses. In order to ensure that
+only a single copy of the DLL code is required, Symbian's moving-process WSD
+implementation ensures that the virtual addresses of static data is the same
+across every running process. </p> <p>The way this works is: </p> <ol id="GUID-66A040C2-7B0F-56E0-A634-501D3E133A12">
+<li id="GUID-964A78E1-D86E-50D0-8AA0-D3D9346A43E7"><p>A specific address space
+is reserved for a per-process static data chunk. This chunk is used to hold
+all the static data for all the DLLs loaded into the process. </p> </li>
+<li id="GUID-0A528F28-55B2-5B8B-A337-8B2377241CF0"><p>At ROM build time the
+kernel reserves specific addresses within the static data chunk for all the
+WSD in all the ROM loaded DLLs. The addresses for ROM based DLLs are reserved
+from the top of the static data chunk address space to the bottom. Note that
+static data addresses for RAM based DLLs are reserved when the DLL is first
+loaded into any process. In this case, addresses are reserved from the bottom
+of the static data chunk address space. </p> </li>
+<li id="GUID-1898478C-2E24-53B4-BDEB-765FEEDC539C"><p>When the first DLL with
+WSD is loaded into a process, a static data chunk is created to hold the static
+data for all DLLs that are loaded into the process. </p> </li>
+<li id="GUID-7A88C9EB-31F9-559E-8DBD-221848CA2A46"><p>Any global static data
+in the DLL is written to its specific reserved addresses. Note that addresses
+are reserved for that particular static data across all processes; if the
+DLL is loaded into another process, any static data will get the same virtual
+address. </p> </li>
+</ol> <p> <b>Case 2. For fixed processes:</b>  </p> <p>A fixed process is
+one in which the process data does not move; code is run on process data stored
+in the process "home section". </p> <p>Since the static data for every fixed
+process is uniquely addressed, and a DLL can only point to a single address
+for its data, the implication is that a separate copy of the DLL code is required
+for every fixed process that loads the DLL. </p> <p>The restrictions listed
+above for ARM architecture 4 and 5 directly result. </p> <ul>
+<li id="GUID-125EDB37-4540-5EDB-9C19-6F92A307627F"><p>For XIP based devices
+the DLL code chunk address is fixed at ROM build time, and there can only
+be one copy of the DLL code. Therefore the DLL code can address the data in
+either a single fixed process or the virtual address used by all moveable
+addresses. </p> </li>
+<li id="GUID-BC66EA5A-252D-5E37-80F6-BEC82C03DABA"><p>For non-XIP based devices
+the DLL is run from RAM, and the loader is able to fix-up the address that
+a DLL expects its data at load time (rather than ROM build time). Therefore
+in this case the loader creates a separate copy of DLL code for each fixed
+process that loads the DLL and a single copy shared by all moving processes. </p> </li>
+</ul> <p>Notes: Fixed processes are not supported or required on ARM v6 architectures.
+This discussion only applies to devices based on ARMv4 or v5. On ARM architecture
+6 each DLL with WSD has a reserved address, similar to the ARMv5 moving process
+case. However there is no 'home section' and memory is not relocated between
+low and high addresses on a context switch. Instead, each process uses its
+own set of page tables for the bottom half of virtual address space. </p> <p><b>Why does the EKA2 Emulator only allow a DLL with WSD to load into a single
+process?</b> </p> <p>The Symbian platform permits a DLL with global data to
+be loaded into only one Symbian platform process on the emulator. This limitation
+is a result of the way the Emulator is implemented on top of the Windows process
+model. </p> <p>On EKA2, separate Symbian platform processes are emulated within
+a single Windows process. To preserve Symbian platform semantics there should
+be one copy of the global data for each emulated process. However, this is
+not possible since a DLL on the emulator is just a Windows DLL; Windows gives
+it a single copy of any global data it needs when it is loaded. </p> <p><b>What happens if epocallowdlldata isn't declared for a DLL with WSD?</b> </p> <p> <b>Case
+1: On the EKA2 Emulator:</b>  </p> <p>Most constant data should be treated
+by the compiler as read-only rather than writeable static data (the exception
+is when the const data has a non-trivial constructor, so a real variable is
+required during initialisation). </p> <p>Unfortunately, different compilers
+sometimes treat const data as WSD. For example, CodeWarrior puts it in writeable
+data and initialises it at run time. MSVC generally puts it into read-only
+data, but occasionally puts it into writeable data. </p> <p>As most DLLs have
+const data, this means that the compilers have "accidentally" created WSD
+in almost every DLL. Symbian cannot therefore rigorously enforce the "single
+process can load a DLL with WSD" rule, as the Emulator would not work. </p> <p>On
+the EKA2 Emulator, the workaround Symbian have implemented is to recognise
+two types of DLL global data: </p> <ul>
+<li id="GUID-6AD2E89F-6361-5F1F-8EC1-A203801BCC8F"><p>'Deliberate' global
+data is where the programmer specifies that they want DLL global data (using
+the <codeph>epocallowdlldata</codeph> keyword in the MMP file. In this case
+any global data in the DLL is assumed to be deliberate, and the "DLL loaded
+into one-emulated-process" rule applies. </p> </li>
+<li id="GUID-225E44BE-434E-5C2A-8503-318E31B17EF0"><p>'Accidental' global
+data is the data introduced by the compiler with no encouragement from the
+programmer. If <codeph>epocallowdlldata</codeph> is absent, global data is
+assumed to be accidental and the rule does not apply. Note that the global
+data includes both const and non-const static data; there is no way to tell
+the compilers to only apply it to non-const data - if we could do that then
+we could force correct handling of const static data. </p> </li>
+</ul> <p>In order to prevent abuse of this workaround, there are restrictions
+on what can be done with accidental global data; specifically, the Emulator
+will fault if any of the global data's initialisers attempt to call the Symbian
+platform kernel functions (i.e. executive calls). </p> <p>Note that there
+is only one copy of the global data. Therefore it is possible for two processes
+to write to the same 'accidental' global data (causing undefined behaviour).
+The "DLL loaded into one-emulated-process" rule prevents this being a problem
+for deliberate global data. </p> <p> <b>Case 2: On the EKA1 Emulator</b>  </p> <p>The
+EKA1 emulator has no concept of separate Symbian platform processes. Global
+data is allowed on the Emulator as there is only one copy of any global data. </p> <p>Symbian
+developers often have problems when porting to real hardware, which does not
+support this type of data. This is discussed in the following section. </p> <p> <b>Case
+3: On native target builds</b>  </p> <p>On either EKA1 or EKA2, target compilers
+will fail the build with an error indicating that the code has initialised
+or un-initialised data. </p> <p>The error message does not specify the symbol(s)
+that are causing the problem. The <filepath>.map</filepath> files output by
+the linker can however be helpful in finding the problem symbol. The RVCT
+map files provide a list of global symbols and the object files in which they
+occur. FAQ-0329 on the <xref href="http://developer.symbian.org/wiki/index.php/Symbian_C++_Knowledgebase_Q&amp;As#How_can_I_find_the_.22uninitialised_data.22_in_my_DLL.3F" scope="external">DevNet knowledgebase</xref> works through an example of using
+a map file using the GCC compiler used on older Symbian platform releases. </p> <p><b>Can Kernel DLLs have WSD ?</b> </p> <p>Yes, WSD is supported for kernel
+DLLs in both EKA1 and EKA2 (through alternative mechanisms to those described
+here). </p> <p>Of course, kernel DLLs are guaranteed to be loaded into only
+one process, so the per-process multiplication of RAM usage does not apply.
+EKA2 will work correctly with global data in any kernel DLL. However EKA1
+does not call constructors for global C++ objects in kernel extensions or
+device drivers, and does not call destructors for global C++ objects in device
+drivers at driver unload time. </p> </section>
 </conbody></concept>
\ No newline at end of file