[ros-diffs] [sir_richard] 49485: [NTOS]: Implement the idle loop in C.

sir_richard at svn.reactos.org sir_richard at svn.reactos.org
Fri Nov 5 15:58:35 UTC 2010


Author: sir_richard
Date: Fri Nov  5 15:58:34 2010
New Revision: 49485

URL: http://svn.reactos.org/svn/reactos?rev=49485&view=rev
Log:
[NTOS]: Implement the idle loop in C.

Modified:
    trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
    trunk/reactos/ntoskrnl/ke/i386/thrdini.c

Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S?rev=49485&r1=49484&r2=49485&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] Fri Nov  5 15:58:34 2010
@@ -498,129 +498,6 @@
     ret
 .endfunc
 
-.globl @KiIdleLoop at 0
-.func @KiIdleLoop at 0, @KiIdleLoop at 0
- at KiIdleLoop@0:
-
-    /* Set EBX */
-    mov ebx, fs:[KPCR_SELF]
-
-    /* Jump into mainline code */
-    jmp MainLoop
-
-CpuIdle:
-    /* Call the CPU's idle function */
-    lea ecx, [ebx+KPCR_PRCB_POWER_STATE_IDLE_FUNCTION]
-    call [ecx]
-
-MainLoop:
-    /* Cycle interrupts for 1 cycle */
-    sti
-    nop
-    nop
-    cli
-
-    /* Check if we have to deliver DPCs, timers, or deferred threads */
-    mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
-    or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
-#ifdef CONFIG_SMP
-    or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
-#endif
-    jz CheckSchedule
-
-    mov cl, DISPATCH_LEVEL
-    call @HalClearSoftwareInterrupt at 4
-    
-    /* Handle the above */
-    lea ecx, [ebx+KPCR_PRCB_DATA]
-    call @KiRetireDpcList at 4
-
-CheckSchedule:
-    /* Check if a next thread is queued */
-    cmp dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
-#ifdef CONFIG_SMP
-    jz NoNextThread
-#else
-    jz CpuIdle
-#endif
-
-#ifdef CONFIG_SMP
-    /* There is, raise IRQL to synch level */
-    call _KeRaiseIrqlToSynchLevel at 0
-#endif
-    sti
-
-    /* Set the current thread to ready */
-    mov edi, [ebx+KPCR_CURRENT_THREAD]
-#ifdef CONFIG_SMP
-    mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
-
-    /* Acquire the PRCB Lock */
-    lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
-    jnb CheckNext
-    lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
-    call @KefAcquireSpinLockAtDpcLevel at 4
-#endif
-
-CheckNext:
-    /* Check if the next thread is the current */
-    mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
-#ifdef CONFIG_SMP
-    cmp esi, edi
-    jz SameThread
-#endif
-
-    /* Clear the next thread and set this one instead */
-    and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
-    mov [ebx+KPCR_CURRENT_THREAD], esi
-
-    /* Set the thread as running */
-    mov byte ptr [esi+KTHREAD_STATE_], Running
-
-#ifdef CONFIG_SMP
-    /* Disable the idle scheduler and release the PRCB lock */
-    and byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0
-    and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
-#endif
-
-SwapContext:
-    /* Swap context at APC_LEVEL */
-    mov ecx, APC_LEVEL
-    call @KiSwapContextInternal at 0
-
-#ifdef CONFIG_SMP
-    /* Lower to DPC level */
-    mov ecx, DISPATCH_LEVEL
-    call @KfLowerIrql at 4
-#endif
-    jmp MainLoop
-
-#ifdef CONFIG_SMP
-SameThread:
-    /* Clear the next thread, and put the thread as ready after lock release */
-    and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
-    and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
-    and byte ptr [edi+KTHREAD_STATE_], Ready
-    jmp MainLoop
-
-NoNextThread:
-    /* Check if the idle scheduler is enabled */
-    cmp byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0
-    jz CpuIdle
-
-    /* It is, so call the scheduler */
-    lea ecx, [ebx+KPCR_PRCB_DATA]
-    call @KiIdleSchedule at 4
-    test eax, eax
-
-    /* Get new thread pointers and either swap or idle loop again */
-    mov esi, eax
-    mov edi, [ebx+KPCR_PRCB_IDLE_THREAD]
-    jnz SwapContext
-    jmp MainLoop
-#endif
-.endfunc
-
 /* FIXFIX: Move to C code ****/
 .globl _Ki386SetupAndExitToV86Mode at 4
 .func Ki386SetupAndExitToV86Mode at 4

Modified: trunk/reactos/ntoskrnl/ke/i386/thrdini.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thrdini.c?rev=49485&r1=49484&r2=49485&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] Fri Nov  5 15:58:34 2010
@@ -249,6 +249,64 @@
     Thread->KernelStack = (PVOID)CtxSwitchFrame;
 }
 
+VOID
+FASTCALL
+KiIdleLoop(VOID)
+{
+    PKPRCB Prcb = KeGetCurrentPrcb();
+    PKTHREAD OldThread, NewThread;
+
+    /* Initialize the idle loop: disable interrupts */
+    _enable();
+    __asm__("nop; nop");
+    _disable();
+    
+    /* Now loop forever */
+    while (TRUE)
+    {
+        /* Check for pending timers, pending DPCs, or pending ready threads */
+        if ((Prcb->DpcData[0].DpcQueueDepth) ||
+            (Prcb->TimerRequest) ||
+            (Prcb->DeferredReadyListHead.Next))
+        {
+            /* Quiesce the DPC software interrupt */
+            HalClearSoftwareInterrupt(DISPATCH_LEVEL);
+        
+            /* Handle it */
+            KiRetireDpcList(Prcb);
+        }
+    
+        /* Check if a new thread is scheduled for execution */
+        if (Prcb->NextThread)
+        {
+            /* Enable interupts */
+            _enable();
+        
+            /* Capture current thread data */
+            OldThread = Prcb->CurrentThread;
+            NewThread = Prcb->NextThread;
+        
+            /* Set new thread data */
+            Prcb->NextThread = NULL;
+            Prcb->CurrentThread = NewThread;
+        
+            /* The thread is now running */
+            NewThread->State = Running;
+        
+            /* Switch away from the idle thread */
+            KiSwapContext(OldThread, NewThread);
+            
+            /* We are back in the idle thread -- disable interrupts again */
+            _enable();
+            __asm__("nop");
+            _disable();
+        }
+        else
+        {
+            /* Continue staying idle. Note the HAL returns with interrupts on */
+            Prcb->PowerState.IdleFunction(&Prcb->PowerState);
+        }
+    }
+}
+
 /* EOF */
-
-




More information about the Ros-diffs mailing list