freertos: vPortCPUReleaseMutex() no longer returns a value

Unlocking a never-locked mutex is an assertion failure in debug mode.

In release mode, this further improves performance:
No-Contention ->  153 cycles
Recursion No-Contention -> 138 cycles
Contention -> 378 cycles
This commit is contained in:
Angus Gratton
2017-02-16 16:03:02 +11:00
committed by Angus Gratton
parent 4d42b2d100
commit db58a2732b
2 changed files with 29 additions and 29 deletions

View File

@@ -127,7 +127,7 @@ typedef unsigned portBASE_TYPE UBaseType_t;
typedef struct { typedef struct {
volatile uint32_t owner; uint32_t owner;
uint32_t count; uint32_t count;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn; const char *lastLockedFn;
@@ -211,9 +211,9 @@ void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line );
void vTaskExitCritical( portMUX_TYPE *mux ); void vTaskExitCritical( portMUX_TYPE *mux );
void vTaskEnterCritical( portMUX_TYPE *mux ); void vTaskEnterCritical( portMUX_TYPE *mux );
void vPortCPUAcquireMutex(portMUX_TYPE *mux); void vPortCPUAcquireMutex(portMUX_TYPE *mux);
portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux); void vPortCPUReleaseMutex(portMUX_TYPE *mux);
void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux); void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux);
portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux); void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux);
#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) #define portENTER_CRITICAL(mux) vTaskEnterCritical(mux)
#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) #define portEXIT_CRITICAL(mux) vTaskExitCritical(mux)

View File

@@ -308,6 +308,9 @@ void vPortCPUInitializeMutex(portMUX_TYPE *mux) {
} }
/*
* For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long.
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *fnName, int line) { void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *fnName, int line) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED(); unsigned int irqStatus = portENTER_CRITICAL_NESTED();
@@ -325,9 +328,6 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux) {
/* XOR one core ID with this value to get the other core ID */ /* XOR one core ID with this value to get the other core ID */
#define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP) #define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP)
/*
* For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long.
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) {
#else #else
@@ -372,12 +372,14 @@ void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux) {
#endif #endif
} while (res == otherCoreID); } while (res == otherCoreID);
assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption */ assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption or uninitialized mux */
assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */ assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */
assert(mux->count < 0xFF); /* Bad count value implies memory corruption */
/* now we own it, we can increment the refcount */ /* now we own it, we can increment the refcount */
mux->count++; mux->count++;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if (res==portMUX_FREE_VAL) { //initial lock if (res==portMUX_FREE_VAL) { //initial lock
mux->lastLockedFn=fnName; mux->lastLockedFn=fnName;
@@ -390,33 +392,31 @@ void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux) {
#endif #endif
} }
/*
* For kernel use: Release a per-CPU mux
*
* Mux must be already locked by this core
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *fnName, int line) { void vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *fnName, int line) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED(); unsigned int irqStatus = portENTER_CRITICAL_NESTED();
portBASE_TYPE res = vPortCPUReleaseMutexIntsDisabled(mux, fnName, line); vPortCPUReleaseMutexIntsDisabled(mux, fnName, line);
portEXIT_CRITICAL_NESTED(irqStatus); portEXIT_CRITICAL_NESTED(irqStatus);
return res;
} }
#else #else
portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux) { void vPortCPUReleaseMutex(portMUX_TYPE *mux) {
unsigned int irqStatus = portENTER_CRITICAL_NESTED(); unsigned int irqStatus = portENTER_CRITICAL_NESTED();
portBASE_TYPE res = vPortCPUReleaseMutexIntsDisabled(mux); vPortCPUReleaseMutexIntsDisabled(mux);
portEXIT_CRITICAL_NESTED(irqStatus); portEXIT_CRITICAL_NESTED(irqStatus);
return res;
} }
#endif #endif
/*
* For kernel use: Release a per-CPU mux. Returns true if everything is OK, false if mux
* was already unlocked or is locked by a different core.
*/
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) {
#else #else
portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) { void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) {
#endif #endif
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
portBASE_TYPE res;
portBASE_TYPE coreID; portBASE_TYPE coreID;
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
const char *lastLockedFn=mux->lastLockedFn; const char *lastLockedFn=mux->lastLockedFn;
@@ -425,20 +425,25 @@ portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) {
mux->lastLockedLine=line; mux->lastLockedLine=line;
uint32_t owner = mux->owner; uint32_t owner = mux->owner;
if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) {
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is uninitialized (0x%x)!\n", mux, mux->owner); ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner);
} }
#endif #endif
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG)
RSR(PRID, coreID); RSR(PRID, coreID);
res = (coreID == mux->owner); #endif
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
if (!res) { if (coreID != mux->owner) {
ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux); ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux);
ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line); ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line);
} }
#endif #endif
assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt
assert(mux->count > 0); // Indicates memory corruption
assert(mux->count < 0x100); // Indicates memory corruption
mux->count--; mux->count--;
if(mux->count == 0) { if(mux->count == 0) {
mux->owner = portMUX_FREE_VAL; mux->owner = portMUX_FREE_VAL;
@@ -448,12 +453,7 @@ portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) {
ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line); ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line);
} }
#endif #endif
#endif //!CONFIG_FREERTOS_UNICORE
return res;
#else //!CONFIG_FREERTOS_UNICORE
return 0;
#endif
} }
#if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG #if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG