reactos操作系统实现(22)

 Boot.S文件里初始化系统基本组件后,就跳到空闲函数处理,就成为一个空闲处理的线程,其实也是一个管理系统的任务。下面就来分析KiIdleLoop函数的代码,如下:

#001  .globl @KiIdleLoop@0

#002  .func @KiIdleLoop@0, @KiIdleLoop@0

#003  @KiIdleLoop@0:

#004 

 

获取KPCR的指针地址,这样就可以方便访问KPCR里的成员。

#005      /* Set EBX */

#006      mov ebx, fs:[KPCR_SELF]

#007 

 

跳到主循环开始位置。

#008      /* Jump into mainline code */

#009      jmp MainLoop

#010 

#011  CpuIdle:

#012      /* Call the CPU's idle function */

#013      lea ecx, [ebx+KPCR_PRCB_POWER_STATE_IDLE_FUNCTION]

#014      call [ecx]

#015 

 

主循环开始位置。

#016  MainLoop:

#017      /* Cycle interrupts for 1 cycle */

 

打开中断以便响应中断任务处理。

#018      sti

#019      nop

#020      nop

 

下面代码运行需要关闭中断,以便打乱线程调度处理。

#021      cli

#022 

 

先检查是否有DPC请求或者时间请求,如果有就需要处理。

#023      /* Check if we have to deliver DPCs, timers, or deferred threads */

#024      mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]

#025      or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]

#026  #ifdef CONFIG_SMP

#027      or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]

#028  #endif

#029      jz CheckSchedule

#030 

 

下面处理DPC或时钟请求处理。

清除软件中断。

#031      mov cl, DISPATCH_LEVEL

#032      call @HalClearSoftwareInterrupt@4

#033     

#034      /* Handle the above */

 

处理DPC队列的请求。

#035      lea ecx, [ebx+KPCR_PRCB_DATA]

#036      call @KiRetireDpcList@4

#037 

 

检查是否有线程可以调度运行。

#038  CheckSchedule:

#039      /* Check if a next thread is queued */

 

检查下一个线程是否准备好。

#040      cmp dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0

#041  #ifdef CONFIG_SMP

#042      jz NoNextThread

#043  #else

 

如果没有准备好的线程,就跳到让CPU空闲处理。

#044      jz CpuIdle

#045  #endif

#046 

#047  #ifdef CONFIG_SMP

#048      /* There is, raise IRQL to synch level */

#049      call _KeRaiseIrqlToSynchLevel@0

#050  #endif

 

打开CPU中断。

#051      sti

#052 

#053      /* Set the current thread to ready */

 

获取当前线程数据指针。

#054      mov edi, [ebx+KPCR_CURRENT_THREAD]

#055  #ifdef CONFIG_SMP

#056      mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1

#057 

#058      /* Acquire the PRCB Lock */

#059      lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0

#060      jnb CheckNext

#061      lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]

#062      call @KefAcquireSpinLockAtDpcLevel@4

#063  #endif

#064 

#065  CheckNext:

#066      /* Check if the next thread is the current */

 

获取下一个线程数据指针。

#067      mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]

#068  #ifdef CONFIG_SMP

#069      cmp esi, edi

#070      jz SameThread

#071  #endif

#072 

#073      /* Clear the next thread and set this one instead */

 

清空下一个线程标志。

#074      and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0

 

设置当前线程为下一个运行线程数据指针。

#075      mov [ebx+KPCR_CURRENT_THREAD], esi

#076 

 

设置下一个线程为运行状态。

#077      /* Set the thread as running */

#078      mov byte ptr [esi+KTHREAD_STATE_], Running

#079 

#080  #ifdef CONFIG_SMP

#081      /* Disable the idle scheduler and release the PRCB lock */

#082      and byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0

#083      and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0

#084  #endif

#085 

 

开始切换线程的运行环境。

#086  SwapContext:

#087      /* ReactOS Mm Hack */

 

切换线程内存空间。

#088      mov ecx, esi

#089      call @MiSyncForContextSwitch@4

#090 

 

从当前线程任务状态切换到即将运行的线程。

#091      /* Swap context at APC_LEVEL */

#092      mov ecx, APC_LEVEL

#093      call @KiSwapContextInternal@0

#094 

#095  #ifdef CONFIG_SMP

#096      /* Lower to DPC level */

#097      mov ecx, DISPATCH_LEVEL

#098      call @KfLowerIrql@4

#099  #endif

 

跳到主循环开始新的处理。

#100      jmp MainLoop

#101 

#102  #ifdef CONFIG_SMP

#103  SameThread:

#104      /* Clear the next thread, and put the thready as ready after lock release */

#105      and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0

#106      and dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0

#107      and byte ptr [edi+KTHREAD_STATE_], Ready

#108      jmp MainLoop

#109 

#110  NoNextThread:

#111      /* Check if the idle scheduler is enabled */

#112      cmp byte ptr [ebx+KPCR_PRCB_IDLE_SCHEDULE], 0

#113      jz CpuIdle

#114 

#115      /* It is, so call the scheduler */

#116      lea ecx, [ebx+KPCR_PRCB_DATA]

#117      call @KiIdleSchedule@4

#118      test eax, eax

#119 

#120      /* Get new thread pointers and either swap or idle loop again */

#121      mov esi, eax

#122      mov edi, [ebx+KPCR_PRCB_IDLE_THREAD]

#123      jnz SwapContext

#124      jmp MainLoop

#125  #endif

#126  .endfunc

 

空闲函数主要处理DPC的队列和时间钟请求。如果有线程切换,就改变线程运行环境。

你可能感兴趣的:(reactos操作系统实现(22))