Skip to content

Commit c319296

Browse files
committed
Add RTX API to report stack usage
Add the function osThreadGetInfo to allow various Thread information to be queried. This includes stack size and maximum stack usage among other things. Note - for Cortex-A devices the worst case stack usage is not available.
1 parent ad24b7d commit c319296

File tree

7 files changed

+195
-0
lines changed

7 files changed

+195
-0
lines changed

rtos/rtx/TARGET_CORTEX_A/cmsis_os.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,16 @@ typedef enum {
224224
osTimerPeriodic = 1 ///< repeating timer
225225
} os_timer_type;
226226

227+
typedef enum {
228+
osThreadInfoState,
229+
osThreadInfoStackSize,
230+
osThreadInfoStackMax,
231+
osThreadInfoEntry,
232+
osThreadInfoArg,
233+
234+
osThreadInfo_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
235+
} osThreadInfo;
236+
227237
/// Entry point of a thread.
228238
/// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
229239
typedef void (*os_pthread) (void const *argument);
@@ -451,6 +461,13 @@ osPriority osThreadGetPriority (osThreadId thread_id);
451461
uint8_t osThreadGetState (osThreadId thread_id);
452462
#endif
453463

464+
/// Get into from an active thread.
465+
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
466+
/// \param[in] info information to read.
467+
/// \return current state of the thread function.
468+
/// \return requested info that includes the status code.
469+
os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info);
470+
454471
// ==== Generic Wait Functions ====
455472

456473
/// Wait for Timeout (Time Delay).

rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,7 @@ SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET
713713
SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
714714
SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus)
715715
SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority)
716+
SVC_2_3(svcThreadGetInfo, os_InRegs osEvent, osThreadId, osThreadInfo, RET_osEvent)
716717

717718
// Thread Service Calls
718719

@@ -851,6 +852,80 @@ osPriority svcThreadGetPriority (osThreadId thread_id) {
851852
return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
852853
}
853854

855+
/// Get info from an active thread
856+
os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) {
857+
P_TCB ptcb;
858+
osEvent ret;
859+
ret.status = osOK;
860+
861+
ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
862+
if (ptcb == NULL) {
863+
ret.status = osErrorValue;
864+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
865+
osEvent_ret_status;
866+
return;
867+
#else
868+
return osEvent_ret_status;
869+
#endif
870+
}
871+
872+
if (osThreadInfoStackSize == info) {
873+
uint32_t size;
874+
size = ptcb->priv_stack;
875+
if (0 == size) {
876+
// This is an OS task - always a fixed size
877+
size = os_stackinfo & 0x3FFFF;
878+
}
879+
ret.value.v = size;
880+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
881+
osEvent_ret_value;
882+
return;
883+
#else
884+
return osEvent_ret_value;
885+
#endif
886+
}
887+
888+
if (osThreadInfoStackMax == info) {
889+
// Cortex-A RTX does not have stack init so
890+
// the maximum stack usage cannot be obtained.
891+
ret.status = osErrorResource;
892+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
893+
osEvent_ret_status;
894+
return;
895+
#else
896+
return osEvent_ret_status;
897+
#endif
898+
}
899+
900+
if (osThreadInfoEntry == info) {
901+
ret.value.p = (void*)ptcb->ptask;
902+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
903+
osEvent_ret_value;
904+
return;
905+
#else
906+
return osEvent_ret_value;
907+
#endif
908+
}
909+
910+
if (osThreadInfoArg == info) {
911+
ret.value.p = (void*)ptcb->argv;
912+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
913+
osEvent_ret_value;
914+
return;
915+
#else
916+
return osEvent_ret_value;
917+
#endif
918+
}
919+
920+
// Unsupported option so return error
921+
ret.status = osErrorParameter;
922+
#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
923+
osEvent_ret_status;
924+
return;
925+
#else
926+
return osEvent_ret_status;
927+
#endif
928+
}
854929

855930
// Thread Public API
856931

@@ -930,6 +1005,16 @@ uint8_t osThreadGetState (osThreadId thread_id) {
9301005
}
9311006
#endif
9321007

1008+
/// Get the requested info from the specified active thread
1009+
os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info) {
1010+
osEvent ret;
1011+
if (__exceptional_mode()) {
1012+
ret.status = osErrorISR;
1013+
return ret; // Not allowed in ISR
1014+
}
1015+
return __svcThreadGetInfo(thread_id, info);
1016+
}
1017+
9331018
osThreadEnumId osThreadsEnumStart() {
9341019
static uint32_t thread_enum_index;
9351020
osMutexWait(osMutexId_osThreadMutex, osWaitForever);

rtos/rtx/TARGET_CORTEX_A/rt_TypeDef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ typedef struct OS_TCB {
8585

8686
/* Task entry point used for uVision debugger */
8787
FUNCP ptask; /* Task entry address */
88+
void *argv; /* Task argument */
8889
} *P_TCB;
8990
#define TCB_TID 3 /* 'task id' offset */
9091
#define TCB_STACKF 37 /* 'stack_frame' offset */

rtos/rtx/TARGET_CORTEX_M/cmsis_os.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,16 @@ typedef enum {
160160
osTimerPeriodic = 1 ///< repeating timer
161161
} os_timer_type;
162162

163+
typedef enum {
164+
osThreadInfoState,
165+
osThreadInfoStackSize,
166+
osThreadInfoStackMax,
167+
osThreadInfoEntry,
168+
osThreadInfoArg,
169+
170+
osThreadInfo_reserved = 0x7FFFFFFF ///< prevent from enum down-size compiler optimization.
171+
} osThreadInfo;
172+
163173
/// Entry point of a thread.
164174
typedef void (*os_pthread) (void const *argument);
165175

@@ -361,6 +371,13 @@ osPriority osThreadGetPriority (osThreadId thread_id);
361371
uint8_t osThreadGetState (osThreadId thread_id);
362372
#endif
363373

374+
/// Get into from an active thread.
375+
/// \param[in] thread_id thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
376+
/// \param[in] info information to read.
377+
/// \return current state of the thread function.
378+
/// \return requested info that includes the status code.
379+
os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info);
380+
364381
// ==== Generic Wait Functions ====
365382

366383
/// Wait for Timeout (Time Delay).

rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET
637637
SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
638638
SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus)
639639
SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority)
640+
SVC_2_3(svcThreadGetInfo, os_InRegs osEvent, osThreadId, osThreadInfo, RET_osEvent)
640641

641642
// Thread Service Calls
642643

@@ -796,6 +797,67 @@ osPriority svcThreadGetPriority (osThreadId thread_id) {
796797
return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
797798
}
798799

800+
/// Get info from an active thread
801+
os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) {
802+
P_TCB ptcb;
803+
osEvent ret;
804+
ret.status = osOK;
805+
806+
ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
807+
if (ptcb == NULL) {
808+
ret.status = osErrorValue;
809+
return osEvent_ret_status;
810+
}
811+
812+
if (osThreadInfoStackSize == info) {
813+
uint32_t size;
814+
size = ptcb->priv_stack;
815+
if (0 == size) {
816+
// This is an OS task - always a fixed size
817+
size = os_stackinfo & 0x3FFFF;
818+
}
819+
ret.value.v = size;
820+
return osEvent_ret_value;
821+
}
822+
823+
if (osThreadInfoStackMax == info) {
824+
uint32_t i;
825+
uint32_t *stack_ptr;
826+
uint32_t stack_size;
827+
if (!(os_stackinfo & (1 << 28))) {
828+
// Stack init must be turned on for max stack usage
829+
ret.status = osErrorResource;
830+
return osEvent_ret_status;
831+
}
832+
stack_ptr = (uint32_t*)ptcb->stack;
833+
stack_size = ptcb->priv_stack;
834+
if (0 == stack_size) {
835+
// This is an OS task - always a fixed size
836+
stack_size = os_stackinfo & 0x3FFFF;
837+
}
838+
for (i = 1; i <stack_size / 4; i++) {
839+
if (stack_ptr[i] != MAGIC_PATTERN) {
840+
break;
841+
}
842+
}
843+
ret.value.v = stack_size - i * 4;
844+
return osEvent_ret_value;
845+
}
846+
847+
if (osThreadInfoEntry == info) {
848+
ret.value.p = (void*)ptcb->ptask;
849+
return osEvent_ret_value;
850+
}
851+
852+
if (osThreadInfoArg == info) {
853+
ret.value.p = (void*)ptcb->argv;
854+
return osEvent_ret_value;
855+
}
856+
857+
// Unsupported option so return error
858+
ret.status = osErrorParameter;
859+
return osEvent_ret_status;
860+
}
799861

800862
// Thread Public API
801863

@@ -890,6 +952,17 @@ uint8_t osThreadGetState (osThreadId thread_id) {
890952
}
891953
#endif
892954

955+
/// Get the requested info from the specified active thread
956+
os_InRegs osEvent osThreadGetInfo(osThreadId thread_id, osThreadInfo info) {
957+
osEvent ret;
958+
959+
if (__get_IPSR() != 0U) { // Not allowed in ISR
960+
ret.status = osErrorISR;
961+
return ret;
962+
}
963+
return __svcThreadGetInfo(thread_id, info);
964+
}
965+
893966
osThreadEnumId osThreadsEnumStart() {
894967
static uint32_t thread_enum_index;
895968
osMutexWait(osMutexId_osThreadMutex, osWaitForever);

rtos/rtx/TARGET_CORTEX_M/rt_Task.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) {
247247
task_context->task_id = (U8)i;
248248
/* Pass parameter 'argv' to 'rt_init_context' */
249249
task_context->msg = argv;
250+
task_context->argv = argv;
250251
/* For 'size == 0' system allocates the user stack from the memory pool. */
251252
rt_init_context (task_context, (U8)(prio_stksz & 0xFFU), task);
252253

rtos/rtx/TARGET_CORTEX_M/rt_TypeDef.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ typedef struct OS_TCB {
7979

8080
/* Task entry point used for uVision debugger */
8181
FUNCP ptask; /* Task entry address */
82+
void *argv; /* Task argument */
8283
void *context; /* Pointer to thread context */
8384
} *P_TCB;
8485
#define TCB_STACKF 37 /* 'stack_frame' offset */

0 commit comments

Comments
 (0)