for( ;; )\r
{\r
/* Should not be able to 'give' the mutex, as we have not yet 'taken'\r
- it. */\r
+ it. The first time through, the mutex will not have been used yet,\r
+ subsequent times through, at this point the mutex will be held by the\r
+ polling task. */\r
if( xSemaphoreGiveRecursive( xMutex ) == pdPASS )\r
{\r
xErrorOccurred = pdTRUE;\r
for( ux = 0; ux < recmuMAX_COUNT; ux++ )\r
{\r
/* We should now be able to take the mutex as many times as\r
- we like. A one tick delay is used so the polling task will\r
- inherit our priority on all but the first cycle of this task. \r
- If we did not block attempting to receive the mutex then no\r
- priority inheritance would occur. */\r
+ we like.\r
+ \r
+ The first time through the mutex will be immediately available, on\r
+ subsequent times through the mutex will be held by the polling task\r
+ at this point and this Take will cause the polling task to inherit\r
+ the priority of this task. In this case the block time must be\r
+ long enough to ensure the polling task will execute again before the\r
+ block time expires. If the block time does expire then the error\r
+ flag will be set here. */\r
if( xSemaphoreTakeRecursive( xMutex, recmuTWO_TICK_DELAY ) != pdPASS )\r
{\r
xErrorOccurred = pdTRUE;\r
}\r
\r
/* Ensure the other task attempting to access the mutex (and the\r
- other demo tasks) are able to execute. */\r
+ other demo tasks) are able to execute to ensure they either block\r
+ (where a block time is specified) or return an error (where no \r
+ block time is specified) as the mutex is held by this task. */\r
vTaskDelay( recmuSHORT_DELAY );\r
}\r
\r
vTaskDelay( recmuSHORT_DELAY );\r
\r
/* We should now be able to give the mutex as many times as we\r
- took it. */\r
+ took it. When the mutex is available again the Blocking task\r
+ should be unblocked but not run because it has a lower priority\r
+ than this task. The polling task should also not run at this point\r
+ as it too has a lower priority than this task. */\r
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )\r
{\r
xErrorOccurred = pdTRUE;\r
\r
for( ;; )\r
{\r
- /* Attempt to obtain the mutex. We should block until the \r
- controlling task has given up the mutex, and not actually execute\r
- past this call until the controlling task is suspended. */\r
+ /* This task will run while the controlling task is blocked, and the\r
+ controlling task will block only once it has the mutex - therefore\r
+ this call should block until the controlling task has given up the \r
+ mutex, and not actually execute past this call until the controlling \r
+ task is suspended. */\r
if( xSemaphoreTakeRecursive( xMutex, portMAX_DELAY ) == pdPASS )\r
{\r
if( xControllingIsSuspended != pdTRUE )\r
for( ;; )\r
{\r
/* Keep attempting to obtain the mutex. We should only obtain it when\r
- the blocking task has suspended itself. */\r
+ the blocking task has suspended itself, which in turn should only\r
+ happen when the controlling task is also suspended. */\r
if( xSemaphoreTakeRecursive( xMutex, recmuNO_DELAY ) == pdPASS )\r
{\r
/* Is the blocking task suspended? */\r
- if( xBlockingIsSuspended != pdTRUE )\r
+ if( ( xBlockingIsSuspended != pdTRUE ) || ( xControllingIsSuspended != pdTRUE ) )\r
{\r
xErrorOccurred = pdTRUE;\r
}\r
else\r
{\r
- /* Keep count of the number of cycles this task has performed so \r
- a stall can be detected. */\r
+ /* Keep count of the number of cycles this task has performed \r
+ so a stall can be detected. */\r
uxPollingCycles++;\r
\r
/* We can resume the other tasks here even though they have a\r
higher priority than the polling task. When they execute they\r
will attempt to obtain the mutex but fail because the polling\r
task is still the mutex holder. The polling task (this task)\r
- will then inherit the higher priority. */ \r
+ will then inherit the higher priority. The Blocking task will\r
+ block indefinitely when it attempts to obtain the mutex, the\r
+ Controlling task will only block for a fixed period and an\r
+ error will be latched if the polling task has not returned the\r
+ mutex by the time this fixed period has expired. */\r
vTaskResume( xBlockingTaskHandle );\r
vTaskResume( xControllingTaskHandle );\r
\r
+ /* The other two tasks should now have executed and no longer\r
+ be suspended. */\r
+ if( ( xBlockingIsSuspended == pdTRUE ) || ( xControllingIsSuspended == pdTRUE ) )\r
+ {\r
+ xErrorOccurred = pdTRUE;\r
+ } \r
+ \r
/* Release the mutex, disinheriting the higher priority again. */\r
if( xSemaphoreGiveRecursive( xMutex ) != pdPASS )\r
{\r