2.2.3. The __user_libspace static data area
The __user_libspace static data area holds the static data for the C libraries. This is a block of 96 bytes of zero-initialized data, supplied by the C library. It is also used as a temporary stack during C library initialization.
The default ARM C libraries use the __user_libspace area to hold:
errno, used by any function that is capable of setting errno. By default, __rt_errno_addr() returns a pointer to errno.
The FP status word for software floating‑point (exception flags, rounding mode). It is unused in hardware floating‑point. By default, __rt_fp_status_addr() returns a pointer to the FP status word.
A pointer to the base of the heap (that is, the __Heap_Descriptor), used by all the malloc‑related functions.
The alloca state, used by alloca() and its helper functions.
The current locale settings, used by functions such as setlocale(), but also used by all other library functions which depend on them. For example, the ctype.h functions have to access the LC_CTYPE setting.
The C++ libraries use the __user_libspace area to hold:
For more information on __aeabi_atexit(), std::set_terminate() and std::set_unexpected(), see the ARM website for the following specifications: CPPABI and the Exception Handling ABI for the ARM Architecture.
Note
How the C and C++ libraries use the __user_libspace area might change in future releases.
Addressing __user_libspace
Two wrapper functions are provided to return a subsection of the __user_libspace static data area:
__user_perproc_libspace()Returns a pointer to 96 bytes used to store data that is global to an entire process, that is data shared between all threads.
__user_perthread_libspace()Returns a pointer to 96 bytes used to store data that is local to a particular thread. This means that __user_perthread_libspace() returns a different address depending on the thread it is called from.
Re‑implementing __user_libspace
The __user_libspace() function does not normally have to be redefined. However, if you are writing an operating system or a process switcher, you must re‑implement this function. See Tailoring static data access for more information.
Where you are porting single‑threaded processes to RVCT that re‑implement this function, you can continue to do this without having to change your code. The change in behavior is, however, important if you are using RVCT to write multithreaded applications.