Fundamentals of Symbian C++
System Structure
Part One
This work is licensed under the Creative Commons Attribution-Share Alike 2.0 UK: England & Wales License.
To view a copy of this license, visit http://creativecommons.org/licenses/bysa/2.0/uk/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California,
94105, USA.
System Structure
System Structure
This Lecture Examines
• DLLs
• Memory management
• Threads and processes
Fundamentals of Symbian C++ 2
System Structure
System Structure
A brief high-level overview of Symbian OS:
• It is a multi-tasking operating system based on open standards for
advanced mobile phones
The phones
• Have a sophisticated graphical user interface (GUI) and a number of built-
in applications which use it
- For example, messaging and calendar
Is said to be an “open” platform because, in addition to the
applications built in by the manufacturer
• A user may install others such as games, enterprise applications (for
example push e-mail) or utilities
Fundamentals of Symbian C++ 3
System Structure
System Structure
Symbian OS is licensed to the world’s leading handset
manufacturers
• Arima, BenQ, Fujitsu, Lenovo, LG Electronics, Motorola, Mitsubishi,
Nokia, Panasonic, Samsung, Sharp and Sony Ericsson
Symbian OS has a flexible architecture
• Allowing different user interfaces to run on top of the core operating
system
Symbian OS UIs include
• Nokia’s S60 and Series 80 platforms, NTT DoCoMo’s FOMA user
interface and UIQ
Fundamentals of Symbian C++ 4
System Structure
System Structure
EKA1 and EKA2
• Refer to different versions of the Symbian OS kernel
• The EKA stands for “EPOC Kernel Architecture”
(Symbian OS was previously known as “EPOC”, and earlier still “EPOC32”)
• EKA1 is the 32-bit kernel released originally in the Psion Series 5 in
1997
• EKA2 is discussed in the next slide
Fundamentals of Symbian C++ 5
System Structure
System Structure
EKA2
• Was first introduced in Symbian OS version 8.0b
• But first shipped in a phone product until version 8.1b
• Is found in the Japanese MOAP 2.0 FOMA 902i series
phones
• It is the second iteration of Symbian’s 32-bit kernel
• Very different internally to EKA1
• Offers hard real-time guarantees to kernel and user-mode
threads
Fundamentals of Symbian C++ 6
System Structure
DLLs in Symbian OS
• Know and understand the characteristics of polymorphic interface
and shared library (static) DLLs
• Know that UID2 values are used to distinguish between static and
polymorphic DLLs, and between plug-in types
• For a shared library, understand which functions must be exported
if other binary components are to be able to access them
• Know that Symbian OS does not allow library lookup by name but
only by ordinal
Fundamentals of Symbian C++ 7
System Structure
Shared Library and Polymorphic Interface DLLs
Dynamic link libraries
• DLLs are libraries of compiled C++
code
• That may be loaded into a running
process
• In the context of an existing thread
There are two main types of DLL
• Shared library (static-interface) DLLs
• Polymorphic interface (plug-in) DLLs
Fundamentals of Symbian C++ 8
System Structure
Shared Library DLLs
A shared library DLL
• Implements library code that may be used by other libraries
or EXEs
• The filename extension of a shared library is .dll
Examples of this type are
• The user library EUser.dll
• The file system library EFsrv.dll
A shared library
• Exports API functions according to a module definition
(.def) file
• It may have any number of exported functions
• Each is an entry point into the DLL
Fundamentals of Symbian C++ 9
System Structure
Shared Library DLLs
A shared library releases
• A header file (.h) for other components to compile against
• An import library (.lib) to link against in order to resolve the
exported functions
When executable code that uses the library runs
• The Symbian OS loader loads any shared library DLLs that it
links to, and any further DLLs the shared library DLLs require
• This is done recursively until all shared code needed by the
executable is loaded
Fundamentals of Symbian C++ 10
System Structure
Polymorphic Interface DLLs
A polymorphic interface DLL
• Implements an abstract interface which is defined separately
- For example by a framework
It may have a .dll filename extension
• But it often uses a different extension to identify the nature of
the DLL further
For example
• .fsy for a file system plug-in
• .prt for a protocol module plug-in
• File systems and Sockets are discussed later
Fundamentals of Symbian C++ 11
System Structure
Polymorphic Interface DLLs
Polymorphic Interface DLLs are used as plug-ins
They have a single entry-point “gate” or “factory” function
• Which instantiates the concrete class that implements the
interface
They are used
• To provide a range of different implementations (plug-ins) of
a single consistent interface
They are loaded dynamically
• Typically by a framework
Fundamentals of Symbian C++ 12
System Structure
ECOM Plug-ins
From Symbian OS v7.0 onward
• The most common type of plug-ins are ECOM plug-ins
ECOM is a generic framework for specifying interfaces
• And for finding and loading those plug-ins which implement
them
Many Symbian OS frameworks require their plug-ins to
be written as ECOM plug-ins
• Rather than as a “proprietary” type of framework which
loads polymorphic interface DLL plug-ins
• For example, the recognizer framework
Fundamentals of Symbian C++ 13
System Structure
ECOM Plug-ins
Using ECOM allows each framework to delegate the
finding and loading of suitable plug-ins to ECOM
• Rather than performing that task itself
Thus making easier to design and implement new services
or features
• ECOM provide a consistent design pattern
Fundamentals of Symbian C++ 14
System Structure
UIDs used by DLLs
UIDs are used to identify a file type
• For running executable code (including DLLs)
• And for associating data files with the appropriate
application
A UID is a 32-bit globally unique identifier value
Symbian OS uses a combination of up to three
UIDs to uniquely identify a binary executable
• The three UID values used by DLLs are as follows ...
Fundamentals of Symbian C++ 15
System Structure
UID1
UID1 is a system-level identifier
• Distinguishes between EXEs and DLLs
• This value is never stated explicitly
• It is determined by the Symbian build tools from the
targettype specified in the MMP file
For shared libraries
• The targettype specified should be DLL
• UID1 = KDynamicLibraryUid = 0x10000079
Fundamentals of Symbian C++ 16
System Structure
UID1 Continued
For polymorphic ECOM plug-in DLLs
• The targettype is PLUGIN
• Or ECOMIIC for versions of Symbian OS earlier than v9.0
Other polymorphic non-ECOM plug-in DLL target types
• FSY (file system plug-in)
• PRT (protocol module plug-ins).
• The targettype keyword and the build tools are discussed in
later lectures
Fundamentals of Symbian C++ 17
System Structure
UID2
UID2 distinguishes between shared library DLLs and
polymorphic interface DLLs
• Shared libraries are always KSharedLibraryUid
(0x1000008d)
Polymorphic interface DLLs have UID2 values specific to
their type
• For example the socket server protocol module UID2 value is
0x1000004A
Fundamentals of Symbian C++ 18
System Structure
UID3
UID3 is used to identify a component uniquely
Symbian manages UID allocation through a central
database
• Ensuring the UID is a genuinely unique value
Developers must be registered with Symbian Signed
to request UIDs
• More on Symbian Signed later
Fundamentals of Symbian C++ 19
System Structure
EXEs
The UID1 value is set by the targettype EXE
statement to
(KExecutableImageUid=0x1000007a)
UID2 is not relevant for an EXE
• It can be left unspecified
• Or set explicitly to KNullUid (=0)
UID3
• on Symbian OS v9 and beyond UID3 should
usually be set to a unique value to act as the
secure identifier for the binary
• Pre-Symbian OS v9 it can be left unspecified
Fundamentals of Symbian C++ 20
System Structure
Exporting Functions from a DLL
A shared library DLL provides access to its APIs by
exporting its functions
• Used by another DLL or by EXE code compiled into a separate
binary component
• Exporting makes the functions “public” to other modules by
creating a .lib file
• Libs contain the export table to be linked against by the calling
code
Fundamentals of Symbian C++ 21
System Structure
Exporting Functions from a DLL
Functions to be exported
• Should be marked in the class definition in the header file with the
macro IMPORT_C
The client code will include the header file
• effectively “importing” each function into their code module
• When they call it
The corresponding function implementation
• Should be prefixed with the EXPORT_C macro in the .cpp file which
implements it
Fundamentals of Symbian C++ 22
System Structure
Exporting Functions from a DLL
Use of IMPORT_C and EXPORT_C:
class CMyExample : public CSomeBase
{
public:
IMPORT_C static CMyExample* NewL();
public:
IMPORT_C void Foo();
...
};
EXPORT_C CMyExample* CMyExample::NewL()
{...}
EXPORT_C void CMyExample::Foo()
{...}
Fundamentals of Symbian C++ 23
System Structure
Exporting Functions from a DLL
The rules as to which functions should be exported are as
follows:
Inline functions must never be exported because there is no
need to do so
This is why:
• The IMPORT_C and EXPORT_C macros add functions to the export
table to make them accessible to components linking against the
library
• But the code of an inline function is already accessible to callers
because it is declared within the header file
• So the compiler interprets the inline directive by adding the code
directly into the client code wherever it calls it
• There is no need to export it
Fundamentals of Symbian C++ 24
System Structure
Exporting Functions from a DLL
Only functions that are to be used outside a DLL should be
exported by using of IMPORT_C and EXPORT_C
If the function is private to the class
• It can never be accessed by client code
Exporting it adds it to the export table in the module definition
file (.def)unnecessarily
Fundamentals of Symbian C++ 25
System Structure
Exporting Functions from a DLL
All virtual functions should be exported
• Whether public, protected or private
• Since they may be re-implemented by a derived class in another
code module
Any class which has virtual functions
• Must also export a constructor
• Even if it is empty
So that the virtual function table
• Can be correctly generated by access to the base-class constructor
Fundamentals of Symbian C++ 26
System Structure
Lookup by Ordinal and by Name
The size of DLL program code is optimized
• To save ROM and RAM space
In most operating systems to load a dynamic library the entry
points of a DLL can either be:
• Identified by string-matching their name - lookup by name
• Or by the order in which they are exported in the module definition file -
lookup by ordinal
Symbian OS does not offer lookup by name
• As it adds an overhead to the size of the DLL
• Storing the names of all the functions exported from the library is
wasteful of limited ROM and RAM space
Fundamentals of Symbian C++ 27
System Structure
Lookup by Ordinal and by Name
Symbian OS only uses link by ordinal
• This has significant implications for binary compatibility
• Ordinals must not be changed between one release of a DLL and
another
For example
• Code which links against a library and uses an exported function
with a specific ordinal number in an early version of the library
• Will not be able to call that function in a newer version of the library
if the ordinal number is changed
Binary compatibility is discussed further in a later lecture
Fundamentals of Symbian C++ 28
System Structure
Note
The one type of virtual function which should NOT be exported
from a DLL is a pure virtual function
• As there is generally no implementation code for a pure virtual
function
• So there is no code to export
Fundamentals of Symbian C++ 29
System Structure
Writable Static Data
• Recognize that writable static data is not allowed in DLLs on EKA1
and discouraged on EKA2
• Know the basic porting strategies for removing writable static data
from DLLs
Fundamentals of Symbian C++ 30
System Structure
Support for Writable Static Data
Symbian OS supports global writable static data in EXEs
• On all versions and handsets
In versions of Symbian OS which contain EKA1 (Symbian OS
versions 8.1a, 8.0a or earlier)
• Writable static data cannot be used in DLLs
• This is because DLLs have separate areas for program code and
read-only data
- But do not have an area for writable data
Fundamentals of Symbian C++ 31
System Structure
Versions of Symbian OS which Support
Writable Static Data in DLLs
Versions of Symbian OS which contain EKA2 (Symbian
OS versions 8.0b, 8.1b, 9.0 and beyond)
• Now support the use of writable static data in DLLs
But it is still not recommended
• As it is expensive in terms of memory usage
• And has limited support in the Symbian OS Emulator
Symbian recommends that it only be used as a last resort
• e.g. when porting code written for other platforms which uses
writable static data heavily
Fundamentals of Symbian C++ 32
System Structure
Writable Static Data in GUI applications
On EKA1
• All GUI applications were built as DLLs
• No application code could use writable static or global data
On EKA2
• Applications are now built as EXEs, so this is no longer an issue
• Modifiable global or static data has always been allowed in EXEs
Fundamentals of Symbian C++ 33
System Structure
Versions of Symbian OS which Support
Writable Static Data in DLLs
Symbian OS platform Writable static data in DLLs built for Application binary type
version
hardware
v6.1 — v8.0a Not supported on hardware builds DLL — no writable static data
(inclusive), v8.1a (compilation will fail) allowed
(EKA1)
v8.0b, v8.1b, v9.0 and Supported but not recommended — EXE — writable static data can be
beyond limited emulator support and used
(EKA2( inefficient in terms of memory usage
Fundamentals of Symbian C++ 34
System Structure
How to Enable Writable Static Data in DLLs
In order to enable global writable static data on EKA2
• The EPOCALLOWDLLDATA keyword must be added to the MMP file
of a DLL
• Where this is not used and on EKA1 versions of the Symbian OS
• The tool chain will return an error when the DLL code is built for the
phone hardware
Fundamentals of Symbian C++ 35
System Structure
Workarounds to Avoid Writable Static Data in DLLs
1. Thread-local storage
• One workaround used to replace writable static data is called thread-local
storage (TLS)
This can be accessed through
• Class Dll on pre-8.1b versions of Symbian OS
• Class UserSvr for version 8.1b and version 9.0.
Thread-local storage is a 32-bit pointer
• Specific to each thread that can be used to refer to an object which
simulates global writable static data
• All the global data must be grouped within this single object
• And allocated on the heap when the thread is created
Fundamentals of Symbian C++ 36
System Structure
Thread-Local Storage
Functions Dll::SetTls() or
UserSvr::DllSetTls()
• Are used to save the pointer to the object
• To the thread-local storage pointer
Functions Dll::Tls() or UserSvr::DllTls()
• Are used to access the global data
On destruction of the thread
• The data is destroyed too
Fundamentals of Symbian C++ 37
System Structure
Workarounds to Avoid Writable Static Data in DLLs
2. Client–server framework
• Symbian OS supports writable global static data in EXEs
A common porting strategy is to wrap the code in a Symbian
server
• Which is an EXE
• Exposing its API as a client interface
Fundamentals of Symbian C++ 38
System Structure
Workarounds to Avoid Writable Static Data in DLLs
3. Embed global variables into classes
• With small amounts of code it may be possible to move most global
data inside classes
• The data can then be passed as function parameters between objects
and functions
Fundamentals of Symbian C++ 39
System Structure
Writable Static Data Defined
Global writable static data is any per-process modifiable
variable
• Which exists for the lifetime of the process
In practice this means any globally scoped data declared
outside of
• A function
• A struct or class
• Function-scoped static variables
Fundamentals of Symbian C++ 40
System Structure
Writable Static Data Defined
The only global data that can be used within DLLs is
• constant global data of the built-in types
• Or of a class with no constructor
So these definitions are acceptable:
static const TUid KUidFooDll = { 0xF000C001 };
static const TInt KMinimumPasswordLength = 6;
Fundamentals of Symbian C++ 41
System Structure
Writable Static Data Defined
The following definitions cannot be used because they have
non-trivial class constructors
• That is, the objects must be constructed at run-time
static const TPoint KGlobalStartingPoint(50, 50);
static const TChar KExclamation(’!’);
// The following literal type is deprecated
static const TPtrC KDefaultInput =_L("");
Fundamentals of Symbian C++ 42
System Structure
Writable Static Data Defined
The memory for the object is pre-allocated in code but it does not
actually become initialized and constant
• Until after the constructor has run
Thus at build time, each constitutes a non-constant global object
• Causes the build to fail for phone hardware
• Unless the EPOCALLOWDLLDATA keyword has been added to the MMP
file of the DLL
Fundamentals of Symbian C++ 43
System Structure
Writable Static Data Defined
The following object is also non-constant
• Although the data pointed to by ptr is constant
• The pointer itself is not constant:
// Writable static data!
static const TText* ptr = (const TText*)"data";
• This can be corrected by making the pointer constant
static const TText* const ptr = (const TText*)"data";
Fundamentals of Symbian C++ 44
System Structure
Note
On EKA1
• The emulator can use the underlying Windows DLL mechanism to
provide per-process DLL data
• If non-constant global data is used inadvertently - it will go
undetected in emulator builds
• It will only fail when the PETRAN tool encounters it in the hardware
platform build
Fundamentals of Symbian C++ 45
System Structure
Executables in ROM and RAM
• Recognize the correctness of basic statements about Symbian OS
execution of DLLs and EXEs in ROM and RAM
Fundamentals of Symbian C++ 46
System Structure
EXEs in ROM and RAM
On target hardware
• Executable code can either be built onto the phone in read-only
memory (ROM) when the phone is in the factory
• Or can be later installed on the phone either into the phone’s
internal memory or onto removable storage media such as a
memory stick or MMC
ROM-based EXEs
• Can be thought of as executing directly in place from the ROM
• This means that program code and read-only data (such as literal
descriptors) are read directly from the ROM
• The component is only allocated a separate data area in RAM for
its read/write data.
Fundamentals of Symbian C++ 47
System Structure
EXEs in ROM and RAM
If an EXE is installed (rather than built into the ROM)
• It executes entirely from RAM
• It has an area allocated for program code and read-only static
data
• A separate area for read/write static data
If a second copy of the EXE is launched
• The read-only area is shared
• A new area of read/write data is allocated.
Fundamentals of Symbian C++ 48
System Structure
DLLs in ROM and RAM
DLLs in ROM
• Are not loaded into memory
• Execute in place in ROM at their fixed address
DLLs running from RAM
• Are loaded at a particular address
• The address is determined only at load time
Reference counting is used
• Allowing the DLLs to be unloaded only when they are no longer
being used by any component
Fundamentals of Symbian C++ 49
System Structure
DLLs in ROM and RAM
Loading a DLL from RAM
• Is different from simply storing it on the internal (RAM) drive
Symbian OS
• Copies it into the area of RAM reserved for program code
• Preparing it for execution by fixing up the relocation
information
Fundamentals of Symbian C++ 50
System Structure
DLLs in ROM and RAM
DLLs that execute from ROM are fixed at an address
• Thus do not need to be relocated
To compact the DLL
• In order to occupy less ROM space
• Symbian OS tools strip the relocation information out when a
ROM is built
The lack of relocation information means that a DLL cannot
be copied from the ROM
• Then stored and executed from RAM
Fundamentals of Symbian C++ 51
System Structure
DLLs in ROM and RAM
For both types of DLL (shared library and polymorphic
interface plug-in)
• The code section is shared
If multiple threads or processes use a DLL simultaneously
• The same copy of program code is accessed
• At the same location in memory
Subsequently loaded processes or libraries that wish to use
the DLL
• Are fixed up by the DLL loader to use the same copy
Fundamentals of Symbian C++ 52
System Structure
Threads and Processes
• Recognize the correctness of basic statements about threads and
processes on Symbian OS
• Recognize the role and the characteristics of the synchronization
primitives RMutex, RCriticalSection and RSemaphore
Fundamentals of Symbian C++ 53
System Structure
Threads
Threads
• Are the basic unit of execution
• Form the basis of multitasking - allowing multiple sequences of
code to execute simultaneously (or appear to do so)
It is possible to create multiple threads in a Symbian OS
application for parallel execution
But in many cases
• It is more appropriate to use active objects
• Since these are optimized for event-driven multi-tasking on
Symbian OS
Fundamentals of Symbian C++ 54
System Structure
Threads
RHandleBase
RThread
The class used to manipulate threads is RThread
• An object of type RThread represents a handle to a
thread
• The thread itself is a kernel object
Fundamentals of Symbian C++ 55
System Structure
Threads
The base class of RThread is RHandleBase
• Which encapsulates the behavior of a generic handle
• RHandleBase used as a base class throughout Symbian OS
• To identify a handle to another object
• Often a kernel object
Class RThread defines several functions for thread creation
Threads are not contained in separate executable files
• But execute within a parent process executable
• Each thread has an independent execution stream
Fundamentals of Symbian C++ 56
System Structure
The RThread::Create() Function
This is one RThread::Create() method (there are a number of
overloads):
TInt Create(const TDesC &aName,
TThreadFunction aFunction,
TInt aStackSize,
TInt aHeapMinSize,
TInt aHeapMaxSize,
TAny *aPtr,
TOwnerType aType=EOwnerProcess)
Each thread-creation function
• Takes a descriptor representing a unique name for the new thread
• A pointer to a function in which thread execution starts
• A pointer to data to be passed to that function
• A value for the stack size of the thread, which defaults to 8 KB
Fundamentals of Symbian C++ 57
System Structure
Thread Creation
A thread is created
• In the suspended state
• Its execution started by a call to RThread::Resume()
The Create() function
• Is overloaded to offer various options associated with the thread
heap
Such as
• Its maximum and minimum size
• Whether it shares the creating thread’s heap or uses a specific
heap within the process in which it runs
Fundamentals of Symbian C++ 58
System Structure
Thread Heaps
By default, each Symbian OS thread
• Has its own independent heap as well as its own stack
• The size of the stack is limited to the size set in
RThread::Create()
The heap can grow from its minimum size up to a maximum
size
When the thread has its own heap
• The stack and the heap are located in the same chunk of memory
Fundamentals of Symbian C++ 59
System Structure
Thread Identification
When the thread is created the system assigns it a unique
thread identity
• Returned by the Id() function of RThread as a TThreadId
object
If the TThreadId value of an existing thread is known
• It can be passed to RThread::Open()
• To open a handle to that thread
Alternatively
• The unique name of a thread can be passed to open a handle to
it
Fundamentals of Symbian C++ 60
System Structure
Thread Scheduling
Threads are pre-emptively scheduled
• The currently running thread is the highest-priority thread ready
to run
If there are two or more threads with equal priority
• They are time-sliced on a round-robin basis
The priority of a thread is a number
• The higher the value - the higher the priority
A running thread can be removed
• By a call to Suspend() on the thread handle
• Can be scheduled to run again by another call to Resume()
Fundamentals of Symbian C++ 61
System Structure
Thread Termination
A thread can be ended permanently
• By a call to Kill(TInt aReason) or Terminate(TInt
aReason)
• aReason represents the exit reason
• These methods should be used to stop a thread normally
• For stopping the thread to highlight a programming error
Panic() is used
On EKA1
• A thread must call SetProtected()
• To prevent other process threads from acquiring a handle to it
• And killing it by making a call to Suspend(), Panic(),
Kill() or Terminate()
Fundamentals of Symbian C++ 62
System Structure
Thread Security
On EKA2 the security model ensures
• The thread is always protected from threads running in other
processes
• The redundant SetProtected() method has been removed
• A thread cannot stop another thread in a different process
The functions
• Suspend(), Terminate(), Kill() or Panic()
• Are still retained in EKA2
• A thread can still use these functions on itself
• Or other threads in the same process
• but not on threads in a different process
It is also still possible
• For a server to panic a misbehaving client thread
• By calling RMessagePtr2::Panic()
Fundamentals of Symbian C++ 63
System Structure
Thread Termination
If the main thread in a process
• Is ended by any of the termination methods
• Suspend(), Terminate(), Kill() or Panic()
• The process also terminates
If a secondary thread
• That is created by a call to RThread::Create()from with in the
process
• The thread terminates
• The process itself does not stop running
Fundamentals of Symbian C++ 64
System Structure
Thread Death Notification
To receive notification when a thread dies
• Submit a request for notification of thread termination
• By a call to RThread::Logon(TRequestStatus
&aStatus)
• The TRequestStatus is a completion semaphore
The request completes when the thread
terminates
• aStatus contains the value with which the thread
ended
If the notification request was cancelled
• By a call to RThread::LogonCancel()
• aStatus will contain KErrCancel
Fundamentals of Symbian C++ 65
System Structure
Thread Termination
The thread handle class also provides functions to give full
details of the associated thread’s end state
TExitType RThread::ExitType()
• Allows the caller to distinguish between normal termination and a
panic
TInt RThread::ExitReason()
• Gets the specific reason associated with the end of this thread
TExitCategoryName RThread::ExitCategory()
• Gets the name of the category associated with the end of the
thread
Fundamentals of Symbian C++ 66
System Structure
Thread Notification
A thread rendezvous request can also be created
• To allow correct order synchronization e.g. data manipulation
• By calling the asynchronous RThread::Rendezvous()
The request completes in any of the following ways:
• When the thread next calls RThread::Rendezvous(TInt
aReason)
• If the outstanding request is cancelled by a call to
RThread::RendezvousCancel()
• If the thread exits or panics
Fundamentals of Symbian C++ 67
System Structure
Kernel Objects for Synchronization
Besides the use of RThread::Rendezvous(),
Symbian OS provides several classes representing
kernel objects for thread synchronization
• A semaphore
• A mutex
• A critical section
Fundamentals of Symbian C++ 68
System Structure
Semaphores
A semaphore
• Can be used either for sending a signal from one thread to
another
• Or for protecting a shared resource from being accessed by
multiple threads at the same time
A semaphore is created and accessed
• with a handle class called RSemaphore
A global semaphore
• Can be created, opened and used by any process in the system
A local semaphore
• Can be restricted to all threads within a single process
Fundamentals of Symbian C++ 69
System Structure
Semaphore
Semaphores can be used
• To limit concurrent access to a shared
resource
• Either to a single thread at a time
• Or multiple accesses up to a specified limit
Fundamentals of Symbian C++ 70
System Structure
Mutexes
A mutex
• Is used to protect a shared resource
• So that it can only be accessed by one thread at a time
• The RMutex class is used to create and access global and local
mutexes
Fundamentals of Symbian C++ 71
System Structure
Critical Sections
A critical section
• Is a region of code that should not be entered simultaneously by
multiple threads
An example is code that manipulates global static data
• Since it could cause problems if multiple threads change the data
simultaneously
Fundamentals of Symbian C++ 72
System Structure
The RCriticalSection class
The RCriticalSection class
• Allows only one thread within the process into the controlled
section
• Forces other threads attempting to gain access to that critical
section to wait until the first thread has exited from the critical
section
RCriticalSection objects
• Are always local to a process
A critical section cannot be used to control access to a
resource shared by threads across different processes
• A mutex or semaphore should be used instead
Fundamentals of Symbian C++ 73
System Structure
Processes
Fundamentals of Symbian C++ 74
System Structure
Note
A note on User-side or User-mode operations
• User-side operations dealt with by EUser.dll
• Which calls system or kernel functions for the user-side
component
• Kernel functions sometimes referred privileged mode
For mode in-depth information on the Symbian OS kernel
and memory management please see:
• Smartphone Operating System Concepts with Symbian OS
• By Michael J. Jipping
• ISBN 978-0-470-03449-1
Fundamentals of Symbian C++ 75
System Structure
Processes
A Symbian OS process
• Is an executable that has its own data area, stack and heap
• By default a process is given 8 KB of stack and 1 MB of heap
• Sometimes referred to as a unit of protection
Fundamentals of Symbian C++ 76
System Structure
Processes
Many processes can be active on Symbian OS at once
• Including multiple instances of the same process
• Processes have private address spaces
• A user-side process cannot directly access memory
belonging to another user-side process
By default
• A process contains a single execution thread - the main
thread
• Additional threads can be created as described above
Fundamentals of Symbian C++ 77
System Structure
Processes
A context switch occurs when switching from one thread to
another
• Context switches occur whenever a thread is scheduled to run and
becomes active
Switching between threads
• In different processes is more “expensive” than switching between
threads within the same process
A process context switch
• Requires that the data areas of the two processes be remapped by
the memory management unit (MMU)
Fundamentals of Symbian C++ 78
System Structure
Processes
The class used to manipulate processes is
RProcess
RHandleBase
RProcess
The RProcess::Create() function
• Can be used to start a new named process
The RProcess::Open() function
• Can be used to open a handle to a process
• Identified by name or process identity
(TProcessId)
Fundamentals of Symbian C++ 79
System Structure
Processes
There are assorted functions to stop the process
• Similar to RThread
The Resume() function
• Marks the first thread in the process as eligible for
execution
Note that there is no RProcess::Suspend()
function
• As processes are not scheduled
• Threads form the basic unit of execution and run inside
the protected address space of a process
Fundamentals of Symbian C++ 80
System Structure
Processes
On Windows
• The emulator runs within a single Win32 process called EPOC.exe
• Each Symbian OS process runs as a separate thread inside it
On EKA1
• The emulation of processes on Windows is incomplete
• RProcess::Create() returns KErrNotFound
On EKA2
• This has been removed
• Symbian OS still runs in a single process
• But the emulation is enhanced ...
• RProcess::Create() translates to creation of a new Win32
thread
Fundamentals of Symbian C++ 81
System Structure
System Structure: Part One
DLLs in Symbian OS
Writable Static Data
Executables in ROM and RAM
Threads and Processes
Fundamentals of Symbian C++ 82
System Structure
System Structure
Part Two
Fundamentals of Symbian C++
System Structure
System Structure
This Lecture Examines
• Inter-process communication (IPC)
• Recognizers
• Panics and assertions
Fundamentals of Symbian C++ 84
System Structure
Inter-Process Communication (IPC)
• Recognize the preferred mechanisms for IPC on Symbian OS
(client–server, publish and subscribe and message queues), and
demonstrate awareness of which mechanism is most appropriate
for given scenarios
• Understand the use of publish and subscribe to retrieve and
subscribe to changes in system-wide properties, including the role
of platform security in protecting properties against malicious
manipulation
Fundamentals of Symbian C++ 85
System Structure
Client-Server
The Client–Server framework
• Is a common form of inter-process communication (IPC) on Symbian OS
• The client–server framework will be discussed in detail in a later lecture
Clients connect to servers
• To establish a session for all further communication
• A session consists of client requests and server responses mediated by the
kernel
Session-based communication
• Ensures that all clients will be notified in the case of an error or shutdown of
a server
• All server resources will be cleaned up if an error occur
• Or when a client disconnects or dies
Fundamentals of Symbian C++ 86
System Structure
Client-Server
Do not worry about the details now as client-server architecture
shall be examined in a later lecture
user-side kernel-side
client server
mediated by the kernel
Session based clients can serializes requests
have more than one session
CSession2 DSession
CServer2
RServer2 DServer
Fundamentals of Symbian C++ 87
System Structure
Client-Server
The client-server communication paradigm
• Is used for many clients requiring reliable concurrent access to
a service or shared resource
• The server serializes and mediates access to the service
accordingly
There are some limitations:
• Clients must know which server provides the service they need
• A permanent session must be maintained between client and
server
• It is not really suitable for event multicasting
(Server-initiated “broadcast” to multiple clients)
Fundamentals of Symbian C++ 88
System Structure
Inter-Process Communication (IPC)
In order to overcome such limitations
• Symbian OS version 8.0 was extended
To offer additional IPC mechanisms:
• Publish and subscribe
• Message queues
• Shared buffer I/O
Publish and subscribe and message
queues
• Are described in this lecture
Fundamentals of Symbian C++ 89
System Structure
Inter-Process Communication (IPC)
Shared buffer I/O
• Is not discussed because it is intended primarily for device driver
developers
It is used
• To allow a device driver and its clients to access the same
memory area
• Without copying even during interrupt handling
Fundamentals of Symbian C++ 90
System Structure
Publish and Subscribe
The publish and subscribe mechanism
• Provides asynchronous multicast event notification
• Connectionless communication between threads
Publish and subscribe
• Provides a means to define and publish changes to system-wide
global variables known as “properties”
Changes to the properties
• Can be communicated (“published”) to more than one interested
(“subscribed”) peer asynchronously
Publishers and subscribers
• Can dynamically join and leave without any connection set-up or
tear-down
Fundamentals of Symbian C++ 91
System Structure
Publish & Subscribe
user-side kernel-side user-side
Properties
Set
Subscriber
Get
P1
Publisher
Get
Publisher/
P2
Subscriber
Set
Get
Publisher P3
Subscriber
Fundamentals of Symbian C++ 92
System Structure
Publish and Subscribe
Properties are data values
• Uniquely identified by a 64-bit integer
• Which is the only information that must be shared between a
publisher and a subscriber (typically through a common header file)
• There is no need to provide interface classes or functions for a
property
Subscribers
• Do not need to know which component is publishing to a property
They only need to know:
• About the publish and subscribe API
• The identity of the property of interest to them
Fundamentals of Symbian C++ 93
System Structure
Publish and Subscribe
The publish and subscribe API
• Is supplied by the RProperty class
RHandleBase
RProperty
The identity of a property is composed of two parts:
• A category - defined by a standard UID which specifies the category to
which the property belongs
• A key - which uniquely identifies a property within a particular category
• Its value depends on how keys within the category are enumerated
Fundamentals of Symbian C++ 94
System Structure
Publish and Subscribe
A property holds a single data variable which may be
either
• A 32-bit integer
A byte array (a descriptor) of
• Up to 512 bytes in length
• Unicode text (also up to 512 bytes in size)
• Or even large byte arrays of up to 65 536 bytes.
A thread may take the role
• Of either the publisher or the subscriber
Fundamentals of Symbian C++ 95
System Structure
Publish and Subscribe
Any thread can define a property
• By calling RProperty::Define() to create the variable
• And specify its type and access controls
Once a property has been defined
• It will persist in the kernel until it is deleted explicitly or the system
reboots
• The property’s lifetime is not linked to that of the defining thread or
process
Fundamentals of Symbian C++ 96
System Structure
Publish and Subscribe
Properties can be published or retrieved
• Using a previously attached handle
• Or by specifying the property’s identity for each call
On EKA2
• The benefit of attaching to an existing handle is that it has a
deterministic bounded execution time
• This makes it suitable for high-priority real-time tasks
Fundamentals of Symbian C++ 97
System Structure
Publish and Subscribe
A property is published
• By calling RProperty::Set()
• This writes a new value “atomically” to the property
• Ensuring that access by multiple threads is handled correctly
When a property is published
• All outstanding subscriptions are completed
• Even if the value is actually unchanged
• This allows the property to be used as a simple broadcast
notification
Fundamentals of Symbian C++ 98
System Structure
Publish and Subscribe
To subscribe to a property
• A client must register interest by attaching to it
• Calling the asynchronous RProperty::Subscribe()
method
Fundamentals of Symbian C++ 99
System Structure
Publish and Subscribe
Notification happens in the following stages:
1. A client registers its interest in the propertyy attaching to it RProperty::Attach()
- and calling Subscribe() on the resulting handle passing in a
TRequestStatus reference
2. Upon publication of a new value the client gets notified via a signal to the
TRequestStatus object to complete the Subscribe() request
3. The client retrieves the value of the updated property by calling RProperty::Get()
4. The client can re-submit a request for notification of changes to the property by calling
Subscribe() again
Fundamentals of Symbian C++ 100
System Structure
Publish and Subscribe
It is not necessary for a property to be defined
• Before it is accessed
• This is known as “lazy definition”
It is not a programming error
• for a property to be published before it has been defined
• This is known as “speculative publishing”
- Attaching to an undefined property is not necessarily an error
Fundamentals of Symbian C++ 101
System Structure
Publish and Subscribe
A Subscribe() request on an undefined property will not
complete until either:
• The property is defined and published
• Or the subscriber unsubscribes by canceling the request using
RProperty::Cancel()
Fundamentals of Symbian C++ 102
System Structure
Publish and Subscribe
Publish and subscribe is used when a component needs
to supply or consume timely and transient information
• To or from an unknown number and type of interested parties
• While remaining decoupled from them
A typical example
• Is the notification of a change to the device’s radio states
For example
• Flight-mode
• Bluetooth radio on/off
• WiFi on/off
Fundamentals of Symbian C++ 103
System Structure
Publish and Subscribe and Platform Security
On the secure platform of Symbian OS v9
• To ensure that processes are partitioned so that one process
cannot interfere with the property of another process
• The category UID of the property should match the secure
identifier of the defining process
Alternatively
• The process calling RProperty::Define() must have
WriteDeviceData capability
Properties must also be defined
• With security policies using TSecurityPolicy objects
Fundamentals of Symbian C++ 104
System Structure
Publish and Subscribe and Platform Security
For processes to publish the property value, the following
are required
• The capabilities
• (And/or) vendor identifier
• (And/or) secure identifier
For processes to subscribe to the property the following are
required
• The capabilities
• (And/or) vendor identifier
• (And/or) secure identifier
More on Platform Security and capabilities in a later lecture
Fundamentals of Symbian C++ 105
System Structure
Publish and Subscribe and Platform Security
For example
• Before accepting a subscription to a property
• The security policy defined when the property was created is
checked
• The subscription request completes with
KErrPermissionDenied if the check fails
Fundamentals of Symbian C++ 106
System Structure
Message Queues
In contrast to the connection-oriented nature of client–server IPC
• Message queues (RMsgQueue) offer a peer-to-peer, many-to-many
communication mechanism
Message queues
• Provide a way to send data (messages) to interested parties
• Without needing to know whether any thread is listening
• Or the identity of a recipient
Messages are sent
• To the queue rather than to any specific recipient
• A single queue can be shared by many readers and writers
Fundamentals of Symbian C++ 107
System Structure
Message Queues
user-side kernel-side
Msg Q Handle
DMsgQueue
Msg Q Handle
The queue
Msg Q Handle 1
Msg Q Handle 2
Thread 1 Thread 2 Thread 3
Fundamentals of Symbian C++ 108
System Structure
Message Queues
A message
• Is an object that is placed into a queue for delivery to
recipients
• A queue is normally created for messages of a given type
A queue
• Is created to deal with messages of a defined (fixed) length
• Which must be a multiple of four bytes
Fundamentals of Symbian C++ 109
System Structure
Message Queues
The size of a queue
• i.e. the maximum number of messages or slots it can contain
• Is fixed when the queue is created
The maximum size of the message and of the queue
• Are limited only by system resources
Fundamentals of Symbian C++ 110
System Structure
Message Queues
A message queue
• Allows two or more threads to communicate without setting up a
connection to each other
A message queue is a mechanism for passing data:
• Between threads that run in separate processes (using a global
queue which is named and visible to other processes)
• Between threads within a process using a local queue which is not
visible to other processes ...
Within a process
• The messages can point to memory mapped to that process and
can be used for passing descriptors and pointers between threads
Fundamentals of Symbian C++ 111
System Structure
Message Queues
Message queues allow
• For “fire-and-forget” IPC from senders to recipients
• Lend themselves well to event notification
Publish and subscribe
• Is good for notification of state changes which are inherently transient
Message queues
• Are useful for allowing information to be communicated beyond the
lifetime of the sender
Fundamentals of Symbian C++ 112
System Structure
Message Queues
An a good example of using message queues:
• A central logging subsystem can use a message queue to receive
messages from numerous threads
• That may or may not still be running at the point the messages are read
and processed
However
• Neither messages nor queues are persistent
• They are cleaned up when the last handle to the queue is closed
Fundamentals of Symbian C++ 113
System Structure
Recognizers
• Recognize correct statements about the role of recognizers in
Symbian OS
Fundamentals of Symbian C++ 114
System Structure
Recognizers
Recognizers
• Are a good example of the use of framework plug-in DLLs
• The framework which loads the recognizers is provided by the
application architecture server (Apparc)
Up to Symbian OS v9.1
• Apparc implemented its own custom loading of recognizer plug-ins
In later releases it has been modified to use ECOM
Fundamentals of Symbian C++ 115
System Structure
Recognizers
When a file in the file system needs to be associated with an
application
• Apparc opens the file and reads some data from the start of it into a
buffer
• It then calls DoRecognizeL() on each recognizer in the system
in turn
• Passing in the data it read into the buffer
• If a plug-in “recognizes” it it returns its data type (MIME type)
Recognizers do not handle the data
• They just try to identify its type
• So that the data can be passed to the application that can best use
it
Fundamentals of Symbian C++ 116
System Structure
Recognizers
The plug-in recognizer architecture
• Allows developers to create additional data recognizers
• Adding them to the system by installing them
All data recognizers
• Must implement the polymorphic interface defined by
CApaDataRecognizerType
• Which has three virtual functions ...
Fundamentals of Symbian C++ 117
System Structure
DoRecognizeL()
DoRecognizeL()
• Performs data recognition
• This function is not pure virtual but must be implemented
Each implementation
• Should set a value to indicate the MIME type it considers the data to
belong to
And a value to indicate a level of confidence ranging from:
• ECertain - the data is definitely of a specific data type
• ENotRecognized - the data is not recognized
Fundamentals of Symbian C++ 118
System Structure
SupportedDataTypeL()
SupportedDataTypeL()
• Returns the MIME types that the recognizer is capable of
recognizing
• This pure virtual function must be implemented by all recognizer
plug-ins
Each recognizer’s implementation of
SupportedDataTypeL()
• Is called by the recognizer framework
• After all the recognizers in the system have been loaded
• To build up a list of all the types the system can recognize
Fundamentals of Symbian C++ 119
System Structure
PreferredBufSize()
PreferredBufSize()
• Specifies the size in bytes of the buffer passed to
DoRecognizeL()
• That the recognizer needs to work with
• This function is not pure virtual but must be implemented
Fundamentals of Symbian C++ 120
System Structure
Panics and Assertions
• Know the type of parameters to pass to User::Panic() and
understand how to make them meaningful
• Understand the use of __ASSERT_DEBUG statements to detect
programming errors in debug code by breaking the flow of code
execution using a panic
• Recognize that __ASSERT_ALWAYS should be used more sparingly
because it will test statements in released code too and cause code
to panic if the assertion fails
Fundamentals of Symbian C++ 121
System Structure
Panics
When a thread is panicked
• It stops running
Panics are used
• To highlight a programming error in the most noticeable way
• By stopping the thread to ensure that the code is fixed
• Rather than potentially causing serious problems by continuing
to run
There is no recovery from a panic
• Unlike a leave - a panic can’t be trapped
• A panic is terminal
Fundamentals of Symbian C++ 122
System Structure
Panics
If a panic occurs in the main thread of a process
• The entire process in which the thread runs will terminate
If a panic occurs in a secondary thread
• It is only that thread which closes
If a thread is deemed to be a system thread
• That is - essential for the system to run
• A panic in that thread will reboot the phone
This is very rare
• Since the code running in system threads on Symbian OS is
mature and well-tested
Fundamentals of Symbian C++ 123
System Structure
Panics
On phone hardware
• And in release builds on the Windows emulator
• The end result of a panic is either a reboot or an “Application
closed” message box
In debug emulator builds
• A panic can be set to break into the debugger
• Known as “just-in-time” debugging
The developer can use the debugger
• To look through the call stack to see where the panic arose
• Thus to examine the state of appropriate objects and variables
Fundamentals of Symbian C++ 124
System Structure
Panics
A call to the static function User::Panic()
• Panics the currently running thread
On EKA2
• A thread may panic any other thread in the same process
• By acquiring an RThread handle and using it to call
RThread::Panic()
On EKA1
• This function could be used to panic any unprotected thread in any
process
• This was deemed insecure for EKA2
Fundamentals of Symbian C++ 125
System Structure
Panics
The only occasion for EKA2 ...
• Where a thread running inside a user process can panic
another thread in a different process
Is for a server thread to panic a badly-behaved client
• By using the RMessagePtr2::Panic() method
Fundamentals of Symbian C++ 126
System Structure
Panics
User::Panic() and RThread::Panic() take two
parameters:
• A panic category string
• An integer error code which can be any value, positive, zero or
negative.
Without breaking into the debugger
• These values should still be sufficient for a developer to determine
the cause of a panic
Fundamentals of Symbian C++ 127
System Structure
Panics
The panic string
• Should be short and descriptive for a programmer rather than for a
user - since the user should never see them
Panics should only be used as a means to eliminate
programming errors during the development cycle
• For example by using them in assertion statements
• Panicking cannot be seen as useful functionality for properly
debugged software
Fundamentals of Symbian C++ 128
System Structure
Panics
The following is a very bad example of the use of a panic to indicate a
problem to a user:
_LIT(KTryDifferentMMC, "File was not found, try selecting another");
User::Panic(KTryDifferentMMC, KErrNotFound); // Not helpful!
The following is a good example of the use of a panic
• To highlight a programming error to a developer calling a function in class
Bar of the Foo library, and passing in invalid arguments
• The developer can determine which method is called incorrectly and fix the
problem:
_LIT(KFooDllBarAPI, "Foo.dll, Bar::ConstructL");
User::Panic(KFooDllBarAPI, KErrArgument);
Fundamentals of Symbian C++ 129
System Structure
Panics
Symbian OS
• Has a series of well-documented panic categories for
example:
• KERN-EXEC
• E32USER-CBASE
• ALLOC
• USER
• And associated error values
The details of which can be found in the Symbian OS
Library which accompanies each SDK
Fundamentals of Symbian C++ 130
System Structure
Assertions
Assertions are used
• To check that assumptions made about code are correct
• For example - the states of objects, function parameters or return
values are as expected
Typically
• An assertion evaluates a statement
• If it is false it halts execution of the code
There is an assertion macro for debug builds only
• __ASSERT_DEBUG
For both debug and release builds
• __ASSERT_ALWAYS
Fundamentals of Symbian C++ 131
System Structure
Assertions
The assertion macro tests a statement
• If it evaluates to false it calls the method specified in the second
parameter passed to the macro
The method is not hard-coded to be a panic
• But rather than return an error or leave it should always terminate
the running code and flag up the failure
• Panics are the best choice
Fundamentals of Symbian C++ 132
System Structure
Assertions
Assertions help the detection
• Of invalid states or bad program logic so that code can be
fixed
It makes sense to stop the code at the point of error
• Rather than return an error as it is easier to track down the
bug
Fundamentals of Symbian C++ 133
System Structure
Assertions
The use of assertions in release builds of code should be
considered carefully
• Assertion statements have a cost in terms of size and speed
• If the assertion fails - it will cause code to terminate with a panic
• Resulting in a poor user experience
Fundamentals of Symbian C++ 134
System Structure
Assertions
This is one example of how to use the debug assertion macro:
void CTestClass::EatPies(TInt aCount)
{
#ifdef _DEBUG
_LIT(KMyPanicDescriptor, "CTestClass::EatPies");
#endif
__ASSERT_DEBUG((aCount>=0),
User::Panic(KMyPanicDescriptor, KErrArgument));
... // Use aCount
}
Fundamentals of Symbian C++ 135
System Structure
Assertions
It is more common for a class or code module to define:
• A panic function
• A panic category string
• A set of specific panic enumerators
For example
• The following enumeration could be added to CTestClass
• So as not to pollute the global namespace
enum TTestClassPanic
{
EEatPiesInvalidArgument, // Invalid argument passed to EatPies()
... // Enum values for assertions
// in other CTestClass methods
};
Fundamentals of Symbian C++ 136
System Structure
Assertions
A panic function is defined either
• As a member of the class
• Or as a static function within the file containing the implementation
of the class:
static void CTestClass::Panic(TInt aCategory)
{
_LIT(KTestClassPanic, "CTestClass");
User::Panic(KTestClassPanic, aCategory);
}
• The assertion in EatPies() can then be written as follows:
void CTestClass::EatPies(TInt aCount)
{
__ASSERT_DEBUG((aCount>=0), Panic(EEatPiesInvalidArgument));
... // Use aCount
}
Fundamentals of Symbian C++ 137
System Structure
Assertions
The advantage of using an identifiable panic
descriptor and enumerated values for different
assertion conditions
• Is traceability
This is particularly useful for calling code using a
given library
• The developer may not have access to the library source
code
• Only access to the header files
Fundamentals of Symbian C++ 138
System Structure
Assertions
If the panic string is clear and unique
• A developer should be able to locate the class which raised the
panic
• Use the panic category enumeration to find the associated failure
• Which is named and documented to explain clearly why the
assertion failed
Fundamentals of Symbian C++ 139
System Structure
Assertions
Code with side effects
• Should not be called within assertion statements
The code may well behave as expected in debug mode
• But in release builds the assertion statements are removed
by the preprocessor
• With them potentially vital steps in the programming logic
Fundamentals of Symbian C++ 140
System Structure
Assertions
Rather than use the “condensed” statements
// Bad use of assertions!
__ASSERT_DEBUG(FunctionReturningTrue(), Panic(EUnexpectedReturnValue));
__ASSERT_DEBUG(++index<=KMaxValue, Panic(EInvalidIndex));
• Statements should be evaluated independently
• With their returned values then passed into the assertion macros
Fundamentals of Symbian C++ 141
System Structure
Panics, Assertions and Leaves
Leaves
• May legitimately occur under exceptional
conditions
Such as:
• Out of memory
• Insufficient disk space
• Or the absence of a communications link
It is not possible
• To stop a leave from occurring
• Code should implement a graceful recovery
strategy
• Always catch leaves using TRAP statements
Fundamentals of Symbian C++ 142
System Structure
Panics, Assertions and Leaves
Programming errors (“bugs”) can be caused by:
• Contradictory assumptions
• Unexpected design errors
• Genuine implementation errors
These are persistent and unrecoverable errors
• Which should be detected and corrected by the programmer
• Rather than handled at run-time
The mechanism to do this
• Is to use assertion statements
These terminate the flow of execution of code if an error
is detected, using a panic
• Panics cannot be caught and handled gracefully
• The programmer has to fix the problem
Fundamentals of Symbian C++ 143
System Structure
System Structure : Part Two
Inter-Process Communication (IPC)
Recognizers
Panics and Assertions
Fundamentals of Symbian C++ 144