mirror of https://github.com/ARMmbed/mbed-os.git
Add RTX API to enumerate running threads
Add the functions osThreadsEnumStart, osThreadEnumNext and osThreadEnumFree to allow enumeration of running threads. Protect thread creation, thread exit and thread termination with a mutex so threads are not created or destroyed while an enumeration is ongoing.pull/2642/head
parent
e9d0fbd178
commit
ad24b7d982
|
|
@ -160,6 +160,7 @@ used throughout the whole project.
|
|||
#define osFeature_Semaphore 65535 ///< maximum count for \ref osSemaphoreCreate function
|
||||
#define osFeature_Wait 0 ///< osWait function: 1=available, 0=not available
|
||||
#define osFeature_SysTick 1 ///< osKernelSysTick functions: 1=available, 0=not available
|
||||
#define osFeature_ThreadEnum 1 ///< Thread enumeration available
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
|
||||
|
|
@ -261,6 +262,8 @@ typedef struct os_messageQ_cb *osMessageQId;
|
|||
/// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
|
||||
typedef struct os_mailQ_cb *osMailQId;
|
||||
|
||||
/// Thread enumeration ID identifies the enumeration (pointer to a thread enumeration control block).
|
||||
typedef uint32_t *osThreadEnumId;
|
||||
|
||||
/// Thread Definition structure contains startup information of a thread.
|
||||
/// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
|
||||
|
|
@ -823,6 +826,26 @@ osStatus osMailFree (osMailQId queue_id, void *mail);
|
|||
#endif // Mail Queues available
|
||||
|
||||
|
||||
// ==== Thread Enumeration Functions ====
|
||||
|
||||
#if (defined (osFeature_ThreadEnum) && (osFeature_ThreadEnum != 0)) // Thread enumeration available
|
||||
|
||||
/// Start a thread enumeration.
|
||||
/// \return an enumeration ID or NULL on error.
|
||||
osThreadEnumId osThreadsEnumStart(void);
|
||||
|
||||
/// Get the next task ID in the enumeration.
|
||||
/// \return a thread ID or NULL on if the end of the enumeration has been reached.
|
||||
osThreadId osThreadEnumNext(osThreadEnumId enum_id);
|
||||
|
||||
/// Free the enumeration structure.
|
||||
/// \param[in] enum_id pointer to the enumeration ID that was obtained with \ref osThreadsEnumStart.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus osThreadEnumFree(osThreadEnumId enum_id);
|
||||
|
||||
#endif // Thread Enumeration available
|
||||
|
||||
|
||||
// ==== RTX Extensions ====
|
||||
|
||||
/// os_suspend: http://www.keil.com/support/man/docs/rlarm/rlarm_os_suspend.htm
|
||||
|
|
|
|||
|
|
@ -479,6 +479,9 @@ 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
|
||||
osMutexDef(osThreadMutex);
|
||||
osMutexId osMutexId_osThreadMutex;
|
||||
|
||||
// ==== Helper Functions ====
|
||||
|
||||
|
|
@ -596,6 +599,8 @@ osStatus svcKernelInitialize (void) {
|
|||
// Create OS Timers resources (Message Queue & Thread)
|
||||
osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
|
||||
osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
|
||||
// Initialize thread mutex
|
||||
osMutexId_osThreadMutex = osMutexCreate(osMutex(osThreadMutex));
|
||||
}
|
||||
|
||||
sysThreadError(osOK);
|
||||
|
|
@ -856,7 +861,12 @@ osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
|
|||
// Privileged and not running
|
||||
return svcThreadCreate(thread_def, argument);
|
||||
} else {
|
||||
return __svcThreadCreate(thread_def, argument);
|
||||
osThreadId id;
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
// Thread mutex must be held when a thread is created or terminated
|
||||
id = __svcThreadCreate(thread_def, argument);
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -868,8 +878,13 @@ osThreadId osThreadGetId (void) {
|
|||
|
||||
/// Terminate execution of a thread and remove it from ActiveThreads
|
||||
osStatus osThreadTerminate (osThreadId thread_id) {
|
||||
osStatus status;
|
||||
if (__exceptional_mode()) return osErrorISR; // Not allowed in ISR
|
||||
return __svcThreadTerminate(thread_id);
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
// Thread mutex must be held when a thread is created or terminated
|
||||
status = __svcThreadTerminate(thread_id);
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Pass control to next thread that is in state READY
|
||||
|
|
@ -893,6 +908,10 @@ osPriority osThreadGetPriority (osThreadId thread_id) {
|
|||
/// INTERNAL - Not Public
|
||||
/// Auto Terminate Thread on exit (used implicitly when thread exists)
|
||||
__NO_RETURN void osThreadExit (void) {
|
||||
// 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());
|
||||
for (;;); // Should never come here
|
||||
}
|
||||
|
|
@ -911,6 +930,38 @@ uint8_t osThreadGetState (osThreadId thread_id) {
|
|||
}
|
||||
#endif
|
||||
|
||||
osThreadEnumId osThreadsEnumStart() {
|
||||
static uint32_t thread_enum_index;
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
thread_enum_index = 0;
|
||||
return &thread_enum_index;
|
||||
}
|
||||
|
||||
osThreadId osThreadEnumNext(osThreadEnumId enum_id) {
|
||||
uint32_t i;
|
||||
osThreadId id = NULL;
|
||||
uint32_t *index = (uint32_t*)enum_id;
|
||||
for (i = *index; i < os_maxtaskrun; i++) {
|
||||
if (os_active_TCB[i] != NULL) {
|
||||
id = (osThreadId)os_active_TCB[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == os_maxtaskrun) {
|
||||
// Include the idle task at the end of the enumeration
|
||||
id = &os_idle_TCB;
|
||||
}
|
||||
*index = i + 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
osStatus osThreadEnumFree(osThreadEnumId enum_id) {
|
||||
uint32_t *index = (uint32_t*)enum_id;
|
||||
*index = 0;
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return osOK;
|
||||
}
|
||||
|
||||
// ==== Generic Wait Functions ====
|
||||
|
||||
// Generic Wait Service Calls declarations
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
#define osFeature_Semaphore 65535 ///< Maximum count for \ref osSemaphoreCreate function
|
||||
#define osFeature_Wait 0 ///< osWait not available
|
||||
#define osFeature_SysTick 1 ///< osKernelSysTick functions available
|
||||
#define osFeature_ThreadEnum 1 ///< Thread enumeration available
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
#define os_InRegs __value_in_regs // Compiler specific: force struct in registers
|
||||
|
|
@ -188,6 +189,8 @@ typedef struct os_messageQ_cb *osMessageQId;
|
|||
/// Mail ID identifies the mail queue (pointer to a mail queue control block).
|
||||
typedef struct os_mailQ_cb *osMailQId;
|
||||
|
||||
/// Thread enumeration ID identifies the enumeration (pointer to a thread enumeration control block).
|
||||
typedef uint32_t *osThreadEnumId;
|
||||
|
||||
/// Thread Definition structure contains startup information of a thread.
|
||||
typedef struct os_thread_def {
|
||||
|
|
@ -680,6 +683,26 @@ osStatus osMailFree (osMailQId queue_id, void *mail);
|
|||
#endif // Mail Queues available
|
||||
|
||||
|
||||
// ==== Thread Enumeration Functions ====
|
||||
|
||||
#if (defined (osFeature_ThreadEnum) && (osFeature_ThreadEnum != 0)) // Thread enumeration available
|
||||
|
||||
/// Start a thread enumeration.
|
||||
/// \return an enumeration ID or NULL on error.
|
||||
osThreadEnumId osThreadsEnumStart(void);
|
||||
|
||||
/// Get the next task ID in the enumeration.
|
||||
/// \return a thread ID or NULL on if the end of the enumeration has been reached.
|
||||
osThreadId osThreadEnumNext(osThreadEnumId enum_id);
|
||||
|
||||
/// Free the enumeration structure.
|
||||
/// \param[in] enum_id pointer to the enumeration ID that was obtained with \ref osThreadsEnumStart.
|
||||
/// \return status code that indicates the execution status of the function.
|
||||
osStatus osThreadEnumFree(osThreadEnumId enum_id);
|
||||
|
||||
#endif // Thread Enumeration available
|
||||
|
||||
|
||||
// ==== RTX Extensions ====
|
||||
|
||||
/// Suspend the RTX task scheduler.
|
||||
|
|
|
|||
|
|
@ -392,6 +392,9 @@ extern osThreadId osThreadId_osTimerThread;
|
|||
extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
|
||||
extern osMessageQId osMessageQId_osTimerMessageQ;
|
||||
|
||||
// Thread creation and destruction mutex
|
||||
osMutexDef(osThreadMutex);
|
||||
osMutexId osMutexId_osThreadMutex;
|
||||
|
||||
// ==== Helper Functions ====
|
||||
|
||||
|
|
@ -490,6 +493,8 @@ osStatus svcKernelInitialize (void) {
|
|||
// Create OS Timers resources (Message Queue & Thread)
|
||||
osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
|
||||
osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL, NULL);
|
||||
// Initialize thread mutex
|
||||
osMutexId_osThreadMutex = osMutexCreate(osMutex(osThreadMutex));
|
||||
}
|
||||
|
||||
sysThreadError(osOK);
|
||||
|
|
@ -806,7 +811,12 @@ osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argumen
|
|||
// Privileged and not running
|
||||
return svcThreadCreate(thread_def, argument, context);
|
||||
} else {
|
||||
return __svcThreadCreate(thread_def, argument, context);
|
||||
osThreadId id;
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
// Thread mutex must be held when a thread is created or terminated
|
||||
id = __svcThreadCreate(thread_def, argument, context);
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -820,10 +830,15 @@ osThreadId osThreadGetId (void) {
|
|||
|
||||
/// Terminate execution of a thread and remove it from ActiveThreads
|
||||
osStatus osThreadTerminate (osThreadId thread_id) {
|
||||
osStatus status;
|
||||
if (__get_IPSR() != 0U) {
|
||||
return osErrorISR; // Not allowed in ISR
|
||||
}
|
||||
return __svcThreadTerminate(thread_id);
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
// Thread mutex must be held when a thread is created or terminated
|
||||
status = __svcThreadTerminate(thread_id);
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return status;
|
||||
}
|
||||
|
||||
/// Pass control to next thread that is in state READY
|
||||
|
|
@ -852,8 +867,12 @@ osPriority osThreadGetPriority (osThreadId thread_id) {
|
|||
|
||||
/// INTERNAL - Not Public
|
||||
/// Auto Terminate Thread on exit (used implicitly when thread exists)
|
||||
__NO_RETURN void osThreadExit (void) {
|
||||
__svcThreadTerminate(__svcThreadGetId());
|
||||
__NO_RETURN void osThreadExit (void) {
|
||||
// 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());
|
||||
for (;;); // Should never come here
|
||||
}
|
||||
|
||||
|
|
@ -871,6 +890,38 @@ uint8_t osThreadGetState (osThreadId thread_id) {
|
|||
}
|
||||
#endif
|
||||
|
||||
osThreadEnumId osThreadsEnumStart() {
|
||||
static uint32_t thread_enum_index;
|
||||
osMutexWait(osMutexId_osThreadMutex, osWaitForever);
|
||||
thread_enum_index = 0;
|
||||
return &thread_enum_index;
|
||||
}
|
||||
|
||||
osThreadId osThreadEnumNext(osThreadEnumId enum_id) {
|
||||
uint32_t i;
|
||||
osThreadId id = NULL;
|
||||
uint32_t *index = (uint32_t*)enum_id;
|
||||
for (i = *index; i < os_maxtaskrun; i++) {
|
||||
if (os_active_TCB[i] != NULL) {
|
||||
id = (osThreadId)os_active_TCB[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == os_maxtaskrun) {
|
||||
// Include the idle task at the end of the enumeration
|
||||
id = &os_idle_TCB;
|
||||
}
|
||||
*index = i + 1;
|
||||
return id;
|
||||
}
|
||||
|
||||
osStatus osThreadEnumFree(osThreadEnumId enum_id) {
|
||||
uint32_t *index = (uint32_t*)enum_id;
|
||||
*index = 0;
|
||||
osMutexRelease(osMutexId_osThreadMutex);
|
||||
return osOK;
|
||||
}
|
||||
|
||||
// ==== Generic Wait Functions ====
|
||||
|
||||
// Generic Wait Service Calls declarations
|
||||
|
|
|
|||
Loading…
Reference in New Issue