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;

 

你可能感兴趣的:(thread,timer,struct,list,insert,transition)