SignalObjectAndWait( pvInterruptEventMutex, pvTickAcknowledgeEvent, INFINITE, FALSE );\r
}\r
\r
- /* Should never reach here. */\r
- return 0;\r
+ #ifdef __GNUC__\r
+ /* Should never reach here - MingW complains if you leave this line out,\r
+ MSVC complains if you put it in. */\r
+ return 0;\r
+ #endif\r
}\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
pseudo interrupts take priority over tasks. */\r
- SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS );\r
pvHandle = GetCurrentThread();\r
if( pvHandle == NULL )\r
{\r
\r
if( lSuccess == pdPASS )\r
{\r
- if( SetThreadPriority( pvHandle, THREAD_PRIORITY_HIGHEST ) == 0 )\r
+ if( SetThreadPriority( pvHandle, THREAD_PRIORITY_BELOW_NORMAL ) == 0 )\r
{\r
lSuccess = pdFAIL;\r
}\r
pvHandle = CreateThread( NULL, 0, prvSimulatedPeripheralTimer, NULL, 0, NULL );\r
if( pvHandle != NULL )\r
{\r
- SetThreadPriority( pvHandle, THREAD_PRIORITY_HIGHEST );\r
+ SetThreadPriority( pvHandle, THREAD_PRIORITY_NORMAL );\r
SetThreadPriorityBoost( pvHandle, TRUE );\r
SetThreadAffinityMask( pvHandle, 0x01 );\r
}\r
/* Bump up the priority of the thread that is going to run, in the\r
hope that this will asist in getting the Windows thread scheduler to\r
behave as an embedded engineer might expect. */\r
- SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_ABOVE_NORMAL );\r
ResumeThread( pxThreadState->pvThread );\r
\r
/* Handle all pseudo interrupts - including yield requests and \r
\r
static void prvProcessPseudoInterrupts( void )\r
{\r
-long lSwitchRequired;\r
+long lSwitchRequired, lCurrentTaskBeingDeleted;\r
xThreadState *pxThreadState;\r
void *pvObjectList[ 2 ];\r
unsigned long i;\r
/* Used to indicate whether the pseudo interrupt processing has\r
necessitated a context switch to another task/thread. */\r
lSwitchRequired = pdFALSE;\r
+ lCurrentTaskBeingDeleted = pdFALSE;\r
\r
/* For each interrupt we are interested in processing, each of which is\r
represented by a bit in the 32bit ulPendingInterrupts variable. */\r
SetEvent( pvTickAcknowledgeEvent );\r
break;\r
\r
+ case portINTERRUPT_DELETE_THREAD:\r
+\r
+ lCurrentTaskBeingDeleted = pdTRUE;\r
+\r
+ /* Clear the interrupt pending bit. */\r
+ ulPendingInterrupts &= ~( 1UL << portINTERRUPT_DELETE_THREAD );\r
+ break;\r
+\r
default:\r
\r
/* Is a handler installed? */\r
}\r
}\r
\r
- if( lSwitchRequired != pdFALSE )\r
+ if( ( lSwitchRequired != pdFALSE ) || ( lCurrentTaskBeingDeleted != pdFALSE ) )\r
{\r
void *pvOldCurrentTCB;\r
\r
{\r
/* Suspend the old thread. */\r
pxThreadState = ( xThreadState *) *( ( unsigned long * ) pvOldCurrentTCB );\r
- SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_IDLE );\r
- SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
- SuspendThread( pxThreadState->pvThread );\r
- \r
-\r
-\r
- /* NOTE! - Here lies a problem when the preemptive scheduler is \r
- used. It would seem Win32 threads do not stop as soon as a\r
- call to suspend them is made. The co-operative scheduler gets\r
- around this by having the thread block on a semaphore \r
- immediately after yielding so it cannot execute any more task\r
- code until it is once again scheduled to run. This cannot be\r
- done if the task is pre-empted though, and I have not found an\r
- equivalent work around for the preemptive situation. */\r
- \r
\r
+ if( lCurrentTaskBeingDeleted != pdFALSE )\r
+ {\r
+ TerminateThread( pxThreadState->pvThread, 0 );\r
+ }\r
+ else\r
+ {\r
+ SuspendThread( pxThreadState->pvThread );\r
+ } \r
\r
/* Obtain the state of the task now selected to enter the \r
Running state. */\r
pxThreadState = ( xThreadState * ) ( *( unsigned long *) pxCurrentTCB );\r
-\r
- /* Boost the priority of the thread selected to run a little \r
- in an attempt to get the Windows thread scheduler to act a \r
- little more like an embedded engineer might expect. */\r
- SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_ABOVE_NORMAL );\r
- SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
ResumeThread( pxThreadState->pvThread );\r
}\r
}\r
}\r
/*-----------------------------------------------------------*/\r
\r
+void vPortDeleteThread( void *pvTaskToDelete )\r
+{\r
+xThreadState *pxThreadState;\r
+\r
+ if( pvTaskToDelete == pxCurrentTCB )\r
+ {\r
+ /* The task is deleting itself, and so the thread that is running now\r
+ is also to be deleted. This has to be deferred until this thread is\r
+ no longer running, so its done in the pseudo interrupt handler thread. */\r
+ vPortGeneratePseudoInterrupt( portINTERRUPT_DELETE_THREAD );\r
+ }\r
+ else\r
+ {\r
+ WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
+\r
+ /* Find the handle of the thread being deleted. */\r
+ pxThreadState = ( xThreadState * ) ( *( unsigned long *) pvTaskToDelete );\r
+ TerminateThread( pxThreadState->pvThread, 0 );\r
+\r
+ ReleaseMutex( pvInterruptEventMutex );\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
void vPortEndScheduler( void )\r
{\r
+ /* This function IS NOT TESTED! */\r
+ TerminateProcess( GetCurrentProcess(), 0 );\r
}\r
/*-----------------------------------------------------------*/\r
\r