Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
3.0 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. yield.c
  5. Abstract:
  6. This module implements the function to yield execution for one quantum
  7. to any other runnable thread.
  8. Author:
  9. David N. Cutler (davec) 15-Mar-1996
  10. Environment:
  11. Kernel mode only.
  12. Revision History:
  13. --*/
  14. #include "ki.h"
  15. NTSTATUS
  16. NtYieldExecution (
  17. VOID
  18. )
  19. /*++
  20. Routine Description:
  21. This function yields execution to any ready thread for up to one
  22. quantum.
  23. Arguments:
  24. None.
  25. Return Value:
  26. None.
  27. --*/
  28. {
  29. KIRQL OldIrql;
  30. PKTHREAD NewThread;
  31. PRKPRCB Prcb;
  32. NTSTATUS Status;
  33. PKTHREAD Thread;
  34. //
  35. // If any other threads are ready, then attempt to yield execution.
  36. //
  37. Status = STATUS_NO_YIELD_PERFORMED;
  38. Thread = KeGetCurrentThread();
  39. OldIrql = KeRaiseIrqlToSynchLevel();
  40. Prcb = KeGetCurrentPrcb();
  41. if (Prcb->ReadySummary != 0) {
  42. //
  43. // Acquire the thread lock and the PRCB lock.
  44. //
  45. // If a thread has not already been selected for execution, then
  46. // attempt to select another thread for execution.
  47. //
  48. KiAcquireThreadLock(Thread);
  49. KiAcquirePrcbLock(Prcb);
  50. if (Prcb->NextThread == NULL) {
  51. Prcb->NextThread = KiSelectReadyThread(1, Prcb);
  52. }
  53. //
  54. // If a new thread has been selected for execution, then switch
  55. // immediately to the selected thread.
  56. //
  57. if ((NewThread = Prcb->NextThread) != NULL) {
  58. Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
  59. //
  60. // Compute the new thread priority.
  61. //
  62. // N.B. The new priority will never be greater than the previous
  63. // priority.
  64. //
  65. Thread->Priority = KiComputeNewPriority(Thread, 1);
  66. //
  67. // Release the thread lock, set swap busy for the old thread,
  68. // set the next thread to NULL, set the current thread to the
  69. // new thread, set the new thread state to running, set the
  70. // wait reason, queue the old running thread, and release the
  71. // PRCB lock, and swp context to the new thread.
  72. //
  73. KiReleaseThreadLock(Thread);
  74. KiSetContextSwapBusy(Thread);
  75. Prcb->NextThread = NULL;
  76. Prcb->CurrentThread = NewThread;
  77. NewThread->State = Running;
  78. Thread->WaitReason = WrYieldExecution;
  79. KxQueueReadyThread(Thread, Prcb);
  80. Thread->WaitIrql = APC_LEVEL;
  81. ASSERT(OldIrql <= DISPATCH_LEVEL);
  82. KiSwapContext(Thread, NewThread);
  83. Status = STATUS_SUCCESS;
  84. } else {
  85. KiReleasePrcbLock(Prcb);
  86. KiReleaseThreadLock(Thread);
  87. }
  88. }
  89. //
  90. // Lower IRQL to its previous level and return.
  91. //
  92. KeLowerIrql(OldIrql);
  93. return Status;
  94. }