to a thread handle. */\r
typedef struct\r
{\r
- /* Set to true if the task run by the thread yielded control to the pseudo\r
- interrupt handler manually - either by yielding or when exiting a critical\r
- section while pseudo interrupts were pending. */\r
- long lWaitingInterruptAck; \r
-\r
/* Handle of the thread that executes the task. */\r
void *pvThread;\r
\r
- /* Used to check that the thread that is supposed to be running in indeed\r
- the thread that is running. */\r
- unsigned long ulThreadId;\r
-\r
} xThreadState;\r
\r
/* Pseudo interrupts waiting to be processed. This is a bit mask where each\r
static void *pvInterruptEventMutex = NULL;\r
\r
/* Events used to manage sequencing. */\r
-static void *pvTickAcknowledgeEvent = NULL, *pvInterruptAcknowledgeEvent = NULL;\r
+static void *pvTickAcknowledgeEvent = NULL;\r
\r
/* The critical nesting count for the currently executing task. This is \r
initialised to a non-zero value so interrupts do not become enabled during \r
\r
WaitForSingleObject( pvInterruptEventMutex, INFINITE );\r
\r
- /* A thread will hold the interrupt event mutex while in a critical\r
- section, so ulCriticalSection should be zero for this tick event to be\r
- possible. */\r
- if( ulCriticalNesting != 0 )\r
- {\r
- /* For a break point only. */\r
- __asm{ NOP };\r
- }\r
-\r
/* The timer has expired, generate the simulated tick event. */\r
ulPendingInterrupts |= ( 1 << portINTERRUPT_TICK );\r
\r
pseudo interrupt handler thread to acknowledge the tick. */\r
SignalObjectAndWait( pvInterruptEventMutex, pvTickAcknowledgeEvent, INFINITE, FALSE );\r
}\r
+\r
+ /* Should never reach here. */\r
+ return 0;\r
}\r
/*-----------------------------------------------------------*/\r
\r
pxThreadState = ( xThreadState * ) ( pxTopOfStack - sizeof( xThreadState ) );\r
\r
/* Create the thread itself. */\r
- pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, &( pxThreadState->ulThreadId ) );\r
+ pxThreadState->pvThread = CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) pxCode, pvParameters, CREATE_SUSPENDED, NULL );\r
+ SetThreadAffinityMask( pxThreadState->pvThread, 0x01 );\r
SetThreadPriorityBoost( pxThreadState->pvThread, TRUE );\r
- pxThreadState->lWaitingInterruptAck = pdFALSE;\r
SetThreadPriority( pxThreadState->pvThread, THREAD_PRIORITY_IDLE );\r
\r
return ( portSTACK_TYPE * ) pxThreadState;\r
pvInterruptEventMutex = CreateMutex( NULL, FALSE, NULL );\r
pvInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
pvTickAcknowledgeEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
- pvInterruptAcknowledgeEvent = CreateEvent( NULL, FALSE, FALSE, NULL );\r
\r
- if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) || ( pvTickAcknowledgeEvent == NULL ) || ( pvInterruptAcknowledgeEvent == NULL ) )\r
+ if( ( pvInterruptEventMutex == NULL ) || ( pvInterruptEvent == NULL ) || ( pvTickAcknowledgeEvent == NULL ) )\r
{\r
lSuccess = pdFAIL;\r
}\r
lSuccess = pdFAIL;\r
}\r
SetThreadPriorityBoost( pvHandle, TRUE );\r
+ SetThreadAffinityMask( pvHandle, 0x01 );\r
}\r
\r
if( lSuccess == pdPASS )\r
{\r
SetThreadPriority( pvHandle, THREAD_PRIORITY_HIGHEST );\r
SetThreadPriorityBoost( pvHandle, TRUE );\r
+ SetThreadAffinityMask( pvHandle, 0x01 );\r
}\r
\r
/* Start the highest priority task by obtaining its associated thread \r
{\r
WaitForMultipleObjects( sizeof( pvObjectList ) / sizeof( void * ), pvObjectList, TRUE, INFINITE );\r
\r
- /* A thread will hold the interrupt event mutex while in a critical\r
- section, so this pseudo interrupt handler should only run when\r
- critical nesting is zero. */\r
- if( ulCriticalNesting != 0 )\r
- {\r
- /* For a break point only. */\r
- __asm{ NOP };\r
- }\r
-\r
/* Used to indicate whether the pseudo interrupt processing has\r
necessitated a context switch to another task/thread. */\r
lSwitchRequired = pdFALSE;\r
}\r
}\r
\r
- /* On exiting a critical section a task may have blocked on the\r
- interrupt event when only a tick needed processing, in which case\r
- it will not have been released from waiting on the event yet. */\r
- pxThreadState = ( xThreadState * ) ( *( unsigned long *) pxCurrentTCB );\r
- if( pxThreadState->lWaitingInterruptAck == pdTRUE )\r
- {\r
- pxThreadState->lWaitingInterruptAck = pdFALSE;\r
- SetEvent( pvInterruptAcknowledgeEvent );\r
- }\r
-\r
ReleaseMutex( pvInterruptEventMutex );\r
}\r
}\r
/* The event handler needs to know to signal the interrupt acknowledge event\r
the next time this task runs. */\r
pxThreadState = ( xThreadState * ) *( ( unsigned long * ) pxCurrentTCB );\r
- pxThreadState->lWaitingInterruptAck = pdTRUE;\r
-\r
- SetEvent( pvInterruptEvent );\r
-\r
- /* The interrupt ack event should not be signaled yet - if it is then there\r
- is an error in the logical simulation. */\r
- if( WaitForSingleObject( pvInterruptAcknowledgeEvent, 0 ) != WAIT_TIMEOUT )\r
- {\r
- /* This line is for a break point only. */\r
- __asm { NOP };\r
- }\r
-\r
- SignalObjectAndWait( pvInterruptEventMutex, pvInterruptAcknowledgeEvent, INFINITE, FALSE );\r
- }\r
- else\r
- {\r
- ReleaseMutex( pvInterruptEventMutex );\r
+ SetEvent( pvInterruptEvent ); \r
}\r
+\r
+ ReleaseMutex( pvInterruptEventMutex );\r
}\r
}\r
/*-----------------------------------------------------------*/\r
/* The event handler needs to know to signal the interrupt \r
acknowledge event the next time this task runs. */\r
pxThreadState = ( xThreadState * ) *( ( unsigned long * ) pxCurrentTCB );\r
- pxThreadState->lWaitingInterruptAck = pdTRUE;\r
\r
/* Mutex will be released now, so does not require releasing\r
on function exit. */\r
lMutexNeedsReleasing = pdFALSE;\r
- SignalObjectAndWait( pvInterruptEventMutex, pvInterruptAcknowledgeEvent, INFINITE, FALSE );\r
+ ReleaseMutex( pvInterruptEventMutex );\r
}\r
}\r
else\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vPortCheckCorrectThreadIsRunning( void )\r
-{\r
-xThreadState *pxThreadState;\r
-\r
- /* When switching threads, Windows does not always seem to run the selected\r
- thread immediately. This function can be called to check if the thread\r
- that is currently running is the thread that is responsible for executing\r
- the task selected by the real time scheduler. The demo project for the Win32\r
- port calls this function from the trace macros which are seeded throughout \r
- the real time kernel code at points where something significant occurs.\r
- Adding this functionality allows all the standard tests to pass, but users\r
- should still be aware that extra calls to this function could be required\r
- if their application requires absolute fixes and predictable sequencing (as\r
- the port tests do). This is still a simulation - not the real thing! */\r
- if( xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED )\r
- {\r
- /* Obtain the real time task to Win32 mapping state information. */\r
- pxThreadState = ( xThreadState * ) *( ( unsigned long * ) pxCurrentTCB );\r
-\r
- if( GetCurrentThreadId() != pxThreadState->ulThreadId )\r
- {\r
- SwitchToThread();\r
- }\r
- }\r
-}\r
-\r