Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: RFC: Enable granular locks for critical sections instead of a single kernel lock #601

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions event_groups.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ typedef struct EventGroupDef_t
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
#endif

portMUX_TYPE xEventGroupLock;
} EventGroup_t;

/*-----------------------------------------------------------*/
Expand Down Expand Up @@ -125,6 +127,9 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */

/* Initialize the event group's spinlock. */
portMUX_INITIALIZE( &pxEventBits->xEventGroupLock );

traceEVENT_GROUP_CREATE( pxEventBits );
}
else
Expand Down Expand Up @@ -176,6 +181,9 @@ static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits,
}
#endif /* configSUPPORT_STATIC_ALLOCATION */

/* Initialize the event group's spinlock. */
portMUX_INITIALIZE( &pxEventBits->xEventGroupLock );

traceEVENT_GROUP_CREATE( pxEventBits );
}
else
Expand Down Expand Up @@ -272,7 +280,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
/* The task timed out, just return the current event bit value. */
taskENTER_CRITICAL();
taskENTER_CRITICAL( &( pxEventBits->xEventGroupLock ) );
{
uxReturn = pxEventBits->uxEventBits;

Expand All @@ -289,7 +297,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL();
taskEXIT_CRITICAL( &( pxEventBits->xEventGroupLock ) );

xTimeoutOccurred = pdTRUE;
}
Expand Down Expand Up @@ -423,7 +431,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,

if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
{
taskENTER_CRITICAL();
taskENTER_CRITICAL( &( pxEventBits->xEventGroupLock ) );
{
/* The task timed out, just return the current event bit value. */
uxReturn = pxEventBits->uxEventBits;
Expand All @@ -448,7 +456,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,

xTimeoutOccurred = pdTRUE;
}
taskEXIT_CRITICAL();
taskEXIT_CRITICAL( &( pxEventBits->xEventGroupLock ) );
}
else
{
Expand Down Expand Up @@ -479,7 +487,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
configASSERT( xEventGroup );
configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );

taskENTER_CRITICAL();
taskENTER_CRITICAL( &( pxEventBits->xEventGroupLock ) );
{
traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear );

Expand All @@ -490,7 +498,7 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
/* Clear the bits. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
taskEXIT_CRITICAL();
taskEXIT_CRITICAL( &( pxEventBits->xEventGroupLock ) );

return uxReturn;
}
Expand Down Expand Up @@ -546,6 +554,12 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
pxList = &( pxEventBits->xTasksWaitingForBits );
pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
vTaskSuspendAll();
#if ( configNUM_CORES > 1 )

/* We are about to traverse a task list which is a kernel data structure.
* Thus we need to call vTaskTakeKernelLock() to take the kernel lock. */
vTaskTakeKernelLock();
#endif /* configNUM_CORES > 1 */
{
traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );

Expand Down Expand Up @@ -617,6 +631,10 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
* bit was set in the control word. */
pxEventBits->uxEventBits &= ~uxBitsToClear;
}
#if ( configNUM_CORES > 1 )
/* Release the previously taken kernel lock. */
vTaskReleaseKernelLock();
#endif /* configNUM_CORES > 1 */
( void ) xTaskResumeAll();

return pxEventBits->uxEventBits;
Expand All @@ -629,6 +647,12 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
const List_t * pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );

vTaskSuspendAll();
#if ( configNUM_CORES > 1 )

/* We are about to traverse a task list which is a kernel data structure.
* Thus we need to call vTaskTakeKernelLock() to take the kernel lock. */
vTaskTakeKernelLock();
#endif /* configNUM_CORES > 1 */
{
traceEVENT_GROUP_DELETE( xEventGroup );

Expand Down Expand Up @@ -661,6 +685,10 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
#if ( configNUM_CORES > 1 )
/* Release the previously taken kernel lock. */
vTaskReleaseKernelLock();
#endif /* configNUM_CORES > 1 */
( void ) xTaskResumeAll();
}
/*-----------------------------------------------------------*/
Expand Down
7 changes: 7 additions & 0 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@
#define configUSE_TIMERS 0
#endif

#ifndef configCHECK_MUTEX_GIVEN_BY_OWNER
#define configCHECK_MUTEX_GIVEN_BY_OWNER 0
#endif

#ifndef configUSE_COUNTING_SEMAPHORES
#define configUSE_COUNTING_SEMAPHORES 0
#endif
Expand Down Expand Up @@ -1300,6 +1304,7 @@ typedef struct xSTATIC_QUEUE
UBaseType_t uxDummy8;
uint8_t ucDummy9;
#endif
portMUX_TYPE xDummyQueueLock;
} StaticQueue_t;
typedef StaticQueue_t StaticSemaphore_t;

Expand Down Expand Up @@ -1329,6 +1334,7 @@ typedef struct xSTATIC_EVENT_GROUP
#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
uint8_t ucDummy4;
#endif
portMUX_TYPE xDummyEventGroupLock;
} StaticEventGroup_t;

/*
Expand Down Expand Up @@ -1356,6 +1362,7 @@ typedef struct xSTATIC_TIMER
UBaseType_t uxDummy7;
#endif
uint8_t ucDummy8;
portMUX_TYPE xDummyStreamBufferLock;
} StaticTimer_t;

/*
Expand Down
6 changes: 3 additions & 3 deletions include/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ typedef enum
* \defgroup taskENTER_CRITICAL taskENTER_CRITICAL
* \ingroup SchedulerControl
*/
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR()
#define taskENTER_CRITICAL( x ) portENTER_CRITICAL( x )
#define taskENTER_CRITICAL_FROM_ISR( x ) portSET_INTERRUPT_MASK_FROM_ISR( x )

/**
* task. h
Expand All @@ -218,7 +218,7 @@ typedef enum
* \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL
* \ingroup SchedulerControl
*/
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
#define taskEXIT_CRITICAL( x ) portEXIT_CRITICAL( x )
#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x )

/**
Expand Down
Loading