To use the ARM C library in a multithreaded environment, you must provide:
An implementation of
__user_perthread_libspace()that returns a different block of memory for each thread. This can be achieved by either:
Returning a different address depending on the thread it is called from.
Having a single
__user_perthread_libspaceblock at a fixed address and swapping its contents when switching threads.
You can use either approach to suit your environment.
You do not have to re-implement
__user_perproc_libspace()unless there is a specific reason to do so. In the majority of cases, there is no requirement to re-implement this function.
A way to manage multiple stacks.
A simple way to do this is to use the ARM two-region memory model. Using this means that you keep the stack that belongs to the primary thread entirely separate from the heap. Then you must allocate more memory for additional stacks from the heap itself.
Thread management functions, for example, to create or destroy threads, to handle thread synchronization, and to retrieve exit codes.
The ARM C libraries supply no thread management functions of their own so you must supply any that are required.
A thread-switching mechanism.
The ARM C libraries supply no thread-switching mechanisms of their own. This is because there are many different ways to do this and the libraries are designed to work with all of them.
You only have to provide implementations of the mutex functions if you require them to be called.
In some applications, the mutex functions might not be useful. For example, a co-operatively threaded program does not have to take steps to ensure data integrity, provided it avoids calling its yield function during a critical section. However, in other types of application, for example where you are implementing preemptive scheduling, or in a Symmetric Multi-Processor (SMP) model, these functions play an important part in handling locks.
If all of these requirements are met, you can use the ARM C library in your multithreaded environment. The following behavior applies:
Some functions work independently in each thread.
Some functions automatically use the mutex functions to mediate multiple accesses to a shared resource.
Some functions are still nonreentrant so a reentrant equivalent is supplied.
A few functions remain nonreentrant and no alternative is available.