ARM MicroLIB and malloc() thread safety with FreeRTOS

  • MCU: nRF52840
  • IDE: Keil uVision 5.17
  • SDK: 15.2.0
  • Board: Custom
  • OS: FreeRTOS
  • Using MicroLIB

Hello,

I am currently working on a FreeRTOS project that leverages a third party data processing library that internally uses malloc(), realloc(), and free(). I realize that all of these malloc() and associated calls should ideally be replaced with FreeRTOS equivalents pvPortMalloc(), vPortFree(), and a custom solution for realloc(). However, I am fine with allowing this library to use the standard heap as defined by '__HEAP_SIZE=8092' in my preprocessor symbols. My concern is whether or not the malloc() standard library functions are thread safe in MicroLIB.

According to the ARM documentation, it doesn't state MicroLIB specifically, but it does state that malloc() and other standard functions can be made thread safe by specifying _mutex_* functions.

Source: https://developer.arm.com/documentation/dui0475/m/the-c-and-c---library-functions-reference/thread-safe-c-library-functions

Question 1: Is malloc(), free(), and realloc() thread safe in MicroLib? I am not sure whether the link above applies to the default C library or MicroLIB.

Question 2: If not thread safe, does anyone have the correct function prototypes for the necessary mutex functions in MicroLib? The only thing I have been able to find is the following from an unofficial source:

int _mutex_initialize (OS_ID *mutex) __attribute__((used));

void _mutex_acquire (OS_ID *mutex)   __attribute__((used));

void _mutex_release (OS_ID *mutex)   __attribute__((used));

Lastly, I tested compiling my code with the "MicroLIB" box not checked, and I can now see the following in my .map file:

_mutex_acquire - Undefined Weak Reference
_mutex_free - Undefined Weak Reference
_mutex_release - Undefined Weak Reference

So it seems the standard library has some sort of existing implementation that I have no visibility into.

Thanks,

Derek

Parents
  • Question 1: Is malloc(), free(), and realloc() thread safe in MicroLib? I am not sure whether the link above applies to the default C library or MicroLIB.

    I do not see that the weak implementation of _mutex_acquire , _mutex_free  and _mutex_release  has been patched with freertos mutexes. What I understand from the documentation of the arm c libraries is that there is a use of these weak implementation of mutexes inside these heap functions, but these are dummy functions not doing anything and expects to be overridden by the layer above. So what you need to do is that you need to overide the weak implementation of these C library functions with freertos mutexes API and the C library for these heap functions would make sure to call these overridden calls to ensure thread safety.

    In short, you should override these functions using FreeRTOS API and the C library would take care of the rest to call them when needed.

  • So this is what I have discovered after implementing the following functions as test code:

    volatile SemaphoreHandle_t testMutex = (SemaphoreHandle_t) 0x00000012;
    
    int _mutex_initialize(SemaphoreHandle_t *sid)
    {
       *sid = testMutex;
       return 1;
       
       // /* Create a mutex semaphore */
       // *sid = CreateLock(...);
       // return 1;
    }
    
    void _mutex_acquire(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Task sleep until get semaphore */
       //AcquireLock(*sid, ...);
    }
    
    void _mutex_release(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Release the semaphore. */
       //ReleaseLock(*sid);
    }
    
    void _mutex_free(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Free the semaphore. */
       //FreeLock(*sid, ...);
    }

    If I compile without MicroLIB (box not checked on Options for Target->Target), I see the following in the .map file:

    "h1_free_mt.o(.text) refers (Weak) to main.o(i._mutex_acquire) for _mutex_acquire"

    So I can see my implementation overriding the weak implementations. I can also see the code execute as shown below:

    If I compile with MicroLIB and look at the .map file, there are no weak implementations of _mutex_acquire() and similar functions and thus nothing is overridden. Also, my breakpoint depicted above is never hit.

    Question : Does this mean that MicroLIB doesn't use the _mutex_* functions? If not, then is malloc() thread safe in MicroLIB or is it inherently not thread safe with no way to make it thread safe?

    Thanks,

    Derek

Reply
  • So this is what I have discovered after implementing the following functions as test code:

    volatile SemaphoreHandle_t testMutex = (SemaphoreHandle_t) 0x00000012;
    
    int _mutex_initialize(SemaphoreHandle_t *sid)
    {
       *sid = testMutex;
       return 1;
       
       // /* Create a mutex semaphore */
       // *sid = CreateLock(...);
       // return 1;
    }
    
    void _mutex_acquire(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Task sleep until get semaphore */
       //AcquireLock(*sid, ...);
    }
    
    void _mutex_release(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Release the semaphore. */
       //ReleaseLock(*sid);
    }
    
    void _mutex_free(SemaphoreHandle_t *sid)
    {
       testMutex = * sid;
       
       /* Free the semaphore. */
       //FreeLock(*sid, ...);
    }

    If I compile without MicroLIB (box not checked on Options for Target->Target), I see the following in the .map file:

    "h1_free_mt.o(.text) refers (Weak) to main.o(i._mutex_acquire) for _mutex_acquire"

    So I can see my implementation overriding the weak implementations. I can also see the code execute as shown below:

    If I compile with MicroLIB and look at the .map file, there are no weak implementations of _mutex_acquire() and similar functions and thus nothing is overridden. Also, my breakpoint depicted above is never hit.

    Question : Does this mean that MicroLIB doesn't use the _mutex_* functions? If not, then is malloc() thread safe in MicroLIB or is it inherently not thread safe with no way to make it thread safe?

    Thanks,

    Derek

Children
Related