Skip to content

Instantly share code, notes, and snippets.

@Xenoamor
Created June 15, 2021 10:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xenoamor/cacf18cb19e2b260fe291b3474e1605d to your computer and use it in GitHub Desktop.
Save Xenoamor/cacf18cb19e2b260fe291b3474e1605d to your computer and use it in GitHub Desktop.
C++ embedded exception thread safety test
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
static TaskHandle_t xHandleTask1 = nullptr;
static TaskHandle_t xHandleTask2 = nullptr;
static SemaphoreHandle_t cxa_throw_mutex = nullptr;
static void toggle_blue_led();
static void toggle_green_led();
// Wrap the _cxa_begin_catch and _cxa_end_catch calls with a mutex
// This requires the following linker options:
// -Wl,--wrap=__cxa_begin_catch
// -Wl,--wrap=__cxa_end_catch
extern "C" void *__real___cxa_begin_catch(void *);
extern "C" void *__wrap___cxa_begin_catch(void *ptr)
{
xSemaphoreTakeRecursive(cxa_throw_mutex, portMAX_DELAY);
return __real___cxa_begin_catch(ptr);
}
extern "C" void __real___cxa_end_catch();
extern "C" void __wrap___cxa_end_catch()
{
__real___cxa_end_catch();
xSemaphoreGiveRecursive(cxa_throw_mutex);
}
void Task1(void *pvParameters)
{
for (;;)
{
try
{
throw 5;
}
catch (int e)
{
toggle_blue_led();
}
try
{
throw 10;
}
catch (int e)
{
toggle_blue_led();
}
}
}
void Task2(void *pvParameters)
{
for (;;)
{
try
{
throw 5;
}
catch (int e)
{
toggle_green_led();
}
try
{
throw 10;
}
catch (int e)
{
toggle_green_led();
}
}
}
int main()
{
xTaskCreate(Task1, "Task1", 512, nullptr, 3, xHandleTask1);
xTaskCreate(Task2, "Task2", 512, nullptr, 3, xHandleTask2);
cxa_throw_mutex = xSemaphoreCreateRecursiveMutex();
vTaskStartScheduler();
while (true)
{}
return 0;
}
#include <errno.h>
#include <string.h>
#include "FreeRTOS.h"
// Binds newlib memory allocators to that of freeRTOS
// this makes them thread-safe
#if !defined(configUSE_NEWLIB_REENTRANT) || (configUSE_NEWLIB_REENTRANT != 1)
#warning "#define configUSE_NEWLIB_REENTRANT 1 // Required for thread-safety of newlib sprintf, dtoa, strtok, etc..."
#endif
void* sbrk(int incr)
{
// Newlib standard heap usage banned
// Instead newlib should automatically use the overriden malloc etc... functions below
configASSERT(false);
errno = ENOMEM;
return (char*)-1;
}
void* _sbrk(int incr)
{
return sbrk(incr);
}
void* _sbrk_r(struct _reent* r, int incr)
{
return _sbrk(incr);
}
void free(void* ptr)
{
return vPortFree(ptr);
}
void _free_r(struct _reent* r, void* ptr)
{
return free(ptr);
}
void* malloc(size_t size)
{
return pvPortMalloc(size);
}
void* _malloc_r(struct _reent* r, size_t size)
{
return malloc(size);
}
void* realloc(void* ptr, size_t size)
{
void* mem;
mem = malloc(size);
if (mem != NULL) {
memcpy(mem, ptr, size);
free(ptr);
}
return mem;
}
void* _realloc_r(struct _reent* r, void* ptr, size_t size)
{
return realloc(ptr, size);
}
void* calloc(size_t nitems, size_t size)
{
void* mem;
size_t bytes = nitems * size;
mem = malloc(bytes);
if (mem != NULL)
memset(mem, 0, bytes);
return mem;
}
void* _calloc_r(struct _reent* r, size_t nitems, size_t size)
{
return calloc(nitems, size);
}
void* memalign(size_t alignment, size_t size)
{
configASSERT(false); // Not implemented
return NULL;
}
void* _memalign_r(struct _reent* r, size_t alignment, size_t size)
{
return memalign(alignment, size);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment