From 6fd9154d75a7fc618391acfea16c8218758427bd Mon Sep 17 00:00:00 2001 From: Russ Butler Date: Wed, 7 Sep 2016 00:19:48 -0500 Subject: [PATCH] Add task terminate hook Add an RTX hook which gets called when a thread terminates. Add the function Thread::attach_terminate_hook() to allow users to attach a hook to this event at runtime. --- rtos/rtos/Thread.cpp | 13 +++++++++++++ rtos/rtos/Thread.h | 5 +++++ rtos/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c | 8 ++++++++ rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c | 9 +++++++-- rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c | 9 +++++++++ rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c | 9 +++++++-- 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/rtos/rtos/Thread.cpp b/rtos/rtos/Thread.cpp index 91e80afe2b..80eae63bc3 100644 --- a/rtos/rtos/Thread.cpp +++ b/rtos/rtos/Thread.cpp @@ -30,6 +30,15 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); + +static void (*terminate_hook)(osThreadId id) = 0; +extern "C" void thread_terminate_hook(osThreadId id) +{ + if (terminate_hook != (void (*)(osThreadId))NULL) { + terminate_hook(id); + } +} + namespace rtos { void Thread::constructor(osPriority priority, @@ -336,6 +345,10 @@ void Thread::attach_idle_hook(void (*fptr)(void)) { rtos_attach_idle_hook(fptr); } +void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) { + terminate_hook = fptr; +} + Thread::~Thread() { // terminate is thread safe terminate(); diff --git a/rtos/rtos/Thread.h b/rtos/rtos/Thread.h index f2b5cb9300..5c6114f355 100644 --- a/rtos/rtos/Thread.h +++ b/rtos/rtos/Thread.h @@ -320,6 +320,11 @@ public: */ static void attach_idle_hook(void (*fptr)(void)); + /** Attach a function to be called when a task is killed + @param fptr pointer to the function to be called + */ + static void attach_terminate_hook(void (*fptr)(osThreadId id)); + virtual ~Thread(); private: diff --git a/rtos/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c b/rtos/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c index 83b5820e09..7ef9f6ca05 100644 --- a/rtos/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c +++ b/rtos/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c @@ -320,6 +320,14 @@ void os_error (uint32_t err_code) { for (;;); } +/*---------------------------------------------------------------------------- + * RTX Hooks + *---------------------------------------------------------------------------*/ +extern void thread_terminate_hook(osThreadId id); + +void sysThreadTerminate(osThreadId id) { + thread_terminate_hook(id); +} /*---------------------------------------------------------------------------- * RTX Configuration Functions diff --git a/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c b/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c index 7f71b8e0ff..9d1eb2645d 100644 --- a/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c +++ b/rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c @@ -479,9 +479,10 @@ extern osMessageQId osMessageQId_osTimerMessageQ; extern U32 IRQNestLevel; /* Indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR. */ -// Thread creation and destruction mutex +// Thread creation and destruction osMutexDef(osThreadMutex); osMutexId osMutexId_osThreadMutex; +void sysThreadTerminate(osThreadId id); // ==== Helper Functions ==== @@ -956,6 +957,7 @@ osStatus osThreadTerminate (osThreadId thread_id) { osStatus status; if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR osMutexWait(osMutexId_osThreadMutex, osWaitForever); + sysThreadTerminate(thread_id); // Thread mutex must be held when a thread is created or terminated status = __svcThreadTerminate(thread_id); osMutexRelease(osMutexId_osThreadMutex); @@ -983,11 +985,14 @@ osPriority osThreadGetPriority (osThreadId thread_id) { /// INTERNAL - Not Public /// Auto Terminate Thread on exit (used implicitly when thread exists) __NO_RETURN void osThreadExit (void) { + osThreadId id; // Thread mutex must be held when a thread is created or terminated // Note - the mutex will be released automatically by the os when // the thread is terminated osMutexWait(osMutexId_osThreadMutex, osWaitForever); - __svcThreadTerminate(__svcThreadGetId()); + id = __svcThreadGetId(); + sysThreadTerminate(id); + __svcThreadTerminate(id); for (;;); // Should never come here } diff --git a/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c b/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c index 562f1addd0..2c548ce31f 100755 --- a/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c +++ b/rtos/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c @@ -407,6 +407,15 @@ void sysThreadError(osStatus status) { } } +/*---------------------------------------------------------------------------- + * RTX Hooks + *---------------------------------------------------------------------------*/ +extern void thread_terminate_hook(osThreadId id); + +void sysThreadTerminate(osThreadId id) { + thread_terminate_hook(id); +} + /*---------------------------------------------------------------------------- * RTX Configuration Functions *---------------------------------------------------------------------------*/ diff --git a/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c b/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c index 092539bb63..c857153e3b 100644 --- a/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c +++ b/rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c @@ -392,9 +392,10 @@ extern osThreadId osThreadId_osTimerThread; extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ; extern osMessageQId osMessageQId_osTimerMessageQ; -// Thread creation and destruction mutex +// Thread creation and destruction osMutexDef(osThreadMutex); osMutexId osMutexId_osThreadMutex; +void sysThreadTerminate(osThreadId id); // ==== Helper Functions ==== @@ -897,6 +898,7 @@ osStatus osThreadTerminate (osThreadId thread_id) { return osErrorISR; // Not allowed in ISR } osMutexWait(osMutexId_osThreadMutex, osWaitForever); + sysThreadTerminate(thread_id); // Thread mutex must be held when a thread is created or terminated status = __svcThreadTerminate(thread_id); osMutexRelease(osMutexId_osThreadMutex); @@ -930,11 +932,14 @@ osPriority osThreadGetPriority (osThreadId thread_id) { /// INTERNAL - Not Public /// Auto Terminate Thread on exit (used implicitly when thread exists) __NO_RETURN void osThreadExit (void) { + osThreadId id; // Thread mutex must be held when a thread is created or terminated // Note - the mutex will be released automatically by the os when // the thread is terminated osMutexWait(osMutexId_osThreadMutex, osWaitForever); - __svcThreadTerminate(__svcThreadGetId()); + id = __svcThreadGetId(); + sysThreadTerminate(id); + __svcThreadTerminate(id); for (;;); // Should never come here }