mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-02 04:04:31 +02:00
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:
committed by
Angus Gratton
parent
4d42b2d100
commit
db58a2732b
@@ -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)
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user