mirror of
https://github.com/espressif/esp-idf.git
synced 2025-09-25 17:52:36 +00:00
freertos spinlock/portmux: Reduce spinlocking overhead
Ref TW7117 Microbenchmarks in unit tests: (All numbers in cycles per benchmarked operation): Release mode No lock contention lock/unlock - 301 -> 167 (-45%) Recursive no contention lock/unlock - 289 -> 148 (-49%) Lock contention two CPUs (lock/unlock) 699 -> 400 (-43%) Debug mode No lock contention lock/unlock - 355 -> 203 (-43%) Recursive no contention lock/unlock - 345 -> 188 (-46%) Lock contention two CPUs (lock/unlock) 761 -> 483 (-36%)
This commit is contained in:

committed by
Angus Gratton

parent
f2952de3a5
commit
4d42b2d100
@@ -4111,7 +4111,8 @@ For ESP32 FreeRTOS, vTaskEnterCritical implements both portENTER_CRITICAL and po
|
||||
#endif
|
||||
{
|
||||
BaseType_t oldInterruptLevel=0;
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
BaseType_t schedulerRunning = xSchedulerRunning;
|
||||
if( schedulerRunning != pdFALSE )
|
||||
{
|
||||
//Interrupts may already be disabled (because we're doing this recursively) but we can't get the interrupt level after
|
||||
//vPortCPUAquireMutex, because it also may mess with interrupts. Get it here first, then later figure out if we're nesting
|
||||
@@ -4119,26 +4120,27 @@ For ESP32 FreeRTOS, vTaskEnterCritical implements both portENTER_CRITICAL and po
|
||||
oldInterruptLevel=portENTER_CRITICAL_NESTED();
|
||||
}
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
vPortCPUAcquireMutex( mux, function, line );
|
||||
vPortCPUAcquireMutexIntsDisabled( mux, function, line );
|
||||
#else
|
||||
vPortCPUAcquireMutex( mux );
|
||||
vPortCPUAcquireMutexIntsDisabled( mux );
|
||||
#endif
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
if( schedulerRunning != pdFALSE )
|
||||
{
|
||||
( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )++;
|
||||
|
||||
if( xSchedulerRunning != pdFALSE && pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 )
|
||||
TCB_t *tcb = pxCurrentTCB[xPortGetCoreID()];
|
||||
BaseType_t newNesting = tcb->uxCriticalNesting + 1;
|
||||
tcb->uxCriticalNesting = newNesting;
|
||||
if( newNesting == 1 )
|
||||
{
|
||||
//This is the first time we get called. Save original interrupt level.
|
||||
pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState=oldInterruptLevel;
|
||||
tcb->uxOldInterruptState = oldInterruptLevel;
|
||||
}
|
||||
|
||||
/* Original FreeRTOS comment, saved for reference:
|
||||
This is not the interrupt safe version of the enter critical
|
||||
function so assert() if it is being called from an interrupt
|
||||
context. Only API functions that end in "FromISR" can be used in an
|
||||
interrupt. Only assert if the critical nesting count is 1 to
|
||||
interrupt. Only assert if the critical nesting count is 1 to
|
||||
protect against recursive calls if the assert function also uses a
|
||||
critical section. */
|
||||
|
||||
@@ -4149,7 +4151,7 @@ For ESP32 FreeRTOS, vTaskEnterCritical implements both portENTER_CRITICAL and po
|
||||
both from ISR as well as non-ISR code, thus we re-organized
|
||||
vTaskEnterCritical to also work in ISRs. */
|
||||
#if 0
|
||||
if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 )
|
||||
if( newNesting == 1 )
|
||||
{
|
||||
portASSERT_IF_IN_ISR();
|
||||
}
|
||||
@@ -4178,19 +4180,22 @@ For ESP32 FreeRTOS, vTaskExitCritical implements both portEXIT_CRITICAL and port
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
vPortCPUReleaseMutex( mux, function, line );
|
||||
vPortCPUReleaseMutexIntsDisabled( mux, function, line );
|
||||
#else
|
||||
vPortCPUReleaseMutex( mux );
|
||||
vPortCPUReleaseMutexIntsDisabled( mux );
|
||||
#endif
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting > 0U )
|
||||
TCB_t *tcb = pxCurrentTCB[xPortGetCoreID()];
|
||||
BaseType_t nesting = tcb->uxCriticalNesting;
|
||||
if( nesting > 0U )
|
||||
{
|
||||
( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )--;
|
||||
nesting--;
|
||||
tcb->uxCriticalNesting = nesting;
|
||||
|
||||
if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 0U )
|
||||
if( nesting == 0U )
|
||||
{
|
||||
portEXIT_CRITICAL_NESTED(pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState);
|
||||
portEXIT_CRITICAL_NESTED(tcb->uxOldInterruptState);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Reference in New Issue
Block a user