Writable Static Data (WSD): Problem Definition and Solutions
Process and Thread Memory
In Symbian, process address space includes:
System-wide memory for ROM and RAM loaded DLLs
Process-wide memory such as code and data segment
Thread-wide memory such as stack and heap (not always)
When a thread is created, by default each thread will have its own stack of size 8KB. We can change this by specifying the stack size while creating the thread. We can set the thread size in mmp file also using epocstaksize keyword. A thread's stack cannot grow once after the thread has been started. If all stack variables cannot be accommodated on that thread's stack, it will PANIC. When a thread is created, it can either have its own heap, or can share the parent thread's heap. By default, a thread can have minimum of 4KB and maximum of 1 MB heap area. We can change this using mmp file with epocheapsize keyword. We can also specify, these two parameters while creating the thread also. A thread's default heap can grow if the current heap cannot accommodate all heap resources. If system free list does not have enough pages, then, even this will fail with out-of-memory error.
Typically, in Symbian, as executable can be EXE (executable with single main entry at E32Main) or DLL (library of program code with many entry points). All ROM based executables are executed in-place where as those executable not in ROM, must be first loaded into RAM.
Each instance of a RAM based EXE will have its own area for code, read-only data and read-write data. When it comes to ROM based EXE, there is some amount of optimization; each instance of ROM based EXE will have its own RAM area for read/write data. Code and read-only data are shared and read directly from ROM.
ROM based DLLs are not loaded at all. They are simply used in-place in ROM. RAM based DLL's are relocated to a particular address. When 2nd process requires the same DLL, it will be attached with existing code. Symbian OS will have a reference count so that DLL will be unloaded when no more threads are linked (attached) to it. So, DLLs are shared with all the process they are linked with.
Since DLLs are shared, there is some issue when it comes to accessing write-able global data of DLL. These data are called as WSD (Write-able Static Data). Each DLL that has WSD would require a separate chunk of memory of RAM (which is 4KB) to be allocated in every process that links to this DLL. Assuming a DLL has a global non-constant char as WSD and there are some 50 applications links to them, then 50 * 4 = 200 KB of RAM memory will be allocated for this WSD, which will take just 50 Bytes (50 * size of char) of memory! Assume a situation where there are hundreds of such DLLs linking to hundreds of applications, then huge amount of RAM (100*100*4 KB) will be consumed only for WSD.
Because of the problem, which I have mentioned above, Symbian does not encourage the use of WSD in our DLLs. In fact till Symbian 9.1, we cannot have WSD in a Symbian DLL. But from Symbian 9.1 onwards Symbian allows this by making of use of EPOCALLOWDLLDATA keyword in mmp file. Main reason for this one is for porting some non-Symbian applications onto Symbian. But Symbian does not encourage the use of this keyword. Instead of this Symbian provides some alternatives like:
Use of Client-Server framework
Use of TLS (Thread Local Storage)
Use of TLS for WSD:
Each DLL will have one word entity called as TLS (Thread Local Storage) that exists per thread per DLL basis.
All the global and static data in the DLL can be grouped together into a single structure and this particular structure will be created on heap when the thread is created. And thread's TLS will be assigned with this pointer to the structure. For this Dll::SetTls() api is used. For accessing/modifying any of the global data, we need to follow these steps:
- use Dll::Tls() for getting the pointer to the structure
- use the pointer for referencing the actual data.
During the destruction of the thread, TLS pointed structure can be deleted and the TLS can be set to zero.
Typically each DLL, which uses this technique, will have one function, which will be called just before using any of the DLL's functionality (api). This function will take care of creating the structure that contains all global data on heap and setting up the Dll's Tls. The code will look something like this:
{
//allocate the structure containing global data on heap
GlobalData* p = new GlobalData();
if ( p )
{
Dll::SetTls( p ); //Set this Dll's Tls with this structure pointer
}
else
//Panic the thread
}
Such DLL will have one more function, which will take care of freeing up resources. When done with the usage of this DLL, thread will call this function. The functionality of this function will look something like this.
{
//Get the Dll's Tls
GlobalData* p = (GlobalData*) Dll::Tls();
if ( p )
{
//Do some global variable specific cleanup activity if required
Cleanup( p );
delete p; //Deallocate the memory now
}
}
Typically other exported api's of DLL will get the DLL's Tls and use the global variables. It will be implemented something like this most of time:
typedef struct
{
int globalVal1;
...
char globalValn
}GlobalData;
//some .c or .cpp file
EXPORT_C void FunctionOne()
{
//Get the Dll's Tls
GlobalData* p = (GlobalData*) Dll::Tls();
FunctionOne_r ( p );
}
//re-entrant version of above function
void FunctionOne_r( GlobalData* p )
{
//use all those variables required pointed by the structure p
p->globalVal1 += 10;
p->globalValn = ‘C';
}
Assuming MyDLL.DLL is a DLL, which links to two more DLLs namely LIBRARYONE.DLL and LIBRARYTWO.DLL, then the thread in MyDLL.DLL will have 2 TLS each for above 2 DLLs. When MyDLL.DLL uses some functionality of LIBRARYONE.DLL, its TLS will be different and when it uses some functionality of LIBRARYTWO.DLL, its TLS will be different.
Use of Client Server Framework for WSD:
As EXE's are not sharable, Symbian OS supports writeable global static data in EXEs. Server, which runs as a thread, can be an independent thread/process separate from its client or both client and server can be embedded in same process as two different threads. When Server runs as a separate process, then it will be an EXE. As EXE's can have WSD, a common strategy is to keep all global data in the server and to expose some APIs as client interface that modify these global variables for clients.






> Writable Static Data (WSD): Problem Definition and Solutions
Probably the biggest problem with TLS is the overhead accessing a global variable through it.
This requires a switch (slow call) into the Kernel to get the pointer which is roughly 30 times slower than an equivalent call to a global variable.
> Writable Static Data (WSD): Problem Definition and Solutions
The support for writeable static global data in DLLs has been provided (by EKA2 kernel ) since Symbian OS 8.0b , refer following link for details .
http://www.symbian.com/developer/techlib/papers/static_data/SupportForWriteableStaticDataInDLLsv1.1.pdf
Pls do not mind girish , the WSD is supported since Symbian OS 8.0 and not since symbian OS 9.1 .
Regards Neo
> Writable Static Data (WSD): Problem Definition and Solutions
Hi Neo,
In EKA2 , WSD is allowed as you said, but with restrictions on the emulator environment.There is a limitation: the dll with WSD can only be loaded into a single process on emulator. WSD's are anyway expensive because they take up one memory chunk. And since in EKA2, there are only 16 memory chunks, this would mean, having WSD's would reduce the number of chunks available for other processes.
So we're still advised to minimise/avoid use of WSD's in non kernel dll's.
cheers, Mable.
Writable Static Data (WSD): Problem Definition and Solutions
I wonder why DLL WSD could not use the heap of the process, who is using the DLL? Then it would not need a new memory page ("chunk") for each process, that uses the DLL, and thus this would eliminate the huge memory overhead described in the article.
I think there is a question of address space, but there is probably a solution for that: dynamical re-mapping of the WSD addressing. I can explain this more detail if somebody still gets interested.
Writable Static Data (WSD): Problem Definition and Solutions
As all global/static data will get loaded onto Data Segement of a process, WSD of DLL can not get loaded onto heap of the process unless and until something is supported by the Loader of the OS.
Again, the above statement is just from my understanding of OS and process creation. I am very much interested in knowing the solution details you are proposing for the WSD problem. Please do explain me about that, either through this one or through by mailing it to my id: girish.shetty@nokia.com
Thanks a lot well in advance
Girish