Symbian OS Support For Writeable Static Data in DLLs
Symbian OS Support For Writeable Static Data in DLLs
in DLLs
Hamish Willee
Published by the Symbian Developer Network
Version: 2.2 – November 2007
2 Introduction
The mapping between kernel, Symbian OS version, and support for global writeable static data is
summarised in the table below.
Kernel Symbian OS version DLL EXE
EKA1 Symbian OS v6.1, v7.0, v7.0s, v8.0a v8.1a No Yes
EKA2 Symbian OS v8.0b, v8.1b, v9.x Yes Yes
Note that kernel side DLLs may use writeable static data in all versions of Symbian OS, as
discussed in section 5.4.
4.1 EKA2 emulator only allows a DLL with WSD to load into a single
process
The Symbian OS EKA2 emulator only allows a DLL with WSD to be loaded into a single process.
The reasons for this limitation are discussed in section 5.2.
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 KErrNotSupported.
For reasons described in section 5.3.1, the emulator will allow WSD in DLLs even if
EPOCALLOWDLLDATA 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 OS kernel functions (i.e. executive calls)
the emulator will fault.
Symbian OS v9.4 introduces emulator-specific support for process-wide WSD through the “EWSD”
library. This support allows developers to load a DLL with WSD into multiple processes on the
emulator, at the cost of potentially significant additional development effort. A brief overview of the
EWSD support, and the costs, is provided in section 5.5.
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.
For an ISV application developer porting/writing DLLs with a single client process the
(approximately) 4Kb wasted memory may be justifiable.
For Device Creators, where much of the code written is shared DLLs, using WSD has
proportionally greater costs. The largest possible amount of wastage is 400Kb - calculated by
assuming that there are 100 processes running on the device, each loading a single DLL with 1
byte of WSD.
5.2 Why does the EKA2 emulator only allow a DLL with WSD to load into
a single process?
Symbian OS permits a DLL with global data to be loaded into only one Symbian OS process. This
limitation is a result of the way the emulator is implemented on top of the Windows process model.
On EKA2, separate Symbian OS processes are emulated within a single Windows process. To
preserve Symbian OS 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.
5.3 What happens if 'epocallowdlldata' isn’t declared for a DLL with WSD?
5.3.1 On the EKA2 emulator
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).
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.
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.
8
On the EKA2 emulator, the workaround Symbian has implemented is to recognise two types of
DLL global data:
• 'Deliberate' global data is where the programmer specifies that they want DLL global
data (using the epocallowdlldata 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.
• ‘Accidental’ global data is the data introduced by the compiler with no encouragement
from the programmer. If epocallowdlldata 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.
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 Symbian OS kernel functions (i.e. executive calls).
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.
The support is not transparent to the DLL writer; they have to wrap the WSD in a data structure
and pass it to the EWSD library. This library maintains the relationship between the library, and its
WSD values in each process.
The DLL writer has to make emulator-conditional changes to the source code to:
• wrap all the WSD in the DLL into a single “wrapper” data structure
• change code to refer to the wrapper data member rather than directly
• prevent EPOCALLOWDLLDATA being declared in the emulator build
For example, consider a DLL with a function foo() that uses WSD iState as shown:
// source for foo.cpp
int iState;
void foo()
{
if (iState == ESomeState)
{
//do something
}
else
{
//do something else
}
}
The MMP file of that DLL must not have EPOCALLOWDLLDATA for the emulator build, so you would
make its specification conditional on use of EWSD in the MMP file:
#ifndef _USE_EWSD_
EPOCALLOWDLLDATA
#endif
If the DLL has a lot of WSD then recoding as above may take significant effort. Note that this
recoding is not necessary if your DLL is only to be loaded into a single process, or if you only need
to test on target.
6 Summary
WSD in DLLs is not, and never will be, supported on EKA1 based versions of Symbian OS.
However WSD in DLLs is supported on EKA2.
Support for WSD in DLLs is provided primarily for ISVs porting code with WSD from other
operating systems, where the cost of using the other alternatives is prohibitive.
11
7 Further Information
7.1 References
7.2 Glossary
Term Definition
Execute in Execute in place. On an XIP “ROM” the ROM memory is mapped into the
place (XIP) process address space. Code is executed directly from the ROM. NOR flash is
XIP memory.
Non XIP ROM is not mapped into the process address space. Code is loaded
into RAM before being executed.
Chunk A collection of physical RAM pages mapped to contiguous virtual addresses. In
EKA2 a process may have only 8 chunks.
Want to be kept informed of new articles being made available on the Symbian Developer
Network?
Subscribe to the Symbian Community Newsletter.
The Symbian Community Newsletter brings you, every month, the latest news and resources for
Symbian OS.