Core kernel code:

- Re-introduce the ability to give a mutex from an ISR.

Common demo code:
- Add additional tests into the GenQTest files for priority inheritance and using a mutex from an ISR.
This commit is contained in:
Richard Barry 2014-08-29 13:53:58 +00:00
parent 6507701fdf
commit ff5d3512b3
13 changed files with 379 additions and 176 deletions

View File

@ -34,12 +34,12 @@
<PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><ShowCodeCoverage>1</ShowCodeCoverage><ShowInstrProfiling>1</ShowInstrProfiling></Disassembly>
<Register><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows></Register><WATCH_1><expressions><item></item></expressions><col-names><item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names><col-widths><item>207</item><item>150</item><item>100</item><item>294</item></col-widths><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows></WATCH_1><CallStack><PreferedWindows><Position>1</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Frame</item><item>_I0</item></col-names><col-widths><item>400</item><item>20</item></col-widths></CallStack><Breakpoints><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Breakpoint</item><item>_I0</item></col-names><col-widths><item>500</item><item>35</item></col-widths></Breakpoints><Find-in-Files><ColumnWidth0>497</ColumnWidth0><ColumnWidth1>82</ColumnWidth1><ColumnWidth2>746</ColumnWidth2><ColumnWidth3>331</ColumnWidth3><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows><Window><Factory>Debug-Log</Factory></Window><Window><Factory>Build</Factory></Window></Windows></PreferedWindows></Find-in-Files><QuickWatch><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names><col-widths><item>100</item><item>150</item><item>100</item><item>100</item></col-widths><QWatchHistory><item>TC0</item><item>TC0-&gt;TC_CHANNEL[ tmrTC0_CHANNEL_0 ].TC_RC</item></QWatchHistory></QuickWatch><Memory><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><FindDirection>1</FindDirection><FindAsHex>0</FindAsHex></Memory><TASKVIEW><Column0>200</Column0><Column1>100</Column1><Column2>100</Column2><Column3>100</Column3><Column4>100</Column4><Column5>100</Column5><Column6>100</Column6><Column7>100</Column7><Column8>150</Column8></TASKVIEW><QUEUEVIEW><Column0>200</Column0><Column1>100</Column1><Column2>100</Column2><Column3>100</Column3><Column4>100</Column4><Column5>100</Column5><Column6>100</Column6></QUEUEVIEW></Static>
<Register><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows></Register><WATCH_1><expressions><item/></expressions><col-names><item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names><col-widths><item>207</item><item>150</item><item>100</item><item>294</item></col-widths><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows></WATCH_1><CallStack><PreferedWindows><Position>1</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Frame</item><item>_I0</item></col-names><col-widths><item>400</item><item>20</item></col-widths></CallStack><Breakpoints><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Breakpoint</item><item>_I0</item></col-names><col-widths><item>500</item><item>35</item></col-widths></Breakpoints><Find-in-Files><ColumnWidth0>497</ColumnWidth0><ColumnWidth1>82</ColumnWidth1><ColumnWidth2>746</ColumnWidth2><ColumnWidth3>331</ColumnWidth3><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows><Window><Factory>Debug-Log</Factory></Window><Window><Factory>Build</Factory></Window></Windows></PreferedWindows></Find-in-Files><QuickWatch><PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names><col-widths><item>100</item><item>150</item><item>100</item><item>100</item></col-widths><QWatchHistory><item>TC0</item><item>TC0-&gt;TC_CHANNEL[ tmrTC0_CHANNEL_0 ].TC_RC</item></QWatchHistory></QuickWatch><Memory><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><FindDirection>1</FindDirection><FindAsHex>0</FindAsHex></Memory><TASKVIEW><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><Column0>200</Column0><Column1>100</Column1><Column2>100</Column2><Column3>100</Column3><Column4>100</Column4><Column5>100</Column5><Column6>100</Column6><Column7>100</Column7><Column8>150</Column8></TASKVIEW><QUEUEVIEW><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><Column0>300</Column0><Column1>100</Column1><Column2>100</Column2><Column3>100</Column3><Column4>100</Column4><Column5>100</Column5><Column6>100</Column6></QUEUEVIEW></Static>
<Windows>
<Wnd1>
<Wnd0>
<Tabs>
<Tab>
<Identity>TabID-24673-23877</Identity>
@ -51,20 +51,20 @@
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd1><Wnd2><Tabs><Tab><Identity>TabID-22902-32031</Identity><TabName>Tasks</TabName><Factory>TASKVIEW</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd2><Wnd3><Tabs><Tab><Identity>TabID-22379-32041</Identity><TabName>Queues</TabName><Factory>QUEUEVIEW</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd3></Windows>
<SelectedTab>0</SelectedTab></Wnd0><Wnd5><Tabs><Tab><Identity>TabID-31713-7906</Identity><TabName>Debug Log</TabName><Factory>Debug-Log</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd5></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>140</YPos2><SelStart2>7249</SelStart2><SelEnd2>7249</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\Full_Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\blinky_demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>1373</SelStart2><SelEnd2>1373</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\Source\portable\IAR\ARM_CA5_No_GIC\portASM.s</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>73</YPos2><SelStart2>3799</SelStart2><SelEnd2>3799</SelEnd2></Tab><ActiveTab>3</ActiveTab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>127</YPos2><SelStart2>6411</SelStart2><SelEnd2>6411</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\Full_Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\blinky_demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>1373</SelStart2><SelEnd2>1373</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Common\Minimal\GenQTest.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>796</YPos2><SelStart2>27238</SelStart2><SelEnd2>27238</SelEnd2></Tab><ActiveTab>3</ActiveTab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-0111A108><key>iaridepm.enu1</key></Toolbar-0111A108></Sizes></Row0><Row1><Sizes><Toolbar-222ED2A8><key>debuggergui.enu1</key></Toolbar-222ED2A8></Sizes></Row1></Top><Left><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>520</Bottom><Right>332</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>198810</sizeVertCX><sizeVertCY>530488</sizeVertCY></Rect></Wnd1></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>198</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>200</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd2></Sizes></Row0><Row1><Sizes><Wnd3><Rect><Top>196</Top><Left>-2</Left><Bottom>396</Bottom><Right>1682</Right><x>-2</x><y>196</y><xscreen>1684</xscreen><yscreen>200</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd3></Sizes></Row1></Bottom><Float><Sizes/></Float></Positions>
<Top><Row0><Sizes><Toolbar-011172A8><key>iaridepm.enu1</key></Toolbar-011172A8></Sizes></Row0><Row1><Sizes><Toolbar-07251300><key>debuggergui.enu1</key></Toolbar-07251300></Sizes></Row1></Top><Left><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>718</Bottom><Right>332</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>198810</sizeVertCX><sizeVertCY>731707</sizeVertCY></Rect></Wnd0></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd5><Rect><Top>-2</Top><Left>-2</Left><Bottom>198</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>200</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd5></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Project>

View File

@ -14,7 +14,7 @@ Watch0=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
Watch1=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
CStepIntDis=_ 0
[DebugChecksum]
Checksum=-666464609
Checksum=-1280642381
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
@ -42,7 +42,7 @@ Exclusions=
[Disassemble mode]
mode=0
[Breakpoints2]
Bp0=_ 1 "EMUL_CODE" "{$PROJ_DIR$\main.c}.218.24" 0 0 1 "" 0 "" 0
Bp0=_ 1 "EMUL_CODE" "{$PROJ_DIR$\main.c}.221.2" 0 0 1 "" 0 "" 0
Count=1
[Aliases]
Count=0

View File

@ -36,7 +36,7 @@
<Windows>
<Wnd1>
<Wnd0>
<Tabs>
<Tab>
<Identity>TabID-22351-19008</Identity>
@ -48,7 +48,7 @@
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd1><Wnd4>
<SelectedTab>0</SelectedTab></Wnd0><Wnd2>
<Tabs>
<Tab>
<Identity>TabID-21076-19237</Identity>
@ -58,20 +58,20 @@
</Tab>
<Tab><Identity>TabID-23502-23081</Identity><TabName>Debug Log</TabName><Factory>Debug-Log</Factory><Session/></Tab><Tab><Identity>TabID-24431-23894</Identity><TabName>Ambiguous Definitions</TabName><Factory>Select-Ambiguous-Definitions</Factory><Session/></Tab><Tab><Identity>TabID-9033-6116</Identity><TabName>Find in Files</TabName><Factory>Find-in-Files</Factory><Session/></Tab></Tabs>
<SelectedTab>0</SelectedTab></Wnd4></Windows>
<SelectedTab>0</SelectedTab></Wnd2></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>59</YPos2><SelStart2>7249</SelStart2><SelEnd2>7249</SelEnd2></Tab><ActiveTab>0</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\Full_Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\blinky_demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>1373</SelStart2><SelEnd2>1373</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>5074</SelStart2><SelEnd2>5074</SelEnd2></Tab><ActiveTab>0</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\Full_Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\blinky_demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>1373</SelStart2><SelEnd2>1373</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-0111A108><key>iaridepm.enu1</key></Toolbar-0111A108></Sizes></Row0></Top><Left><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>668</Bottom><Right>352</Right><x>-2</x><y>-2</y><xscreen>190</xscreen><yscreen>170</yscreen><sizeHorzCX>113095</sizeHorzCX><sizeHorzCY>172764</sizeHorzCY><sizeVertCX>210714</sizeVertCX><sizeVertCY>680894</sizeVertCY></Rect></Wnd1></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd4><Rect><Top>-2</Top><Left>-2</Left><Bottom>272</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>274</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>278455</sizeHorzCY><sizeVertCX>113095</sizeVertCX><sizeVertCY>172764</sizeVertCY></Rect></Wnd4></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
<Top><Row0><Sizes><Toolbar-011172A8><key>iaridepm.enu1</key></Toolbar-011172A8></Sizes></Row0><Row1><Sizes/></Row1></Top><Left><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>668</Bottom><Right>352</Right><x>-2</x><y>-2</y><xscreen>190</xscreen><yscreen>170</yscreen><sizeHorzCX>113095</sizeHorzCX><sizeHorzCY>172764</sizeHorzCY><sizeVertCX>210714</sizeVertCX><sizeVertCY>680894</sizeVertCY></Rect></Wnd0></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>272</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>274</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>278455</sizeHorzCY><sizeVertCX>113095</sizeVertCX><sizeVertCY>172764</sizeVertCY></Rect></Wnd2></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Workspace>

View File

@ -93,6 +93,7 @@
#define genqMUTEX_MEDIUM_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define genqMUTEX_HIGH_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ( 100 )
/*-----------------------------------------------------------*/
/*
@ -121,6 +122,28 @@ static void prvLowPriorityMutexTask( void *pvParameters );
static void prvMediumPriorityMutexTask( void *pvParameters );
static void prvHighPriorityMutexTask( void *pvParameters );
/*
* Exercises the priority inheritance when a task takes two mutexes, returning
* them in a different order to which they were taken.
*/
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
/*
* Exercises the priority inheritance when a task takes two mutexes, returning
* them in the same order in which they were taken.
*/
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex );
/*
* Task that receives an a mutex that is given from an interrupt - although
* generally mutexes should not be used given in interrupts (and definitely
* never taken in an interrupt) there are some circumstances when it may be
* desirable. NOTE: This function is not declared static to prevent compiler
* warnings being generated in demos where the function is declared but not
* used.
*/
void vInterruptMutexTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
@ -139,6 +162,11 @@ static volatile uint32_t ulGuardedVariable = 0;
priority mutex test tasks. */
static TaskHandle_t xHighPriorityMutexTask, xMediumPriorityMutexTask;
/* A mutex which is given from an interrupt - although generally mutexes should
not be used given in interrupts (and definitely never taken in an interrupt)
there are some circumstances when it may be desirable. */
static SemaphoreHandle_t xISRMutex = NULL;
/*-----------------------------------------------------------*/
void vStartGenericQueueTasks( UBaseType_t uxPriority )
@ -146,6 +174,9 @@ void vStartGenericQueueTasks( UBaseType_t uxPriority )
QueueHandle_t xQueue;
SemaphoreHandle_t xMutex;
xISRMutex = xSemaphoreCreateMutex();
configASSERT( xISRMutex );
/* Create the queue that we are going to use for the
prvSendFrontAndBackTest demo. */
xQueue = xQueueCreate( genqQUEUE_LENGTH, sizeof( uint32_t ) );
@ -180,6 +211,14 @@ SemaphoreHandle_t xMutex;
xTaskCreate( prvLowPriorityMutexTask, "MuLow", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_LOW_PRIORITY, NULL );
xTaskCreate( prvMediumPriorityMutexTask, "MuMed", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, &xMediumPriorityMutexTask );
xTaskCreate( prvHighPriorityMutexTask, "MuHigh", configMINIMAL_STACK_SIZE, ( void * ) xMutex, genqMUTEX_HIGH_PRIORITY, &xHighPriorityMutexTask );
/* Only when the windows simulator is being used - create the task that
receives a mutex from an interrupt. */
#ifdef _WINDOWS_
{
xTaskCreate( vInterruptMutexTask, "IntMu", configMINIMAL_STACK_SIZE, NULL, genqMUTEX_MEDIUM_PRIORITY, NULL );
}
#endif /* __WINDOWS__ */
}
/*-----------------------------------------------------------*/
@ -411,6 +450,252 @@ QueueHandle_t xQueue;
}
/*-----------------------------------------------------------*/
static void prvTakeTwoMutexesReturnInDifferentOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
{
/* Take the mutex. It should be available now. */
if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* Set the guarded variable to a known start value. */
ulGuardedVariable = 0;
/* This task's priority should be as per that assigned when the task was
created. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the high priority task. This will attempt to take the
mutex, and block when it finds it cannot obtain it. */
vTaskResume( xHighPriorityMutexTask );
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Ensure the task is reporting its priority as blocked and not
suspended (as it would have done in versions up to V7.5.3). */
#if( INCLUDE_eTaskGetState == 1 )
{
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
}
#endif /* INCLUDE_eTaskGetState */
/* The priority of the high priority task should now have been inherited
as by now it will have attempted to get the mutex. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Attempt to set the priority of this task to the test priority -
between the idle priority and the medium/high test priorities, but the
actual priority should remain at the high priority. */
vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the medium priority task. This should not run as the
inherited priority of this task is above that of the medium priority
task. */
vTaskResume( xMediumPriorityMutexTask );
/* If the medium priority task did run then it will have incremented the
guarded variable. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
/* Take the local mutex too, so two mutexes are now held. */
if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* When the semaphore is given back the priority of this task should not
yet be disinherited because the local mutex is still held. This is a
simplification to allow FreeRTOS to be integrated with middleware that
attempts to hold multiple mutexes without bloating the code with complex
algorithms. It is possible that the high priority mutex task will
execute as it shares a priority with this task. */
if( xSemaphoreGive( xMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* The guarded variable is only incremented by the medium priority task,
which still should not have executed as this task should remain at the
higher priority, ensure this is the case. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now also give back the local mutex, taking the held count back to 0.
This time the priority of this task should be disinherited back to the
priority to which it was set while the mutex was held. This means
the medium priority task should execute and increment the guarded
variable. When this task next runs both the high and medium priority
tasks will have been suspended again. */
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Check the guarded variable did indeed increment... */
if( ulGuardedVariable != 1 )
{
xErrorDetected = pdTRUE;
}
/* ... and that the priority of this task has been disinherited to
genqMUTEX_TEST_PRIORITY. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Set the priority of this task back to its original value, ready for
the next loop around this test. */
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
}
/*-----------------------------------------------------------*/
static void prvTakeTwoMutexesReturnInSameOrder( SemaphoreHandle_t xMutex, SemaphoreHandle_t xLocalMutex )
{
/* Take the mutex. It should be available now. */
if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* Set the guarded variable to a known start value. */
ulGuardedVariable = 0;
/* This task's priority should be as per that assigned when the task was
created. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the high priority task. This will attempt to take the
mutex, and block when it finds it cannot obtain it. */
vTaskResume( xHighPriorityMutexTask );
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Ensure the task is reporting its priority as blocked and not
suspended (as it would have done in versions up to V7.5.3). */
#if( INCLUDE_eTaskGetState == 1 )
{
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
}
#endif /* INCLUDE_eTaskGetState */
/* The priority of the high priority task should now have been inherited
as by now it will have attempted to get the mutex. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the medium priority task. This should not run as the
inherited priority of this task is above that of the medium priority
task. */
vTaskResume( xMediumPriorityMutexTask );
/* If the medium priority task did run then it will have incremented the
guarded variable. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
/* Take the local mutex too, so two mutexes are now held. */
if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* When the local semaphore is given back the priority of this task should
not yet be disinherited because the shared mutex is still held. This is a
simplification to allow FreeRTOS to be integrated with middleware that
attempts to hold multiple mutexes without bloating the code with complex
algorithms. It is possible that the high priority mutex task will
execute as it shares a priority with this task. */
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* The guarded variable is only incremented by the medium priority task,
which still should not have executed as this task should remain at the
higher priority, ensure this is the case. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now also give back the shared mutex, taking the held count back to 0.
This time the priority of this task should be disinherited back to the
priority at which it was created. This means the medium priority task
should execute and increment the guarded variable. When this task next runs
both the high and medium priority tasks will have been suspended again. */
if( xSemaphoreGive( xMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Check the guarded variable did indeed increment... */
if( ulGuardedVariable != 1 )
{
xErrorDetected = pdTRUE;
}
/* ... and that the priority of this task has been disinherited to
genqMUTEX_LOW_PRIORITY. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
{
xErrorDetected = pdTRUE;
}
}
/*-----------------------------------------------------------*/
static void prvLowPriorityMutexTask( void *pvParameters )
{
SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
@ -430,131 +715,21 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters, xLocalMutex;
for( ;; )
{
/* Take the mutex. It should be available now. */
if( xSemaphoreTake( xMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* The first tests exercise the priority inheritance when two mutexes
are taken then returned in a different order to which they were
taken. */
prvTakeTwoMutexesReturnInDifferentOrder( xMutex, xLocalMutex );
/* Set the guarded variable to a known start value. */
ulGuardedVariable = 0;
/* This task's priority should be as per that assigned when the task was
created. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_LOW_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the high priority task. This will attempt to take the
mutex, and block when it finds it cannot obtain it. */
vTaskResume( xHighPriorityMutexTask );
/* Just to show this task is still running. */
ulLoopCounter2++;
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Ensure the task is reporting its priority as blocked and not
suspended (as it would have done in versions up to V7.5.3). */
#if( INCLUDE_eTaskGetState == 1 )
{
configASSERT( eTaskGetState( xHighPriorityMutexTask ) == eBlocked );
}
#endif /* INCLUDE_eTaskGetState */
/* The priority of the high priority task should now have been inherited
as by now it will have attempted to get the mutex. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Attempt to set the priority of this task to the test priority -
between the idle priority and the medium/high test priorities, but the
actual priority should remain at the high priority. */
vTaskPrioritySet( NULL, genqMUTEX_TEST_PRIORITY );
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now unsuspend the medium priority task. This should not run as the
inherited priority of this task is above that of the medium priority
task. */
vTaskResume( xMediumPriorityMutexTask );
/* If the medium priority task did run then it will have incremented the
guarded variable. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
/* Take the local mutex too, so two mutexes are now held. */
if( xSemaphoreTake( xLocalMutex, genqNO_BLOCK ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
/* When the semaphore is given back the priority of this task should not
yet be disinherited because the local mutex is still held. This is a
simplification to allow FreeRTOS to be integrated with middleware that
attempts to hold multiple mutexes without bloating the code with complex
algorithms. It is possible that the high priority mutex task will
execute as it shares a priority with this task. */
if( xSemaphoreGive( xMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* The guarded variable is only incremented by the medium priority task,
which still should not have executed as this task should remain at the
higher priority, ensure this is the case. */
if( ulGuardedVariable != 0 )
{
xErrorDetected = pdTRUE;
}
if( uxTaskPriorityGet( NULL ) != genqMUTEX_HIGH_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Now also give back the local mutex, taking the held count back to 0.
This time the priority of this task should be disinherited back to the
priority to which it was set while the mutex was held. This means
the medium priority task should execute and increment the guarded
variable. When this task next runs both the high and medium priority
tasks will have been suspended again. */
if( xSemaphoreGive( xLocalMutex ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
#if configUSE_PREEMPTION == 0
taskYIELD();
#endif
/* Check the guarded variable did indeed increment... */
if( ulGuardedVariable != 1 )
{
xErrorDetected = pdTRUE;
}
/* ... and that the priority of this task has been disinherited to
genqMUTEX_TEST_PRIORITY. */
if( uxTaskPriorityGet( NULL ) != genqMUTEX_TEST_PRIORITY )
{
xErrorDetected = pdTRUE;
}
/* Set the priority of this task back to its original value, ready for
the next loop around this test. */
vTaskPrioritySet( NULL, genqMUTEX_LOW_PRIORITY );
/* The second tests exercise the priority inheritance when two mutexes
are taken then returned in the same order in which they were taken. */
prvTakeTwoMutexesReturnInSameOrder( xMutex, xLocalMutex );
/* Just to show this task is still running. */
ulLoopCounter2++;
@ -612,12 +787,53 @@ SemaphoreHandle_t xMutex = ( SemaphoreHandle_t ) pvParameters;
}
/*-----------------------------------------------------------*/
/* NOTE: This function is not declared static to prevent compiler warnings in
demos where the function is declared but not used. */
void vInterruptMutexTask( void *pvParameters )
{
const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS );
volatile uint32_t ulLoops = 0;
/* Just to avoid compiler warnings. */
( void ) pvParameters;
for( ;; )
{
/* Has to wait longer than the time between gives to make sure it
should definitely have received the mutex. */
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
{
xErrorDetected = pdTRUE;
}
else
{
ulLoops++;
}
}
}
/*-----------------------------------------------------------*/
void vMutexISRInteractionTest( void )
{
static TickType_t xLastGiveTime = 0;
TickType_t xTimeNow;
xTimeNow = xTaskGetTickCountFromISR();
if( ( xTimeNow - xLastGiveTime ) >= pdMS_TO_TICKS( genqINTERRUPT_MUTEX_GIVE_PERIOD_MS ) )
{
configASSERT( xISRMutex );
xSemaphoreGiveFromISR( xISRMutex, NULL );
xLastGiveTime = xTimeNow;
}
}
/*-----------------------------------------------------------*/
/* This is called to check that all the created tasks are still running. */
BaseType_t xAreGenericQueueTasksStillRunning( void )
{
static uint32_t ulLastLoopCounter = 0, ulLastLoopCounter2 = 0;
/* If the demo task is still running then we expect the loopcounters to
/* If the demo task is still running then we expect the loop counters to
have incremented since this function was last called. */
if( ulLastLoopCounter == ulLoopCounter )
{

View File

@ -741,7 +741,12 @@ static TickType_t uxTick = ( TickType_t ) -1;
as well as late timer expiries. */
const TickType_t xMargin = 6;
#else
const TickType_t xMargin = 3;
#ifdef _WINDOWS_
/* Windows is not real real time. */
const TickType_t xMargin = 8;
#else
const TickType_t xMargin = 4;
#endif /* _WINDOWS_ */
#endif

View File

@ -1,5 +1,5 @@
/*
FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.
FreeRTOS V8.1.0 - Copyright (C) 2014 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -68,6 +68,7 @@
void vStartGenericQueueTasks( UBaseType_t uxPriority );
BaseType_t xAreGenericQueueTasksStillRunning( void );
void vMutexISRInteractionTest( void );
#endif /* GEN_Q_TEST_H */

View File

@ -297,7 +297,7 @@ volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
( void ) ulLine;
( void ) pcFileName;
taskENTER_CRITICAL();
taskENTER_CRITICAL();
{
/* Stop the trace recording. */
if( xPrinted == pdFALSE )

View File

@ -162,7 +162,7 @@ static void prvTestTask( void *pvParameters );
static void prvDemonstrateTaskStateAndHandleGetFunctions( void );
/*
* Called from the idle task hook function to demonstrate the use of
* Called from the idle task hook function to demonstrate the use of
* xTimerPendFunctionCall() as xTimerPendFunctionCall() is not demonstrated by
* any of the standard demo tasks.
*/
@ -401,6 +401,9 @@ void vFullDemoTickHookFunction( void )
/* Exercise event groups from interrupts. */
vPeriodicEventGroupsProcessing();
/* Exercise giving mutexes from an interrupt. */
vMutexISRInteractionTest();
}
/*-----------------------------------------------------------*/

View File

@ -73,7 +73,7 @@
typedef void (*TaskFunction_t)( void * );
/* Converts a time in milliseconds to a time in ticks. */
#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) xTimeInMs * configTICK_RATE_HZ ) / ( TickType_t ) 1000 )
#define pdMS_TO_TICKS( xTimeInMs ) ( ( ( TickType_t ) ( xTimeInMs ) * configTICK_RATE_HZ ) / ( TickType_t ) 1000 )
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )

View File

@ -1554,12 +1554,9 @@ eSleepModeStatus eTaskConfirmSleepModeStatus( void ) PRIVILEGED_FUNCTION;
/*
* For internal use only. Increment the mutex held count when a mutex is
* taken and decrement the mutex held count when the mutex is given back
* respectively. The mutex held count is used to know when it is safe to
* disinherit a priority.
* taken and return the handle of the task that has taken the mutex.
*/
void vTaskIncrementMutexHeldCount( void );
void vTaskDecrementMutexHeldCount( void );
void *pvTaskIncrementMutexHeldCount( void );
#ifdef __cplusplus
}

View File

@ -144,7 +144,7 @@ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
see http://www.freertos.org/Stacks-and-stack-overflow-checking.html
2) Incorrect interrupt priority assignment, especially on Cortex-M3
parts where numerically high priority values denote low actual
interrupt priories, which can seem counter intuitive. See
interrupt priorities, which can seem counter intuitive. See
configMAX_SYSCALL_INTERRUPT_PRIORITY on http://www.freertos.org/a00110.html
3) Calling an API function from within a critical section or when
the scheduler is suspended, or calling an API function that does

View File

@ -421,10 +421,7 @@ QueueHandle_t xReturn = NULL;
traceCREATE_MUTEX( pxNewQueue );
/* Start with the semaphore in the expected state. Preload the
mutex held count as calling xQueueGenericSend() will decrement the
count back to 0. */
vTaskIncrementMutexHeldCount();
/* Start with the semaphore in the expected state. */
( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK );
}
else
@ -702,7 +699,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
the mutexes were given back in an order that is
different to that in which they were taken. */
queueYIELD_IF_USING_PREEMPTION();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
@ -1125,8 +1122,8 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
{
/* The task waiting has a higher priority so record that a
context switch is required. */
/* The task waiting has a higher priority so
record that a context switch is required. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
@ -1243,7 +1240,7 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
{
/* Record the information required to implement
priority inheritance should it become necessary. */
pxQueue->pxMutexHolder = ( int8_t * ) xTaskGetCurrentTaskHandle(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
pxQueue->pxMutexHolder = ( int8_t * ) pvTaskIncrementMutexHeldCount(); /*lint !e961 Cast is not redundant as TaskHandle_t is a typedef. */
}
else
{
@ -1633,7 +1630,6 @@ BaseType_t xReturn = pdFALSE;
if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX )
{
/* The mutex is no longer being held. */
vTaskDecrementMutexHeldCount();
xReturn = xTaskPriorityDisinherit( ( void * ) pxQueue->pxMutexHolder );
pxQueue->pxMutexHolder = NULL;
}
@ -1699,7 +1695,7 @@ BaseType_t xReturn = pdFALSE;
static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )
{
if( pxQueue->uxQueueType != queueQUEUE_IS_MUTEX )
if( pxQueue->uxItemSize != 0 )
{
pxQueue->u.pcReadFrom += pxQueue->uxItemSize;
if( pxQueue->u.pcReadFrom >= pxQueue->pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
@ -1712,11 +1708,6 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer
}
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. */
}
else
{
/* A mutex was taken. */
vTaskIncrementMutexHeldCount();
}
}
/*-----------------------------------------------------------*/

View File

@ -553,14 +553,14 @@ TCB_t * pxNewTCB;
pxTopOfStack = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack ) & ( ( portPOINTER_SIZE_TYPE ) ~portBYTE_ALIGNMENT_MASK ) ); /*lint !e923 MISRA exception. Avoiding casts between pointers and integers is not practical. Size differences accounted for using portPOINTER_SIZE_TYPE type. */
/* Check the alignment of the calculated top of stack is correct. */
configASSERT( ( ( ( uint32_t ) pxTopOfStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxTopOfStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
}
#else /* portSTACK_GROWTH */
{
pxTopOfStack = pxNewTCB->pxStack;
/* Check the alignment of the stack buffer is correct. */
configASSERT( ( ( ( uint32_t ) pxNewTCB->pxStack & ( uint32_t ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
configASSERT( ( ( ( portPOINTER_SIZE_TYPE ) pxNewTCB->pxStack & ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );
/* If we want to use stack checking on architectures that use
a positive stack growth direction then we also need to store the
@ -3246,6 +3246,9 @@ TCB_t *pxTCB;
if( pxMutexHolder != NULL )
{
configASSERT( pxTCB->uxMutexesHeld );
( pxTCB->uxMutexesHeld )--;
if( pxTCB->uxPriority != pxTCB->uxBasePriority )
{
/* Only disinherit if no other mutexes are held. */
@ -3584,7 +3587,7 @@ TickType_t uxReturn;
}
/*-----------------------------------------------------------*/
void vTaskIncrementMutexHeldCount( void )
void *pvTaskIncrementMutexHeldCount( void )
{
#if ( configUSE_MUTEXES == 1 )
{
@ -3594,26 +3597,13 @@ void vTaskIncrementMutexHeldCount( void )
{
( pxCurrentTCB->uxMutexesHeld )++;
}
return pxCurrentTCB;
}
#endif
}
/*-----------------------------------------------------------*/
void vTaskDecrementMutexHeldCount( void )
{
#if ( configUSE_MUTEXES == 1 )
{
/* If xSemaphoreCreateMutex() is called before any tasks have been created
then pxCurrentTCB will be NULL. */
if( pxCurrentTCB != NULL )
{
configASSERT( pxCurrentTCB->uxMutexesHeld );
( pxCurrentTCB->uxMutexesHeld )--;
}
}
#endif
}
#ifdef FREERTOS_MODULE_TEST
#include "tasks_test_access_functions.h"
#endif