void vTimerISR( void * pvParameters )\r
{\r
static unsigned portCHAR ucLocalTickCount = 0;\r
+ static portBASE_TYPE xTaskWoken;\r
\r
// A timer tick has occurred.\r
\r
// ... Do other time functions.\r
\r
// Is it time for vATask () to run?\r
+ xTaskWoken = pdFALSE;\r
ucLocalTickCount++;\r
if( ucLocalTickCount >= TICKS_TO_WAIT )\r
{\r
// Unblock the task by releasing the semaphore.\r
- xSemaphoreGive( xSemaphore );\r
+ xSemaphoreGiveFromISR( xSemaphore, xTaskWoken );\r
\r
// Reset the count so we release the semaphore again in 10 ticks time.\r
ucLocalTickCount = 0;\r
* \ingroup Semaphores\r
*/\r
#define xSemaphoreCreateMutex() xQueueCreateMutex()\r
+#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()\r
\r
/**\r
* semphr. h\r
- * <pre>xSemaphoreHandle xSemaphoreCreateCounting( uxCountValue, uxInitialCount )</pre>\r
+ * <pre>xSemaphoreHandle xSemaphoreCreateCounting( unsigned portBASE_TYPE uxMaxCount, unsigned portBASE_TYPE uxInitialCount )</pre>\r
*\r
* <i>Macro</i> that creates a counting semaphore by using the existing \r
* queue mechanism. \r
* \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting\r
* \ingroup Semaphores\r
*/\r
-#define xSemaphoreCreateCounting( uxCountValue, uxInitialCount ) xQueueCreateCountingSemaphore( uxCountValue, uxInitialCount )\r
+#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( uxMaxCount, uxInitialCount )\r
+\r
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( xMutex, xBlockTime )\r
+#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( xMutex )\r
\r
#endif /* SEMAPHORE_H */\r
\r
/* Effectively make a union out of the xQUEUE structure. */\r
#define pxMutexHolder pcTail\r
#define uxQueueType pcHead\r
+#define uxRecursiveCallCount pcReadFrom\r
#define queueQUEUE_IS_MUTEX NULL\r
\r
/* Semaphores do not actually store or copy data, so have an items size of\r
zero. */\r
#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( 0 )\r
#define queueDONT_BLOCK ( ( portTickType ) 0 )\r
-\r
+#define queueMUTEX_GIVE_BLOCK_TIME ( ( portTickType ) 0 )\r
/*\r
* Definition of the queue used by the scheduler.\r
* Items are queued by copy, not reference.\r
signed portBASE_TYPE xQueueReceiveFromISR( xQueueHandle pxQueue, const void * const pvBuffer, signed portBASE_TYPE *pxTaskWoken );\r
xQueueHandle xQueueCreateMutex( void );\r
xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount );\r
+portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle xMutex, portTickType xBlockTime );\r
+portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle xMutex );\r
signed portBASE_TYPE xQueueAltGenericSend( xQueueHandle pxQueue, const void * const pvItemToQueue, portTickType xTicksToWait, portBASE_TYPE xCopyPosition );\r
signed portBASE_TYPE xQueueAltGenericReceive( xQueueHandle pxQueue, const void * const pvBuffer, portTickType xTicksToWait, portBASE_TYPE xJustPeeking );\r
\r
#endif /* configUSE_MUTEXES */\r
/*-----------------------------------------------------------*/\r
\r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+ portBASE_TYPE xQueueGiveMutexRecursive( xQueueHandle pxMutex )\r
+ {\r
+ portBASE_TYPE xReturn;\r
+\r
+ /* If this is the task that holds the mutex then pxMutexHolder will not \r
+ change outside of this task. If this task does not hold the mutex then\r
+ pxMutexHolder can never coincidentally equal the tasks handle, and as\r
+ this is the only condition we are interested in it does not matter if\r
+ pxMutexHolder is accessed simultaneously by another task. Therefore no\r
+ mutual exclusion is required to test the pxMutexHolder variable. */\r
+ if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+ {\r
+ /* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to\r
+ the task handle, therefore no underflow check is required. Also, \r
+ uxRecursiveCallCount is only modified by the mutex holder, and as\r
+ there can only be one, no mutual exclusion is required to modify the\r
+ uxRecursiveCallCount member. */\r
+ ( pxMutex->uxRecursiveCallCount )--;\r
+\r
+ /* Have we unwound the call count? */\r
+ if( pxMutex->uxRecursiveCallCount == 0 )\r
+ {\r
+ /* Return the mutex. This will automatically unblock any other\r
+ task that might be waiting to access the mutex. */\r
+ xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );\r
+ }\r
+\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ /* We cannot give the mutex because we are not the holder. */\r
+ xReturn = pdFAIL;\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_RECURSIVE_MUTEXES == 1\r
+\r
+ portBASE_TYPE xQueueTakeMutexRecursive( xQueueHandle pxMutex, portTickType xBlockTime )\r
+ {\r
+ portBASE_TYPE xReturn;\r
+\r
+ /* Comments regarding mutual exclusion as per those within \r
+ xQueueGiveMutexRecursive(). */\r
+\r
+ if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )\r
+ {\r
+ ( pxMutex->uxRecursiveCallCount )++;\r
+ xReturn = pdPASS;\r
+ }\r
+ else\r
+ {\r
+ xReturn = xQueueGenericReceive( pxMutex, NULL, xBlockTime, pdFALSE );\r
+\r
+ /* pdPASS will only be returned if we successfully obtained the mutex,\r
+ we may have blocked to reach here. */\r
+ if( xReturn == pdPASS )\r
+ {\r
+ ( pxMutex->uxRecursiveCallCount )++;\r
+ }\r
+ }\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_RECURSIVE_MUTEXES */\r
+/*-----------------------------------------------------------*/\r
+\r
#if configUSE_COUNTING_SEMAPHORES == 1\r
\r
- xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount )\r
+ xQueueHandle xQueueCreateCountingSemaphore( unsigned portBASE_TYPE uxCountValue, unsigned portBASE_TYPE uxInitialCount, portBASE_TYPE xIsRecursive )\r
{\r
xQueueHandle pxHandle;\r
\r
{\r
/* The mutex is no longer being held. */\r
vTaskPriorityDisinherit( ( void * const ) pxQueue->pxMutexHolder );\r
+ pxQueue->pxMutexHolder = NULL;\r
}\r
}\r
#endif\r