]> git.sur5r.net Git - freertos/commitdiff
Documentation updates.
authorRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 24 Jan 2008 21:33:00 +0000 (21:33 +0000)
committerRichardBarry <RichardBarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 24 Jan 2008 21:33:00 +0000 (21:33 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@133 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/Common/Minimal/recmutex.c
Source/include/semphr.h

index fea1d32c402f21935d85b433cf2a4f1ef17d67b6..a1ceb44854eb5ae1d33610989ebca9b4d2172872 100644 (file)
 /*\r
        The tasks defined on this page demonstrate the use of recursive mutexes.\r
 \r
-       All mutexes are created using a call to xSemaphoreCreateMutex().  For\r
-       recursive mutex functionality the created mutex should then be manipulated\r
+       For recursive mutex functionality the created mutex should be created using\r
+       xSemaphoreCreateRecursiveMutex(), then be manipulated\r
        using the xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() API\r
-       functions.  Recursive mutexes must NOT be passed as a parameter to the\r
-       standard mutex API functions xSemaphoreTake() and xSemaphoreGive().\r
+       functions.\r
 \r
        This demo creates three tasks all of which access the same recursive mutex:\r
 \r
index b5c61e04c2dc1f8eecefa13802a190341c573b71..dc236a59979a58c41a1c3ec6a82974f36e28b8fa 100644 (file)
@@ -99,18 +99,21 @@ typedef xQueueHandle xSemaphoreHandle;
  *                   portTickType xBlockTime \r
  *               )</pre>\r
  *\r
- * <i>Macro</i> to obtain a semaphore.  The semaphore must of been created using \r
- * vSemaphoreCreateBinary ().\r
+ * <i>Macro</i> to obtain a semaphore.  The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or\r
+ * xSemaphoreCreateCounting().\r
  *\r
- * @param xSemaphore A handle to the semaphore being obtained.  This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * @param xSemaphore A handle to the semaphore being taken - obtained when\r
+ * the semaophore was created.\r
  *\r
  * @param xBlockTime The time in ticks to wait for the semaphore to become\r
  * available.  The macro portTICK_RATE_MS can be used to convert this to a\r
- * real time.  A block time of zero can be used to poll the semaphore.\r
+ * real time.  A block time of zero can be used to poll the semaphore.  A block\r
+ * time of portMAX_DELAY can be used to block indefinately (provided\r
+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h).\r
  *\r
- * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime\r
- * expired without the semaphore becoming available.\r
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE\r
+ * if xBlockTime expired without the semaphore becoming available.\r
  *\r
  * Example usage:\r
  <pre>\r
@@ -156,6 +159,100 @@ typedef xQueueHandle xSemaphoreHandle;
  */\r
 #define xSemaphoreTake( xSemaphore, xBlockTime )               xQueueGenericReceive( ( xQueueHandle ) xSemaphore, NULL, xBlockTime, pdFALSE )\r
 \r
+/**\r
+ * semphr. h\r
+ * xSemaphoreTakeRecursive( \r
+ *                          xSemaphoreHandle xMutex, \r
+ *                          portTickType xBlockTime \r
+ *                        )\r
+ *\r
+ * <i>Macro</i> to recursively obtain, or 'take', a mutex type semaphore.  \r
+ * The mutex must have previously been created using a call to \r
+ * xSemaphoreCreateRecursiveMutex();\r
+ * \r
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this\r
+ * macro to be available.\r
+ * \r
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().\r
+ *\r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also  'given' the mutex back\r
+ * exactly five times.\r
+ *\r
+ * @param xMutex A handle to the mutex being obtained.  This is the\r
+ * handle returned by xSemaphoreCreateMutex();\r
+ *\r
+ * @param xBlockTime The time in ticks to wait for the semaphore to become\r
+ * available.  The macro portTICK_RATE_MS can be used to convert this to a\r
+ * real time.  A block time of zero can be used to poll the semaphore.  If\r
+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will\r
+ * return immediately nomatter what the value of xBlockTime. \r
+ *\r
+ * @return pdTRUE if the semaphore was obtained.  pdFALSE if xBlockTime\r
+ * expired without the semaphore becoming available.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xMutex = NULL;\r
+\r
+ // A task that creates a mutex.\r
+ void vATask( void * pvParameters )\r
+ {\r
+    // Create the mutex to guard a shared resource.\r
+    xMutex = xSemaphoreCreateRecursiveMutex();\r
+ }\r
+\r
+ // A task that uses the mutex.\r
+ void vAnotherTask( void * pvParameters )\r
+ {\r
+    // ... Do other things.\r
+\r
+    if( xMutex != NULL )\r
+    {\r
+        // See if we can obtain the mutex.  If the mutex is not available\r
+        // wait 10 ticks to see if it becomes free.    \r
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )\r
+        {\r
+            // We were able to obtain the mutex and can now access the\r
+            // shared resource.\r
+\r
+            // ...\r
+            // For some reason due to the nature of the code further calls to \r
+                       // xSemaphoreTakeRecursive() are made on the same mutex.  In real\r
+                       // code these would not be just sequential calls as this would make\r
+                       // no sense.  Instead the calls are likely to be buried inside\r
+                       // a more complex call structure.\r
+            xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+            xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+\r
+            // The mutex has now been 'taken' three times, so will not be \r
+                       // available to another task until it has also been given back\r
+                       // three times.  Again it is unlikely that real code would have\r
+                       // these calls sequentially, but instead buried in a more complex\r
+                       // call structure.  This is just for illustrative puproses.\r
+            xSemaphoreGiveRecursive( xSemaphore );\r
+                       xSemaphoreGiveRecursive( xSemaphore );\r
+                       xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+                       // Now the mutex can be taken by other tasks.\r
+        }\r
+        else\r
+        {\r
+            // We could not obtain the mutex and can therefore not access\r
+            // the shared resource safely.\r
+        }\r
+    }\r
+ }\r
+ </pre>\r
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive\r
+ * \ingroup Semaphores\r
+ */\r
+#define xSemaphoreTakeRecursive( xMutex, xBlockTime )  xQueueTakeMutexRecursive( xMutex, xBlockTime )\r
+\r
+\r
 /* \r
  * xSemaphoreAltTake() is an alternative version of xSemaphoreTake().\r
  *\r
@@ -174,14 +271,18 @@ typedef xQueueHandle xSemaphoreHandle;
  * semphr. h\r
  * <pre>xSemaphoreGive( xSemaphoreHandle xSemaphore )</pre>\r
  *\r
- * <i>Macro</i> to release a semaphore.  The semaphore must of been created using \r
- * vSemaphoreCreateBinary (), and obtained using sSemaphoreTake ().\r
+ * <i>Macro</i> to release a semaphore.  The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary(), xSemaphoreCreateMutex() or\r
+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake().\r
  *\r
- * This must not be used from an ISR.  See xSemaphoreGiveFromISR () for\r
+ * This macro must not be used from an ISR.  See xSemaphoreGiveFromISR () for\r
  * an alternative which can be used from an ISR.\r
  *\r
+ * This macro must also not be used on semaphores created using \r
+ * xSemaphoreCreateRecursiveMutex().\r
+ *\r
  * @param xSemaphore A handle to the semaphore being released.  This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * handle returned when the semaphore was created.\r
  *\r
  * @return pdTRUE if the semaphore was released.  pdFALSE if an error occurred.\r
  * Semaphores are implemented using queues.  An error can occur if there is\r
@@ -229,6 +330,90 @@ typedef xQueueHandle xSemaphoreHandle;
  */\r
 #define xSemaphoreGive( xSemaphore )           xQueueGenericSend( ( xQueueHandle ) xSemaphore, NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK )\r
 \r
+/**\r
+ * semphr. h\r
+ * <pre>xSemaphoreGiveRecursive( xSemaphoreHandle xSemaphore )</pre>\r
+ *\r
+ * <i>Macro</i> to recursively release, or 'give', a mutex type semaphore.\r
+ * The mutex must have previously been created using a call to \r
+ * xSemaphoreCreateRecursiveMutex();\r
+ * \r
+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this\r
+ * macro to be available.\r
+ *\r
+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex().\r
+ * \r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also  'given' the mutex back\r
+ * exactly five times.\r
+ *\r
+ * @param xMutex A handle to the mutex being released, or 'given'.  This is the\r
+ * handle returned by xSemaphoreCreateMutex();\r
+ *\r
+ * @return pdTRUE if the semaphore was given.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xMutex = NULL;\r
+\r
+ // A task that creates a mutex.\r
+ void vATask( void * pvParameters )\r
+ {\r
+    // Create the mutex to guard a shared resource.\r
+    xMutex = xSemaphoreCreateRecursiveMutex();\r
+ }\r
+\r
+ // A task that uses the mutex.\r
+ void vAnotherTask( void * pvParameters )\r
+ {\r
+    // ... Do other things.\r
+\r
+    if( xMutex != NULL )\r
+    {\r
+        // See if we can obtain the mutex.  If the mutex is not available\r
+        // wait 10 ticks to see if it becomes free.    \r
+        if( xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 ) == pdTRUE )\r
+        {\r
+            // We were able to obtain the mutex and can now access the\r
+            // shared resource.\r
+\r
+            // ...\r
+            // For some reason due to the nature of the code further calls to \r
+                       // xSemaphoreTakeRecursive() are made on the same mutex.  In real\r
+                       // code these would not be just sequential calls as this would make\r
+                       // no sense.  Instead the calls are likely to be buried inside\r
+                       // a more complex call structure.\r
+            xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+            xSemaphoreTakeRecursive( xSemaphore, ( portTickType ) 10 );\r
+\r
+            // The mutex has now been 'taken' three times, so will not be \r
+                       // available to another task until it has also been given back\r
+                       // three times.  Again it is unlikely that real code would have\r
+                       // these calls sequentially, it would be more likely that the calls\r
+                       // to xSemaphoreGiveRecursive() would be called as a call stack\r
+                       // unwound.  This is just for demonstrative purposes.\r
+            xSemaphoreGiveRecursive( xSemaphore );\r
+                       xSemaphoreGiveRecursive( xSemaphore );\r
+                       xSemaphoreGiveRecursive( xSemaphore );\r
+\r
+                       // Now the mutex can be taken by other tasks.\r
+        }\r
+        else\r
+        {\r
+            // We could not obtain the mutex and can therefore not access\r
+            // the shared resource safely.\r
+        }\r
+    }\r
+ }\r
+ </pre>\r
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive\r
+ * \ingroup Semaphores\r
+ */\r
+#define xSemaphoreGiveRecursive( xMutex )      xQueueGiveMutexRecursive( xMutex )\r
+\r
 /* \r
  * xSemaphoreAltGive() is an alternative version of xSemaphoreGive().\r
  *\r
@@ -251,8 +436,8 @@ typedef xQueueHandle xSemaphoreHandle;
                           portSHORT sTaskPreviouslyWoken \r
                       )</pre>\r
  *\r
- * <i>Macro</i> to  release a semaphore.  The semaphore must of been created using \r
- * vSemaphoreCreateBinary (), and obtained using xSemaphoreTake ().\r
+ * <i>Macro</i> to  release a semaphore.  The semaphore must have previously been\r
+ * created with a call to vSemaphoreCreateBinary() or xSemaphoreCreateCounting().\r
  *\r
  * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex())\r
  * must not be used with this macro.\r
@@ -260,7 +445,7 @@ typedef xQueueHandle xSemaphoreHandle;
  * This macro can be used from an ISR.\r
  *\r
  * @param xSemaphore A handle to the semaphore being released.  This is the\r
- * handle returned by vSemaphoreCreateBinary ();\r
+ * handle returned when the semaphore was created.\r
  *\r
  * @param sTaskPreviouslyWoken This is included so an ISR can make multiple calls\r
  * to xSemaphoreGiveFromISR () from a single interrupt.  The first call\r
@@ -283,8 +468,8 @@ typedef xQueueHandle xSemaphoreHandle;
  {\r
     for( ;; )\r
     {\r
-        // We want this task to run every 10 ticks or a timer.  The semaphore \r
-        // was created before this task was started\r
+        // We want this task to run every 10 ticks of a timer.  The semaphore \r
+        // was created before this task was started.\r
 \r
         // Block waiting for the semaphore to become available.\r
         if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )\r
@@ -295,7 +480,8 @@ typedef xQueueHandle xSemaphoreHandle;
 \r
             // We have finished our task.  Return to the top of the loop where\r
             // we will block on the semaphore until it is time to execute \r
-            // again.\r
+            // again.  Note when using the semaphore for synchronisation with an\r
+                       // ISR in this manner there is no need to 'give' the semaphore back.\r
         }\r
     }\r
  }\r
@@ -316,11 +502,18 @@ typedef xQueueHandle xSemaphoreHandle;
     if( ucLocalTickCount >= TICKS_TO_WAIT )\r
     {\r
         // Unblock the task by releasing the semaphore.\r
-        xSemaphoreGiveFromISR( xSemaphore, xTaskWoken );\r
+        xTaskWoken = xSemaphoreGiveFromISR( xSemaphore, xTaskWoken );\r
 \r
         // Reset the count so we release the semaphore again in 10 ticks time.\r
         ucLocalTickCount = 0;\r
     }\r
+\r
+    if( xTaskWoken != pdFALSE )\r
+    {\r
+        // We can force a context switch here.  Context switching from an\r
+        // ISR uses port specific syntax.  Check the demo task for your port\r
+        // to find the syntax required.\r
+    }\r
  }\r
  </pre>\r
  * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR\r
@@ -335,6 +528,10 @@ typedef xQueueHandle xSemaphoreHandle;
  * <i>Macro</i> that implements a mutex semaphore by using the existing queue \r
  * mechanism.\r
  *\r
+ * Mutexes created using this macro can be accessed using the xSemaphoreTake()\r
+ * and xSemaphoreGive() macros.  The xSemaphoreTakeRecursive() and \r
+ * xSemaphoreGiveRecursive() macros should not be used.\r
+ * \r
  * This type of semaphore uses a priority inheritance mechanism so a task \r
  * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the \r
  * semaphore it is no longer required.  \r
@@ -370,6 +567,60 @@ typedef xQueueHandle xSemaphoreHandle;
  * \ingroup Semaphores\r
  */\r
 #define xSemaphoreCreateMutex() xQueueCreateMutex()\r
+\r
+\r
+/**\r
+ * semphr. h\r
+ * <pre>xSemaphoreHandle xSemaphoreCreateRecursiveMutex( void )</pre>\r
+ *\r
+ * <i>Macro</i> that implements a recursive mutex by using the existing queue \r
+ * mechanism.\r
+ *\r
+ * Mutexes created using this macro can be accessed using the \r
+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros.  The \r
+ * xSemaphoreTake() and xSemaphoreGive() macros should not be used.\r
+ *\r
+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex \r
+ * doesn't become available again until the owner has called \r
+ * xSemaphoreGiveRecursive() for each successful 'take' request.  For example, \r
+ * if a task successfully 'takes' the same mutex 5 times then the mutex will \r
+ * not be avilable to any other task until it has also  'given' the mutex back\r
+ * exactly five times.\r
+ * \r
+ * This type of semaphore uses a priority inheritance mechanism so a task \r
+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the \r
+ * semaphore it is no longer required.  \r
+ *\r
+ * Mutex type semaphores cannot be used from within interrupt service routines.  \r
+ *\r
+ * See xSemaphoreCreateBinary() for an alternative implementation that can be \r
+ * used for pure synchronisation (where one task or interrupt always 'gives' the \r
+ * semaphore and another always 'takes' the semaphore) and from within interrupt \r
+ * service routines.\r
+ *\r
+ * @return xSemaphore Handle to the created mutex semaphore.  Should be of type \r
+ *             xSemaphoreHandle.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ xSemaphoreHandle xSemaphore;\r
+\r
+ void vATask( void * pvParameters )\r
+ {\r
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().\r
+    // This is a macro so pass the variable in directly.\r
+    xSemaphore = xSemaphoreCreateRecursiveMutex();\r
+\r
+    if( xSemaphore != NULL )\r
+    {\r
+        // The semaphore was created successfully.\r
+        // The semaphore can now be used.  \r
+    }\r
+ }\r
+ </pre>\r
+ * \defgroup vSemaphoreCreateMutex vSemaphoreCreateMutex\r
+ * \ingroup Semaphores\r
+ */\r
 #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex()\r
 \r
 /**\r
@@ -435,8 +686,6 @@ typedef xQueueHandle xSemaphoreHandle;
  */\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