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的队列和时间钟请求。如果有线程切换,就改变线程运行环境。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |