From 26e9699f9c1bb7259cc62e91c68b9d67c43a8025 Mon Sep 17 00:00:00 2001 From: rtel Date: Mon, 31 Mar 2014 02:12:17 +0000 Subject: [PATCH] Add test and correct code for the unusual case of a task using an event group to synchronise only with itself. Add critical sections around call to prvResetNextTaskUnblockTime() that can occur from within a task. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2233 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../Demo/Common/Minimal/EventGroupsDemo.c | 32 +++++++++++++++++++ FreeRTOS/Source/event_groups.c | 2 +- FreeRTOS/Source/tasks.c | 12 +++++-- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c index daf518950..4890fde4b 100644 --- a/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c +++ b/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c @@ -544,6 +544,38 @@ EventBits_t uxBits; xError = pdTRUE; } + /* Try a synch with no other tasks involved. First set all the bits other + than this task's bit. */ + xEventGroupSetBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + + /* Then wait on just one bit - the bit that is being set. */ + uxBits = xEventGroupSync( xEventGroup, /* The event group used for the synchronisation. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bit set by this task when it reaches the sync point. */ + ebSET_BIT_TASK_SYNC_BIT,/* The bits to wait for - in this case it is just waiting for itself. */ + portMAX_DELAY ); /* The maximum time to wait for the sync condition to be met. */ + + /* A sync with a max delay should only exit when all the synchronise + bits are set...check that is the case. In this case there is only one + sync bit anyway. */ + if( ( uxBits & ebSET_BIT_TASK_SYNC_BIT ) != ebSET_BIT_TASK_SYNC_BIT ) + { + xError = pdTRUE; + } + + /* ...but now the sync bits should be clear again, leaving all the other + bits set (as only one bit was being waited for). */ + if( xEventGroupGetBits( xEventGroup ) != ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ) + { + xError = pdTRUE; + } + + /* Clear all the bits to zero again. */ + xEventGroupClearBits( xEventGroup, ( ebALL_SYNC_BITS & ~ebSET_BIT_TASK_SYNC_BIT ) ); + if( xEventGroupGetBits( xEventGroup ) != 0 ) + { + xError = pdTRUE; + } + /* Unsuspend the other tasks then check they have executed up to the synchronisation point. */ vTaskResume( xTestSlaveTaskHandle ); diff --git a/FreeRTOS/Source/event_groups.c b/FreeRTOS/Source/event_groups.c index c7194016e..5b45f9cc7 100644 --- a/FreeRTOS/Source/event_groups.c +++ b/FreeRTOS/Source/event_groups.c @@ -179,7 +179,7 @@ BaseType_t xTimeoutOccurred = pdFALSE; /* Rendezvous always clear the bits. They will have been cleared already unless this is the only task in the rendezvous. */ - pxEventBits->uxEventBits &= uxBitsToWaitFor; + pxEventBits->uxEventBits &= ~uxBitsToWaitFor; xTicksToWait = 0; } diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index 8512e1bbc..c20aeed54 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -760,7 +760,11 @@ TCB_t * pxNewTCB; { /* Reset the next expected unblock time in case it referred to the task that has just been deleted. */ - prvResetNextTaskUnblockTime(); + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); } } } @@ -1259,7 +1263,11 @@ TCB_t * pxNewTCB; /* A task other than the currently running task was suspended, reset the next expected unblock time in case it referred to the task that is now in the Suspended state. */ - prvResetNextTaskUnblockTime(); + taskENTER_CRITICAL(); + { + prvResetNextTaskUnblockTime(); + } + taskEXIT_CRITICAL(); } else { -- 2.39.5