浏览代码

fix scheduler bug in simulator.

unknown 4 年之前
父节点
当前提交
76b6d7f90d
共有 2 个文件被更改,包括 24 次插入2 次删除
  1. 22 0
      libcpu/sim/win32/cpu_port.c
  2. 2 2
      libcpu/sim/win32/cpu_port.h

+ 22 - 0
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
+    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);

+ 2 - 2
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