summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2020-12-23 19:25:13 +0800
committerGitHub <[email protected]>2020-12-23 19:25:13 +0800
commit5e69accd5c872525a927f0c403e695378c736fde (patch)
treeb8310d6de902dde266bc3b08b134fb4431d19435
parentb10815c060d6b2d8b40faaddf44bb086dcaac547 (diff)
parent82ae97e24898253c344a90ac21e4df04690304a4 (diff)
Merge pull request #4187 from Jedcheen/master
fix scheduler bug in simulator.
-rw-r--r--libcpu/sim/win32/cpu_port.c22
-rw-r--r--libcpu/sim/win32/cpu_port.h4
2 files changed, 24 insertions, 2 deletions
diff --git a/libcpu/sim/win32/cpu_port.c b/libcpu/sim/win32/cpu_port.c
index 6bf3c79cf7..cc8ad9a25c 100644
--- a/libcpu/sim/win32/cpu_port.c
+++ b/libcpu/sim/win32/cpu_port.c
@@ -27,6 +27,8 @@
* The context switch is managed by the threads.So the task stack does not have to be managed directly,
* although the stack stack is still used to hold an WinThreadState structure this is the only thing it
* will be ever hold.
+* YieldEvent used to make sure the thread does not execute before asynchronous SuspendThread() operation
+* actually being performed.
* the structure indirectly maps the task handle to a thread handle
*********************************************************************************************************
*/
@@ -35,6 +37,7 @@ typedef struct
void *Param; //Thread param
void (*Entry)(void *); //Thread entry
void (*Exit)(void); //Thread exit
+ HANDLE YieldEvent;
HANDLE ThreadHandle;
DWORD ThreadID;
}win_thread_t;
@@ -171,6 +174,11 @@ rt_uint8_t* rt_hw_stack_init(void *pEntry,void *pParam,rt_uint8_t *pStackAddr,vo
pWinThread->ThreadHandle = NULL;
pWinThread->ThreadID = 0;
+ pWinThread->YieldEvent = CreateEvent(NULL,
+ FALSE,
+ FALSE,
+ NULL);
+
/* Create the winthread */
pWinThread->ThreadHandle = CreateThread(NULL,
0,
@@ -277,6 +285,19 @@ void rt_hw_context_switch(rt_uint32_t from,
//trigger YIELD exception(cause contex switch)
TriggerSimulateInterrupt(CPU_INTERRUPT_YIELD);
+ // make sure the event is not already signaled
+ win_thread_t *WinThread = (win_thread_t *)rt_interrupt_from_thread;
+ ResetEvent(WinThread->YieldEvent);
+
+ /*
+ * enable interrupt in advance so that scheduler can be executed.please note that interrupt
+ * maybe disable twice before.
+ */
+ rt_hw_interrupt_enable(0);
+ rt_hw_interrupt_enable(0);
+
+ // wait to suspend.
+ WaitForSingleObject(WinThread->YieldEvent, INFINITE);
} /*** rt_hw_context_switch ***/
/*
@@ -578,6 +599,7 @@ void RegisterSimulateInterrupt(rt_uint32_t IntIndex,rt_uint32_t (*IntHandler)(vo
if ((WinThreadFrom != NULL) && (WinThreadFrom->ThreadHandle != NULL))
{
SuspendThread(WinThreadFrom->ThreadHandle);
+ SetEvent(WinThreadFrom->YieldEvent);
}
ResumeThread(WinThreadTo->ThreadHandle);
diff --git a/libcpu/sim/win32/cpu_port.h b/libcpu/sim/win32/cpu_port.h
index 8ab8ae23bd..cccdd48d42 100644
--- a/libcpu/sim/win32/cpu_port.h
+++ b/libcpu/sim/win32/cpu_port.h
@@ -17,8 +17,8 @@
* CPU INTERRUPT PRIORITY
*********************************************************************************************************
*/
-#define CPU_INTERRUPT_YIELD 0x00
-#define CPU_INTERRUPT_TICK 0x01
+#define CPU_INTERRUPT_YIELD 0x01 // should be set to the lowest priority.
+#define CPU_INTERRUPT_TICK 0x00