Maintain legacy RTOS behavior before mbed-5
Fork of mbed-rtos by
Diff: rtx/TARGET_CORTEX_A/rt_CMSIS.c
- Revision:
- 123:58563e6cba1e
- Parent:
- 117:4c105b8d7cae
--- a/rtx/TARGET_CORTEX_A/rt_CMSIS.c Wed Nov 09 12:22:14 2016 -0600 +++ b/rtx/TARGET_CORTEX_A/rt_CMSIS.c Mon Nov 14 17:14:42 2016 -0600 @@ -479,6 +479,10 @@ extern U32 IRQNestLevel; /* Indicates whether inside an ISR, and the depth of nesting. 0 = not in ISR. */ +// Thread creation and destruction +osMutexDef(osThreadMutex); +osMutexId osMutexId_osThreadMutex; +void sysThreadTerminate(osThreadId id); // ==== Helper Functions ==== @@ -539,6 +543,11 @@ } static __inline char __exceptional_mode(void) { + // Interrupts disabled + if (__get_CPSR() & 0x80) { + return 1; + } + switch(__get_mode()) { case MODE_USR: case MODE_SYS: @@ -596,6 +605,8 @@ // 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); @@ -708,6 +719,7 @@ SVC_0_1(svcThreadYield, osStatus, RET_osStatus) SVC_2_1(svcThreadSetPriority, osStatus, osThreadId, osPriority, RET_osStatus) SVC_1_1(svcThreadGetPriority, osPriority, osThreadId, RET_osPriority) +SVC_2_3(svcThreadGetInfo, os_InRegs osEvent, osThreadId, osThreadInfo, RET_osEvent) // Thread Service Calls @@ -846,6 +858,80 @@ return (osPriority)(ptcb->prio - 1 + osPriorityIdle); } +/// Get info from an active thread +os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) { + P_TCB ptcb; + osEvent ret; + ret.status = osOK; + + ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer + if (ptcb == NULL) { + ret.status = osErrorValue; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif + } + + if (osThreadInfoStackSize == info) { + uint32_t size; + size = ptcb->priv_stack; + if (0 == size) { + // This is an OS task - always a fixed size + size = os_stackinfo & 0x3FFFF; + } + ret.value.v = size; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + if (osThreadInfoStackMax == info) { + // Cortex-A RTX does not have stack init so + // the maximum stack usage cannot be obtained. + ret.status = osErrorResource; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif + } + + if (osThreadInfoEntry == info) { + ret.value.p = (void*)ptcb->ptask; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + if (osThreadInfoArg == info) { + ret.value.p = (void*)ptcb->argv; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_value; + return; +#else + return osEvent_ret_value; +#endif + } + + // Unsupported option so return error + ret.status = osErrorParameter; +#if defined (__GNUC__) && defined (__ARM_PCS_VFP) + osEvent_ret_status; + return; +#else + return osEvent_ret_status; +#endif +} // Thread Public API @@ -856,7 +942,12 @@ // 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 +959,14 @@ /// 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); + sysThreadTerminate(thread_id); + // 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,7 +990,14 @@ /// INTERNAL - Not Public /// Auto Terminate Thread on exit (used implicitly when thread exists) __NO_RETURN void osThreadExit (void) { - __svcThreadTerminate(__svcThreadGetId()); + 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); + id = __svcThreadGetId(); + sysThreadTerminate(id); + __svcThreadTerminate(id); for (;;); // Should never come here } @@ -911,6 +1015,48 @@ } #endif +/// Get the requested info from the specified active thread +os_InRegs osEvent _osThreadGetInfo(osThreadId thread_id, osThreadInfo info) { + osEvent ret; + if (__exceptional_mode()) { + ret.status = osErrorISR; + return ret; // Not allowed in ISR + } + return __svcThreadGetInfo(thread_id, info); +} + +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