reactos操作系统实现(42)

接着下来,就需要分析函数KiReadyThread的作用了。根据线程状态来判断是否可以放入延迟队列,还是设置它为转换状态,代码如下:

#001 VOID

#002 NTAPI

#003 KiReadyThread(IN PKTHREAD Thread)

#004 {

获取当前线程的进程对象。

#005 IN PKPROCESS Process = Thread->ApcState.Process;

#006

检查进程是否已经换出内存。

#007 /* Check if the process is paged out */

#008 if (Process->State != ProcessInMemory)

#009 {

如果进程已经换出内存,就不做任何的操作。

#010 /* We don't page out processes in ROS */

#011 ASSERT(FALSE);

#012 }

#013 else if (!Thread->KernelStackResident)

#014 {

检查线程的内核栈是否为空,如果为空就需要增加栈的大小。

#015 /* Increase the stack count */

#016 ASSERT(Process->StackCount != MAXULONG_PTR);

#017 Process->StackCount++;

#018

设置线程为转换状态,由于需要内核栈。

#019 /* Set the thread to transition */

#020 ASSERT(Thread->State != Transition);

#021 Thread->State = Transition;

#022

#023 /* The stack is always resident in ROS */

#024 ASSERT(FALSE);

#025 }

#026 else

#027 {

把线程放到延迟调用队列。

#028 /* Insert the thread on the deferred ready list */

#029 KiInsertDeferredReadyList(Thread);

#030 }

#031 }

KiInsertDeferredReadyList函数是把线程设置为延迟状态,然后插入到当前处理器的延迟队列,代码如下:

#001 //

#002 // This routine inserts a thread into the deferred ready list of the given cpu

#003 //

#004 FORCEINLINE

#005 VOID

#006 KiInsertDeferredReadyList(IN PKTHREAD Thread)

#007 {

获取当前处理器的控制块。

#008 PKPRCB Prcb = KeGetCurrentPrcb();

#009

设置线程为延迟状态。

#010 /* Set the thread to deferred state and cpu */

#011 Thread->State = DeferredReady;

设置线程运行的cpu

#012 Thread->DeferredProcessor = Prcb->Number;

#013

把线程放到当前处理器控制块的延迟队列。

#014 /* Add it on the list */

#015 PushEntryList(&Prcb->DeferredReadyListHead,&Thread->SwapListEntry);

#016 }

在上面这个函数里,调用PushEntryList函数来把当前准备好的线程放到延迟队列。你也许看不明白为什么使用Thread->SwapListEntry就可以把线程的指针放到延迟队列呢?其实需要仔细看线程的结构才可以明白的,如下:

#068 union

#069 {

#070 LIST_ENTRY WaitListEntry;

#071 SINGLE_LIST_ENTRY SwapListEntry;

#072 };

在线程结构里是使用上面的联合来表达的,因此设置WaitListEntry变量,就相当设置SwapListEntry变量的值了。这是在函数KeInitThread里设置它的值,如下:

#027 /* Initialize the wait blocks */

#028 for (i = 0; i< (THREAD_WAIT_OBJECTS + 1); i++)

#029 {

#030 /* Put our pointer */

#031 Thread->WaitBlock[i].Thread = Thread;

#032 }

#033

......

#072 KeInitializeTimer(Timer);

#073 TimerWaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];

因此Thread->SwapListEntry变量的值,就可通过结构里的Thread来访问线程数据。

SwapListEntry的结构排列如下:

#001 typedef struct _KWAIT_BLOCK {

#002 LIST_ENTRY WaitListEntry;

#003 struct _KTHREAD * RESTRICTED_POINTER Thread;

#004 PVOID Object;

#005 struct _KWAIT_BLOCK * RESTRICTED_POINTER NextWaitBlock;

#006 USHORT WaitKey;

#007 UCHAR WaitType;

#008 UCHAR SpareByte;

#009} KWAIT_BLOCK,*PKWAIT_BLOCK,*RESTRICTED_POINTER PRKWAIT_BLOCK;

相关文章

react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接...
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc ...