Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



Emulator/native platform differences

The emulator is a port of the Symbian OS kernel to the Win32 platform. For most circumstances, this provides a faithful emulation of the OS behaviour on target hardware. However, there are some differences that could affect application developers, and these are documented in this page. The sections are:


Bootstrap

On real phones, the first Symbian OS program to run is a bootstrap program, which performs various hardware initialization tasks before starting the kernel. The emulator does not need to perform the hardware initialization tasks, so its start-up simply needs to start the kernel. This is done through the BootEpoc() function in the EUSER library. The standard emulator start program EPOC.EXE simply calls this function. Other executables that are built for the emulator also always include this start up call, so that the running any emulator executable boots the emulator.

The remainder of the boot process is similar on the emulator to the native target. At the end of kernel start-up, a program estart is run. This checks to see how the emulator was bootstrapped: if it was started by EPOC.EXE, it exits and the emulator boot has completed. Otherwise, it retrieves the Symbian OS process to start, and any command line to give it, then creates that process, waits for it to exit, and then terminates the emulator.

[Top]


File system support

The emulator emulates a variety of file systems and drive types, including ROFS/FAT over NAND flash drive, LFFS over NOR flash drive, MMC, and RAM drive. Such drives are mapped to the single files on the Windows local drive, rather than actual hardware. For details, see Files and locations.

Performance and size of such emulated drives may not be the same as would be expected with real hardware. There are some options that you can use though to get a closer emulation:

[Top]


Floating point behaviour

Floating point behaviour is different on the emulator and on hardware.

Symbian OS provides access to IEEE-754 single precision and double precision floating point values through the types TReal32 (C++ float type) and TReal64 (C++ double type) respectively.

The various compilers have built-in types float and double and understand how to represent constants of these types, e.g. "(double)1.1415926". On processors that have floating point hardware, the compiler generates host instructions which use that hardware directly. On processors which don't have a floating point unit, the compiler implements the calculations in software.

The emulator is implemented on the Intel x86 processors which have floating point hardware, so this support is used. Target hardware may or may not have hardware support. You should be careful of large performance differences in code that intensively uses floating-point functions where the target hardware does not have hardware support.

[Top]


Machine word alignment

ARM uses a 32-bit RISC architecture with minimal extra silicon for unnecessary control purposes. This is the main reason why the chip is so cheap, and uses so little power, which in turn is why it is so popular for battery-powered consumer devices.

One consequence of this is that 32-bit quantities must be aligned to a 32-bit machine word boundary: in other words, their address must be a multiple of four. So, for instance, the following code

TInt* p; // pointer to integers
...
TInt i=*p; // get from a pointer

will only work if p is a multiple of four at the time it is used. If p is not a multiple of four, an access violation will result.

For normal purposes, this restriction is transparent to the programmer, because struct and class members are aligned appropriately by the compiler and heap allocator. For example, in

struct S
    {
    TText8 iText; // offset 0, 1 byte
    TText8 iText2; // offset 1, 1 byte
    TInt32 iInteger; // offset 4, 4 bytes
    };

the second byte quantity is aligned at offset 1, which is permissable for bytes. But the compiler generates two pad bytes in order to align the integer at offset 4. Therefore, sizeof(S) is 8, not 6 as might be expected. The compiler ensures that all quantities are aligned, whether in structs or C arrays.

You must be aware of the alignment restriction, however, if you are implementing a packed structure of some kind. For instance, the code

TText8 array[200];
for (TInt i=0; i<=196; i++)
    {
    TInt* p=(TInt*) array[i]; // needs a cast
    TInt n=*p; // four bytes from the array makes one integer?
    }

may work on the emulator. It will compile with a native compiler, but it will generate an access violation the second time through the loop, because p will be one greater than a multiple of four.

To avoid this problem, you should do something like

TText8 array[200];
for (TInt i=0; i<196; i++)
    {
    TAny* p=array[i]; // really a TAny*, so no cast needed!
    TInt n;
    Mem::Copy(&n, p, sizeof(TInt)); // copy byte by byte
    }

In a way, C++'s type system supports the programmer here. The packed structure can only be implemented by using casting. When you do a cast, you must always think about what might be the potentially dangerous consequences. In the ARM environment, machine word alignment is a potentially dangerous consequence that you must always bear in mind. On the other hand, when you are not using casts, the compiler will do all that is necessary to ensure machine word alignment, without programmer intervention.

[Top]


Memory constraints

By default, the emulator emulates a device with a total heap size of 64MB. This value can be changed using the MegabytesOfFreeMemory keyword.

The initial and maximum size for the default heap for an individual process on the emulator (EKA2) can be set, in the same way as for a process on a native target, using the epocheapsize mmp file keyword. This directive is applicable from Symbian OS v9.1, EKA2 releases. EKA2 supports multiple process creation and allows the heap size to be calibrated between the minimum and maximum limits.

Processes on native targets usually have small stack sizes (by default 8K). On the emulator, stack sizes will expand as needed to much larger Windows limits. This may cause programs that overuse the stack to work on the emulator, but fail on hardware with stack overflows KERN-EXEC 3 panics. The epocstacksize mmp file keyword, used to specify a non-default stack size.

[Top]


Process emulation

The EKA2 kernel provides a good emulation of Symbian OS processes on the emulator. There are, however, some limitations:

The background to these differences is that the emulator runs as a single Windows process. This is because a key purpose of the emulator is debugging, and debugging multiple processes is difficult to do. The requirement to run as a single process means that the emulator has to take some extra steps when creating a new Symbian OS process from an EXE file. It makes a copy of the EXE file, and makes some minor changes to the copy that allows Windows to load the file as a DLL into the emulator process.

[Top]


Scheduling

The emulator faithfully emulates the thread scheduling functionality used on a native target.

Windows thread scheduling does not provide the necessary functionality to emulate Symbian OS scheduling: Symbian OS provides 64 priority levels for threads, while Win32 provides five usable distinct priorities within a process. This means that the kernel must provide its own scheduling mechanism. In order for this to work, Win32 cannot be allowed to arbitrarily schedule Symbian OS threads to run. The kernel achieves this by only making one Symbian OS thread ready to run as a Win32 thread; the others will either be waiting on a Win32 event object or suspended. One effect of this policy is that all Symbian OS threads can have the same standard Win32 priority.

The emulator does not provide the real-time guarantees that the EKA2 kernel does on target hardware, as timings are subject to what other processes Windows is running.

[Top]


Serial ports

The emulator provides emulation of serial ports through Windows serial ports. This is adequate for most purposes, but may not provide the same performance as UARTs on a real device. In particular, some applications have found that high latency times in Windows serial ports have caused some communications data to be dropped.

[Top]


Timer

The standard timer resolution used for User::After(), RTimer::At(), etc. is 1/64th second on all platforms, including the emulator.

There is also a finer ('HiRes') timer, accessed through methods such as User::AfterHighRes(), and RTimer::HighRes(). This is 1ms resolution on reference hardware, but defaults to 5ms on the Emulator. This can be changed by setting the timer period (in ms) through the TimerResolution variable in the epoc.ini file.

[Top]


USB

The OS provides USB client support on reference hardware. There is no such support in the emulator.