]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/MSVC-MingW/port.c
Update version number in preparation for maintenance release.
[freertos] / FreeRTOS / Source / portable / MSVC-MingW / port.c
index ad023f1eff4bfe861b5c6baad6a22a4c23cdeef2..54292288b60ba521e07bb7d5c5c63172c2b725d8 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-    FreeRTOS V9.0.0rc1 - Copyright (C) 2016 Real Time Engineers Ltd.\r
+    FreeRTOS V9.0.1 - Copyright (C) 2017 Real Time Engineers Ltd.\r
     All rights reserved\r
 \r
     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
 #define portMAX_INTERRUPTS                             ( ( uint32_t ) sizeof( uint32_t ) * 8UL ) /* The number of bits in an uint32_t. */\r
 #define portNO_CRITICAL_NESTING                ( ( uint32_t ) 0 )\r
 \r
-/* The priorities at which the various components of the simulation execute.\r
-Priorities are higher when a soak test is performed to lessen the effect of\r
-Windows interfering with the timing. */\r
-#define portSOAK_TEST\r
-#ifndef portSOAK_TEST\r
-       #define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_NORMAL\r
-       #define portSIMULATED_TIMER_THREAD_PRIORITY              THREAD_PRIORITY_BELOW_NORMAL\r
-       #define portTASK_THREAD_PRIORITY                                 THREAD_PRIORITY_IDLE\r
-#else\r
-       #define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_TIME_CRITICAL\r
-       #define portSIMULATED_TIMER_THREAD_PRIORITY              THREAD_PRIORITY_HIGHEST\r
-       #define portTASK_THREAD_PRIORITY                                 THREAD_PRIORITY_ABOVE_NORMAL\r
-#endif\r
+/* The priorities at which the various components of the simulation execute. */\r
+#define portDELETE_SELF_THREAD_PRIORITY                         THREAD_PRIORITY_TIME_CRITICAL /* Must be highest. */\r
+#define portSIMULATED_INTERRUPTS_THREAD_PRIORITY THREAD_PRIORITY_TIME_CRITICAL\r
+#define portSIMULATED_TIMER_THREAD_PRIORITY             THREAD_PRIORITY_HIGHEST\r
+#define portTASK_THREAD_PRIORITY                                THREAD_PRIORITY_ABOVE_NORMAL\r
+\r
 /*\r
  * Created as a high priority thread, this function uses a timer to simulate\r
  * a tick interrupt being generated on an embedded target.  In this Windows\r
@@ -260,16 +253,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
 {\r
 xThreadState *pxThreadState = NULL;\r
 int8_t *pcTopOfStack = ( int8_t * ) pxTopOfStack;\r
-\r
-       #ifdef portSOAK_TEST\r
-       {\r
-               /* Ensure highest priority class is inherited. */\r
-               if( !SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS ) )\r
-               {\r
-                       printf( "SetPriorityClass() failed\r\n" );\r
-               }\r
-       }\r
-       #endif\r
+const SIZE_T xStackSize = 1024; /* Set the size to a small number which will get rounded up to the minimum possible. */\r
 \r
        /* In this simulated case a stack is not initialised, but instead a thread\r
        is created that will execute the task being created.  The thread handles\r
@@ -280,8 +264,8 @@ int8_t *pcTopOfStack = ( int8_t * ) pxTopOfStack;
        pxThreadState = ( xThreadState * ) ( pcTopOfStack - sizeof( xThreadState ) );\r
 \r
        /* Create the thread itself. */\r
-       pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );\r
-       configASSERT( pxThreadState->pvThread );\r
+       pxThreadState->pvThread = CreateThread( NULL, xStackSize, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, NULL );\r
+       configASSERT( pxThreadState->pvThread ); /* See comment where TerminateThread() is called. */\r
        SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );\r
        SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
        SetThreadPriority( pxThreadState->pvThread, portTASK_THREAD_PRIORITY );\r
@@ -292,31 +276,53 @@ int8_t *pcTopOfStack = ( int8_t * ) pxTopOfStack;
 \r
 BaseType_t xPortStartScheduler( void )\r
 {\r
-void *pvHandle;\r
-int32_t lSuccess = pdPASS;\r
-xThreadState *pxThreadState;\r
-\r
-       /* Install the interrupt handlers used by the scheduler itself. */\r
-       vPortSetInterruptHandler( portINTERRUPT_YIELD, prvProcessYieldInterrupt );\r
-       vPortSetInterruptHandler( portINTERRUPT_TICK, prvProcessTickInterrupt );\r
-\r
-       /* Create the events and mutexes that are used to synchronise all the\r
-       threads. */\r
-       pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL );\r
-       pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
+void *pvHandle = NULL;\r
+int32_t lSuccess;\r
+xThreadState *pxThreadState = NULL;\r
+SYSTEM_INFO xSystemInfo;\r
 \r
-       if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) )\r
+       /* This port runs windows threads with extremely high priority.  All the\r
+       threads execute on the same core - to prevent locking up the host only start\r
+       if the host has multiple cores. */\r
+       GetSystemInfo( &xSystemInfo );\r
+       if( xSystemInfo.dwNumberOfProcessors <= 1 )\r
        {\r
+               printf( "This version of the FreeRTOS Windows port can only be used on multi-core hosts.\r\n" );\r
                lSuccess = pdFAIL;\r
        }\r
-\r
-       /* Set the priority of this thread such that it is above the priority of\r
-       the threads that run tasks.  This higher priority is required to ensure\r
-       simulated interrupts take priority over tasks. */\r
-       pvHandle = GetCurrentThread();\r
-       if( pvHandle == NULL )\r
+       else\r
        {\r
-               lSuccess = pdFAIL;\r
+               lSuccess = pdPASS;\r
+\r
+               /* The highest priority class is used to [try to] prevent other Windows\r
+               activity interfering with FreeRTOS timing too much. */\r
+               if( SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS ) == 0 )\r
+               {\r
+                       printf( "SetPriorityClass() failed\r\n" );\r
+               }\r
+\r
+               /* Install the interrupt handlers used by the scheduler itself. */\r
+               vPortSetInterruptHandler( portINTERRUPT_YIELD, prvProcessYieldInterrupt );\r
+               vPortSetInterruptHandler( portINTERRUPT_TICK, prvProcessTickInterrupt );\r
+\r
+               /* Create the events and mutexes that are used to synchronise all the\r
+               threads. */\r
+               pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL );\r
+               pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
+\r
+               if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) )\r
+               {\r
+                       lSuccess = pdFAIL;\r
+               }\r
+\r
+               /* Set the priority of this thread such that it is above the priority of\r
+               the threads that run tasks.  This higher priority is required to ensure\r
+               simulated interrupts take priority over tasks. */\r
+               pvHandle = GetCurrentThread();\r
+               if( pvHandle == NULL )\r
+               {\r
+                       lSuccess = pdFAIL;\r
+               }\r
        }\r
 \r
        if( lSuccess == pdPASS )\r
@@ -488,6 +494,10 @@ uint32_t ulErrorCode;
        {\r
                WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
 \r
+               /* !!! This is not a nice way to terminate a thread, and will eventually\r
+               result in resources being depleted if tasks frequently delete other\r
+               tasks (rather than deleting themselves) as the task stacks will not be\r
+               freed. */\r
                ulErrorCode = TerminateThread( pxThreadState->pvThread, 0 );\r
                configASSERT( ulErrorCode );\r
 \r
@@ -516,7 +526,7 @@ uint32_t ulErrorCode;
        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_HIGHEST );\r
+       SetThreadPriority( pvThread, portDELETE_SELF_THREAD_PRIORITY );\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
@@ -530,6 +540,10 @@ uint32_t ulErrorCode;
        ulErrorCode = CloseHandle( pvThread );\r
        configASSERT( ulErrorCode );\r
 \r
+       /* This is called from a critical section, which must be exited before the\r
+       thread stops. */\r
+       taskEXIT_CRITICAL();\r
+\r
        ExitThread( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r