]> git.sur5r.net Git - freertos/commitdiff
Add trace macros into the event groups implementation.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 12 Dec 2013 10:19:07 +0000 (10:19 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 12 Dec 2013 10:19:07 +0000 (10:19 +0000)
Add a task pre-delete hook to allow the insertion of any port specific clean up when a task is deleted.
Increase use of 'const' qualifiers.
Add vPortCloseRunningThread() into the Win32 port layer to attempt to allow Windows threads to be closed more gracefully when a task deletes itself.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2128 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Source/event_groups.c
FreeRTOS/Source/include/FreeRTOS.h
FreeRTOS/Source/include/task.h
FreeRTOS/Source/portable/MSVC-MingW/port.c
FreeRTOS/Source/portable/MSVC-MingW/portmacro.h
FreeRTOS/Source/tasks.c

index 70011c38864cc68088aad97ac33773768a9541e1..644539965556901cc9870e2fc5938bad2850a833 100644 (file)
@@ -128,6 +128,11 @@ xEVENT_BITS *pxEventBits;
        {\r
                pxEventBits->uxEventBits = 0;\r
                vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );\r
+               traceEVENT_GROUP_CREATE( pxEventBits );         \r
+       }\r
+       else\r
+       {\r
+               traceEVENT_GROUP_CREATE_FAILED();\r
        }\r
 \r
        return ( xEventGroupHandle ) pxEventBits;\r
@@ -148,6 +153,8 @@ portBASE_TYPE xYieldedAlready;
 \r
        vTaskSuspendAll();\r
        {\r
+               traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet );\r
+\r
                uxOriginalBitValue = pxEventBits->uxEventBits;\r
 \r
                ( void ) xEventGroupSetBits( xEventGroup, uxBitsToSet );\r
@@ -172,6 +179,11 @@ portBASE_TYPE xYieldedAlready;
                                task's event list item so the kernel knows when a match is\r
                                found.  Then enter the blocked state. */\r
                                vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | taskCLEAR_EVENTS_ON_EXIT_BIT | taskWAIT_FOR_ALL_BITS ), xTicksToWait );\r
+\r
+                               /* This is obsolete as it will get set after the task unblocks,\r
+                               but some compilers mistakenly generate a warning about the\r
+                               variable being returned without being set if it is not done. */\r
+                               uxReturn = 0;\r
                        }\r
                        else\r
                        {\r
@@ -209,6 +221,7 @@ portBASE_TYPE xYieldedAlready;
                }\r
        }\r
 \r
+       traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn );\r
        return uxReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -232,6 +245,8 @@ xEventBitsType uxReturn, uxControlBits = 0;
        {\r
                const xEventBitsType uxCurrentEventBits = pxEventBits->uxEventBits;\r
 \r
+               traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor );\r
+\r
                if( xWaitForAllBits == pdFALSE )\r
                {\r
                        /* Task only has to wait for one bit within uxBitsToWaitFor to be set.  Is\r
@@ -288,6 +303,11 @@ xEventBitsType uxReturn, uxControlBits = 0;
                        found.  Then enter the blocked state. */\r
                        vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );\r
                        portYIELD_WITHIN_API();\r
+\r
+                       /* This is obsolete as it will get set after the task unblocks, but\r
+                       some compilers mistakenly generate a warning about the variable\r
+                       being returned without being set if it is not done. */\r
+                       uxReturn = 0;\r
                }\r
        }\r
        taskEXIT_CRITICAL();\r
@@ -313,6 +333,7 @@ xEventBitsType uxReturn, uxControlBits = 0;
                }\r
        }\r
 \r
+       traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn );\r
        return uxReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -329,6 +350,8 @@ xEventBitsType uxReturn;
        uxBitsToClear = ~uxBitsToClear;\r
        taskENTER_CRITICAL();\r
        {\r
+               traceEVENT_GROUP_CLEAR_BITS( xEventGroup, ~uxBitsToClear );\r
+\r
                /* The value returned is the event group value prior to the bits being\r
                cleared. */\r
                uxReturn = pxEventBits->uxEventBits;\r
@@ -359,6 +382,8 @@ portBASE_TYPE xMatchFound = pdFALSE;
        pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */\r
        vTaskSuspendAll();\r
        {\r
+               traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );\r
+\r
                pxListItem = listGET_HEAD_ENTRY( pxList );\r
 \r
                /* Set the bits. */\r
@@ -432,6 +457,8 @@ const xList *pxTasksWaitingForBits = &( pxEventBits->xTasksWaitingForBits );
 \r
        vTaskSuspendAll();\r
        {\r
+               traceEVENT_GROUP_DELETE( xEventGroup );\r
+\r
                while( listCURRENT_LIST_LENGTH( pxTasksWaitingForBits ) > ( unsigned portBASE_TYPE ) 0 )\r
                {\r
                        /* Unblock the task, returning 0 as the event list is being deleted\r
index 7832f5547dd2d97df3d2f4bf4c302a674dfd99e3..e4a1edd312dcd8bd38309b22370941bf03aa3e56 100644 (file)
@@ -136,11 +136,11 @@ typedef portTickType xEventBitsType;
 #endif\r
 \r
 #ifndef INCLUDE_vTaskDelete\r
-       #error Missing definition:  INCLUDE_vTaskDelete          must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.\r
+       #error Missing definition:  INCLUDE_vTaskDelete must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.\r
 #endif\r
 \r
 #ifndef INCLUDE_vTaskSuspend\r
-       #error Missing definition:  INCLUDE_vTaskSuspend         must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.\r
+       #error Missing definition:  INCLUDE_vTaskSuspend must be defined in FreeRTOSConfig.h as either 1 or 0.  See the Configuration section of the FreeRTOS API documentation for details.\r
 #endif\r
 \r
 #ifndef INCLUDE_vTaskDelayUntil\r
@@ -156,13 +156,13 @@ typedef portTickType xEventBitsType;
 #endif\r
 \r
 #if configUSE_CO_ROUTINES != 0\r
-       #if configMAX_CO_ROUTINE_PRIORITIES < 1\r
+       #ifndef configMAX_CO_ROUTINE_PRIORITIES\r
                #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1.\r
        #endif\r
 #endif\r
 \r
-#if configMAX_PRIORITIES  < 1\r
-       #error configMAX_PRIORITIES  must be greater than or equal to 1.\r
+#ifndef configMAX_PRIORITIES\r
+       #error configMAX_PRIORITIES must be defined to be greater than or equal to 1.\r
 #endif\r
 \r
 #ifndef INCLUDE_xTaskGetIdleTaskHandle\r
@@ -294,6 +294,10 @@ typedef portTickType xEventBitsType;
        #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB\r
 #endif\r
 \r
+#ifndef portPRE_DELETE_HOOK\r
+       #define portPRE_DELETE_HOOK( pvTaskToDelete, pxYieldPending )\r
+#endif\r
+\r
 #ifndef portSETUP_TCB\r
        #define portSETUP_TCB( pxTCB ) ( void ) pxTCB\r
 #endif\r
@@ -551,6 +555,42 @@ typedef portTickType xEventBitsType;
     #define traceFREE( pvAddress, uiSize )\r
 #endif\r
 \r
+#ifndef traceEVENT_GROUP_CREATE\r
+       #define traceEVENT_GROUP_CREATE( xEventGroup )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_CREATE_FAILED\r
+       #define traceEVENT_GROUP_CREATE_FAILED()\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_SYNC_START\r
+       #define traceEVENT_GROUP_SYNC_START( xEventGroup, uxBitsToSet )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_SYNC_END\r
+       #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxReturn )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_WAIT_BITS_START\r
+       #define traceEVENT_GROUP_WAIT_BITS_START( xEventGroup, uxBitsToWaitFor )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_WAIT_BITS_END\r
+       #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxReturn )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_CLEAR_BITS\r
+       #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_SET_BITS\r
+       #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet )\r
+#endif\r
+\r
+#ifndef traceEVENT_GROUP_DELETE\r
+       #define traceEVENT_GROUP_DELETE( xEventGroup )\r
+#endif\r
+\r
 #ifndef configGENERATE_RUN_TIME_STATS\r
        #define configGENERATE_RUN_TIME_STATS 0\r
 #endif\r
index 956556e67bfea3405d468a4d5678c1c5a85b8e21..288c783fe203d2b5c9809aafcb47f8aea2226821 100644 (file)
@@ -1412,8 +1412,8 @@ portBASE_TYPE xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
  * portTICK_RATE_MS can be used to convert kernel ticks into a real time\r
  * period.\r
  */\r
-void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
-void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+void vTaskPlaceOnEventList( xList * const pxEventList, const portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
+void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, const portTickType xTicksToWait ) PRIVILEGED_FUNCTION;\r
 \r
 /*\r
  * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN\r
index 35e40cb61fae07f622e6f6aacb439715c5a82358..8e8e82d5f9e8242c060f5f184fc5022ca929f915 100644 (file)
@@ -244,6 +244,7 @@ char *pcTopOfStack = ( char * ) pxTopOfStack;
 \r
        /* Create the thread itself. */\r
        pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );\r
+       configASSERT( pxThreadState->pvThread );\r
        SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );\r
        SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
        SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_IDLE );\r
@@ -418,13 +419,51 @@ void vPortDeleteThread( void *pvTaskToDelete )
 {\r
 xThreadState *pxThreadState;\r
 \r
-       WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
+       /* Find the handle of the thread being deleted. */\r
+       pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );\r
+\r
+       /* Check that the thread is still valid, it might have been closed by\r
+       vPortCloseRunningThread() - which will be the case if the task associated\r
+       with the thread originally deleted itself rather than being deleted by a\r
+       different task. */\r
+       if( pxThreadState->pvThread != NULL )\r
+       {\r
+               WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
+\r
+               CloseHandle( pxThreadState->pvThread );\r
+               TerminateThread( pxThreadState->pvThread, 0 );\r
+\r
+               ReleaseMutex( pvInterruptEventMutex );\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortCloseRunningThread( void *pvTaskToDelete, volatile portBASE_TYPE *pxPendYield )\r
+{\r
+xThreadState *pxThreadState;\r
+void *pvThread;\r
 \r
        /* Find the handle of the thread being deleted. */\r
        pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );\r
-       TerminateThread( pxThreadState->pvThread, 0 );\r
+       pvThread = pxThreadState->pvThread;\r
+\r
+       /* Raise the Windows priority of the thread to ensure the FreeRTOS scheduler\r
+       does not run and swap it out before it is closed.  If that were to happen\r
+       the thread would never run again and effectively be a thread handle and\r
+       memory leak. */\r
+       SetThreadPriority( pvThread, THREAD_PRIORITY_ABOVE_NORMAL );\r
+\r
+       /* This function will not return, therefore a yield is set as pending to\r
+       ensure a context switch occurs away from this thread on the next tick. */\r
+       *pxPendYield = pdTRUE;\r
+\r
+       /* Mark the thread associated with this task as invalid so \r
+       vPortDeleteThread() does not try to terminate it. */\r
+       pxThreadState->pvThread = NULL;\r
 \r
-       ReleaseMutex( pvInterruptEventMutex );\r
+       /* Close the thread. */\r
+       CloseHandle( pvThread );\r
+       ExitThread( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index 518223622c8314a09845dfe2352d231157444f99..03a9bc981d91fc0862621fd2c69108fabf0fcde2 100644 (file)
@@ -139,7 +139,7 @@ void vPortExitCritical( void );
 #define portINTERRUPT_YIELD                            ( 0UL )\r
 #define portINTERRUPT_TICK                             ( 1UL )\r
 \r
-/* \r
+/*\r
  * Raise a simulated interrupt represented by the bit mask in ulInterruptMask.\r
  * Each bit can be used to represent an individual interrupt - with the first\r
  * two bits being used for the Yield and Tick interrupts respectively.\r
@@ -147,13 +147,13 @@ void vPortExitCritical( void );
 void vPortGenerateSimulatedInterrupt( unsigned long ulInterruptNumber );\r
 \r
 /*\r
- * Install an interrupt handler to be called by the simulated interrupt handler \r
+ * Install an interrupt handler to be called by the simulated interrupt handler\r
  * thread.  The interrupt number must be above any used by the kernel itself\r
  * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2\r
- * as defined above).  The number must also be lower than 32. \r
+ * as defined above).  The number must also be lower than 32.\r
  *\r
  * Interrupt handler functions must return a non-zero value if executing the\r
- * handler resulted in a task switch being required. \r
+ * handler resulted in a task switch being required.\r
  */\r
 void vPortSetInterruptHandler( unsigned long ulInterruptNumber, unsigned long (*pvHandler)( void ) );\r
 \r
index bf7475ab11e4dd1227a2a67b60b863bd76ab35c5..c3284ca3e7e06d16f50c26e4124da91f1cf079c5 100644 (file)
@@ -685,6 +685,13 @@ tskTCB * pxNewTCB;
                        if( pxTCB == pxCurrentTCB )\r
                        {\r
                                configASSERT( uxSchedulerSuspended == 0 );\r
+\r
+                               /* The pre-delete hook is primarily for the Windows simulator,\r
+                               in which Windows specific clean up operations are performed,\r
+                               after which it is not possible to yield away from this task - \r
+                               hence xYieldPending is used to latch that a context switch is\r
+                               required. */\r
+                               portPRE_DELETE_HOOK( pxTCB, &xYieldPending );\r
                                portYIELD_WITHIN_API();\r
                        }\r
                }\r
@@ -1896,7 +1903,7 @@ void vTaskSwitchContext( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vTaskPlaceOnEventList( xList * const pxEventList, portTickType xTicksToWait )\r
+void vTaskPlaceOnEventList( xList * const pxEventList, const portTickType xTicksToWait )\r
 {\r
 portTickType xTimeToWake;\r
 \r
@@ -1948,7 +1955,7 @@ portTickType xTimeToWake;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, portTickType xTicksToWait )\r
+void vTaskPlaceOnUnorderedEventList( xList * pxEventList, portTickType xItemValue, const portTickType xTicksToWait )\r
 {\r
 portTickType xTimeToWake;\r
 \r