ReactOS  r75907
thrdschd.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for thrdschd.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define InterlockedOrSetMember(Destination, SetMember)   InterlockedOr((PLONG)Destination, SetMember);
 
#define KiGetCurrentReadySummary()   KeGetCurrentPrcb()->ReadySummary
 

Functions

PKTHREAD FASTCALL KiIdleSchedule (IN PKPRCB Prcb)
 
VOID FASTCALL KiProcessDeferredReadyList (IN PKPRCB Prcb)
 
VOID FASTCALL KiQueueReadyThread (IN PKTHREAD Thread, IN PKPRCB Prcb)
 
VOID FASTCALL KiDeferredReadyThread (IN PKTHREAD Thread)
 
PKTHREAD FASTCALL KiSelectNextThread (IN PKPRCB Prcb)
 
LONG_PTR FASTCALL KiSwapThread (IN PKTHREAD CurrentThread, IN PKPRCB Prcb)
 
VOID NTAPI KiReadyThread (IN PKTHREAD Thread)
 
VOID NTAPI KiAdjustQuantumThread (IN PKTHREAD Thread)
 
VOID FASTCALL KiSetPriorityThread (IN PKTHREAD Thread, IN KPRIORITY Priority)
 
KAFFINITY FASTCALL KiSetAffinityThread (IN PKTHREAD Thread, IN KAFFINITY Affinity)
 
NTSTATUS NTAPI NtYieldExecution (VOID)
 

Variables

ULONG_PTR KiIdleSummary
 
ULONG_PTR KiIdleSMTSummary
 

Macro Definition Documentation

#define InterlockedOrSetMember (   Destination,
  SetMember 
)    InterlockedOr((PLONG)Destination, SetMember);

Definition at line 19 of file thrdschd.c.

Referenced by KiSelectNextThread(), and KiSwapThread().

#define KiGetCurrentReadySummary ( )    KeGetCurrentPrcb()->ReadySummary

Definition at line 736 of file thrdschd.c.

Referenced by NtYieldExecution().

#define NDEBUG

Definition at line 12 of file thrdschd.c.

Function Documentation

VOID NTAPI KiAdjustQuantumThread ( IN PKTHREAD  Thread)

Definition at line 461 of file thrdschd.c.

Referenced by KeDelayExecutionThread(), KeWaitForMultipleObjects(), and KeWaitForSingleObject().

462 {
463  PKPRCB Prcb = KeGetCurrentPrcb();
464  PKTHREAD NextThread;
465 
466  /* Acquire thread and PRCB lock */
468  KiAcquirePrcbLock(Prcb);
469 
470  /* Don't adjust for RT threads */
471  if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
472  (Thread->BasePriority < (LOW_REALTIME_PRIORITY - 2)))
473  {
474  /* Decrease Quantum by one and see if we've ran out */
475  if (--Thread->Quantum <= 0)
476  {
477  /* Return quantum */
478  Thread->Quantum = Thread->QuantumReset;
479 
480  /* Calculate new Priority */
481  Thread->Priority = KiComputeNewPriority(Thread, 1);
482 
483  /* Check if there's no next thread scheduled */
484  if (!Prcb->NextThread)
485  {
486  /* Select a ready thread and check if we found one */
487  NextThread = KiSelectReadyThread(Thread->Priority, Prcb);
488  if (NextThread)
489  {
490  /* Set it on standby and switch to it */
491  NextThread->State = Standby;
492  Prcb->NextThread = NextThread;
493  }
494  }
495  else
496  {
497  /* This thread can be preempted again */
498  Thread->Preempted = FALSE;
499  }
500  }
501  }
502 
503  /* Release locks */
504  KiReleasePrcbLock(Prcb);
506  KiExitDispatcher(Thread->WaitIrql);
507 }
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define LOW_REALTIME_PRIORITY
struct _KTHREAD * NextThread
Definition: ketypes.h:567
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1458
#define FALSE
Definition: types.h:117
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
VOID FASTCALL KiExitDispatcher(KIRQL OldIrql)
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
volatile UCHAR State
Definition: ketypes.h:997
VOID FASTCALL KiDeferredReadyThread ( IN PKTHREAD  Thread)

Definition at line 79 of file thrdschd.c.

Referenced by KiInsertDeferredReadyList(), KiProcessDeferredReadyList(), and KxQueueReadyThread().

80 {
81  PKPRCB Prcb;
82  BOOLEAN Preempted;
83  ULONG Processor = 0;
84  KPRIORITY OldPriority;
85  PKTHREAD NextThread;
86 
87  /* Sanity checks */
88  ASSERT(Thread->State == DeferredReady);
89  ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
90 
91  /* Check if we have any adjusts to do */
92  if (Thread->AdjustReason == AdjustBoost)
93  {
94  /* Lock the thread */
96 
97  /* Check if the priority is low enough to qualify for boosting */
98  if ((Thread->Priority <= Thread->AdjustIncrement) &&
99  (Thread->Priority < (LOW_REALTIME_PRIORITY - 3)) &&
100  !(Thread->DisableBoost))
101  {
102  /* Calculate the new priority based on the adjust increment */
103  OldPriority = min(Thread->AdjustIncrement + 1,
105 
106  /* Make sure we're not decreasing outside of the priority range */
107  ASSERT((Thread->PriorityDecrement >= 0) &&
108  (Thread->PriorityDecrement <= Thread->Priority));
109 
110  /* Calculate the new priority decrement based on the boost */
111  Thread->PriorityDecrement += ((SCHAR)OldPriority - Thread->Priority);
112 
113  /* Again verify that this decrement is valid */
114  ASSERT((Thread->PriorityDecrement >= 0) &&
115  (Thread->PriorityDecrement <= OldPriority));
116 
117  /* Set the new priority */
118  Thread->Priority = (SCHAR)OldPriority;
119  }
120 
121  /* We need 4 quanta, make sure we have them, then decrease by one */
122  if (Thread->Quantum < 4) Thread->Quantum = 4;
123  Thread->Quantum--;
124 
125  /* Make sure the priority is still valid */
126  ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
127 
128  /* Release the lock and clear the adjust reason */
130  Thread->AdjustReason = AdjustNone;
131  }
132  else if (Thread->AdjustReason == AdjustUnwait)
133  {
134  /* Acquire the thread lock and check if this is a real-time thread */
136  if (Thread->Priority < LOW_REALTIME_PRIORITY)
137  {
138  /* It's not real time, but is it time critical? */
139  if (Thread->BasePriority >= (LOW_REALTIME_PRIORITY - 2))
140  {
141  /* It is, so simply reset its quantum */
142  Thread->Quantum = Thread->QuantumReset;
143  }
144  else
145  {
146  /* Has the priority been adjusted previously? */
147  if (!(Thread->PriorityDecrement) && (Thread->AdjustIncrement))
148  {
149  /* Yes, reset its quantum */
150  Thread->Quantum = Thread->QuantumReset;
151  }
152 
153  /* Wait code already handles quantum adjustment during APCs */
154  if (Thread->WaitStatus != STATUS_KERNEL_APC)
155  {
156  /* Decrease the quantum by one and check if we're out */
157  if (--Thread->Quantum <= 0)
158  {
159  /* We are, reset the quantum and get a new priority */
160  Thread->Quantum = Thread->QuantumReset;
161  Thread->Priority = KiComputeNewPriority(Thread, 1);
162  }
163  }
164  }
165 
166  /* Now check if we have no decrement and boosts are enabled */
167  if (!(Thread->PriorityDecrement) && !(Thread->DisableBoost))
168  {
169  /* Make sure we have an increment */
170  ASSERT(Thread->AdjustIncrement >= 0);
171 
172  /* Calculate the new priority after the increment */
173  OldPriority = Thread->BasePriority + Thread->AdjustIncrement;
174 
175  /* Check if this is a foreground process */
176  if (CONTAINING_RECORD(Thread->ApcState.Process, EPROCESS, Pcb)->
177  Vm.Flags.MemoryPriority == MEMORY_PRIORITY_FOREGROUND)
178  {
179  /* Apply the foreground boost */
180  OldPriority += PsPrioritySeparation;
181  }
182 
183  /* Check if this new priority is higher */
184  if (OldPriority > Thread->Priority)
185  {
186  /* Make sure we don't go into the real time range */
187  if (OldPriority >= LOW_REALTIME_PRIORITY)
188  {
189  /* Normalize it back down one notch */
190  OldPriority = LOW_REALTIME_PRIORITY - 1;
191  }
192 
193  /* Check if the priority is higher then the boosted base */
194  if (OldPriority > (Thread->BasePriority +
195  Thread->AdjustIncrement))
196  {
197  /* Setup a priority decrement to nullify the boost */
198  Thread->PriorityDecrement = ((SCHAR)OldPriority -
199  Thread->BasePriority -
200  Thread->AdjustIncrement);
201  }
202 
203  /* Make sure that the priority decrement is valid */
204  ASSERT((Thread->PriorityDecrement >= 0) &&
205  (Thread->PriorityDecrement <= OldPriority));
206 
207  /* Set this new priority */
208  Thread->Priority = (SCHAR)OldPriority;
209  }
210  }
211  }
212  else
213  {
214  /* It's a real-time thread, so just reset its quantum */
215  Thread->Quantum = Thread->QuantumReset;
216  }
217 
218  /* Make sure the priority makes sense */
219  ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
220 
221  /* Release the thread lock and reset the adjust reason */
223  Thread->AdjustReason = AdjustNone;
224  }
225 
226  /* Clear thread preemption status and save current values */
227  Preempted = Thread->Preempted;
228  OldPriority = Thread->Priority;
229  Thread->Preempted = FALSE;
230 
231  /* Queue the thread on CPU 0 and get the PRCB and lock it */
232  Thread->NextProcessor = 0;
233  Prcb = KiProcessorBlock[0];
234  KiAcquirePrcbLock(Prcb);
235 
236  /* Check if we have an idle summary */
237  if (KiIdleSummary)
238  {
239  /* Clear it and set this thread as the next one */
240  KiIdleSummary = 0;
241  Thread->State = Standby;
242  Prcb->NextThread = Thread;
243 
244  /* Unlock the PRCB and return */
245  KiReleasePrcbLock(Prcb);
246  return;
247  }
248 
249  /* Set the CPU number */
250  Thread->NextProcessor = (UCHAR)Processor;
251 
252  /* Get the next scheduled thread */
253  NextThread = Prcb->NextThread;
254  if (NextThread)
255  {
256  /* Sanity check */
257  ASSERT(NextThread->State == Standby);
258 
259  /* Check if priority changed */
260  if (OldPriority > NextThread->Priority)
261  {
262  /* Preempt the thread */
263  NextThread->Preempted = TRUE;
264 
265  /* Put this one as the next one */
266  Thread->State = Standby;
267  Prcb->NextThread = Thread;
268 
269  /* Set it in deferred ready mode */
270  NextThread->State = DeferredReady;
271  NextThread->DeferredProcessor = Prcb->Number;
272  KiReleasePrcbLock(Prcb);
273  KiDeferredReadyThread(NextThread);
274  return;
275  }
276  }
277  else
278  {
279  /* Set the next thread as the current thread */
280  NextThread = Prcb->CurrentThread;
281  if (OldPriority > NextThread->Priority)
282  {
283  /* Preempt it if it's already running */
284  if (NextThread->State == Running) NextThread->Preempted = TRUE;
285 
286  /* Set the thread on standby and as the next thread */
287  Thread->State = Standby;
288  Prcb->NextThread = Thread;
289 
290  /* Release the lock */
291  KiReleasePrcbLock(Prcb);
292 
293  /* Check if we're running on another CPU */
294  if (KeGetCurrentProcessorNumber() != Thread->NextProcessor)
295  {
296  /* We are, send an IPI */
297  KiIpiSend(AFFINITY_MASK(Thread->NextProcessor), IPI_DPC);
298  }
299  return;
300  }
301  }
302 
303  /* Sanity check */
304  ASSERT((OldPriority >= 0) && (OldPriority <= HIGH_PRIORITY));
305 
306  /* Set this thread as ready */
307  Thread->State = Ready;
308  Thread->WaitTime = KeTickCount.LowPart;
309 
310  /* Insert this thread in the appropriate order */
311  Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[OldPriority],
312  &Thread->WaitListEntry) :
313  InsertTailList(&Prcb->DispatcherReadyListHead[OldPriority],
314  &Thread->WaitListEntry);
315 
316  /* Update the ready summary */
317  Prcb->ReadySummary |= PRIORITY_MASK(OldPriority);
318 
319  /* Sanity check */
320  ASSERT(OldPriority == Thread->Priority);
321 
322  /* Release the lock */
323  KiReleasePrcbLock(Prcb);
324 }
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
ULONG LowPart
Definition: ketypes.h:895
#define TRUE
Definition: types.h:120
#define PRIORITY_MASK(Id)
Definition: ke.h:149
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
SCHAR Priority
Definition: ketypes.h:974
_In_ UCHAR Processor
Definition: kefuncs.h:695
#define AFFINITY_MASK(Id)
Definition: ke.h:148
#define InsertTailList(ListHead, Entry)
#define LOW_REALTIME_PRIORITY
BOOLEAN Preempted
Definition: ketypes.h:1212
struct _KTHREAD * NextThread
Definition: ketypes.h:567
LONG KPRIORITY
Definition: compat.h:454
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:325
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1458
#define FALSE
Definition: types.h:117
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
VOID FASTCALL KiDeferredReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:79
#define STATUS_KERNEL_APC
Definition: ntstatus.h:79
#define IPI_DPC
Definition: ketypes.h:233
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
unsigned char BOOLEAN
volatile ULONG DeferredProcessor
Definition: ketypes.h:978
signed char SCHAR
Definition: sqltypes.h:14
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
unsigned char UCHAR
Definition: xmlstorage.h:181
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
Definition: ketypes.h:370
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
ULONG ReadySummary
Definition: ketypes.h:726
ULONG_PTR KiIdleSummary
Definition: thrdschd.c:25
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:32
ULONG PsPrioritySeparation
Definition: process.c:28
#define min(a, b)
Definition: monoChain.cc:55
LIST_ENTRY DispatcherReadyListHead[32]
Definition: ketypes.h:731
volatile UCHAR State
Definition: ketypes.h:997
USHORT Number
Definition: ketypes.h:559
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define HIGH_PRIORITY
#define MEMORY_PRIORITY_FOREGROUND
Definition: pstypes.h:127
PKTHREAD FASTCALL KiIdleSchedule ( IN PKPRCB  Prcb)

Definition at line 32 of file thrdschd.c.

33 {
34  /* FIXME: TODO */
35  ASSERTMSG("SMP: Not yet implemented\n", FALSE);
36  return NULL;
37 }
#define FALSE
Definition: types.h:117
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
smooth NULL
Definition: ftsmooth.c:513
VOID FASTCALL KiProcessDeferredReadyList ( IN PKPRCB  Prcb)

Definition at line 41 of file thrdschd.c.

Referenced by KiRetireDpcList().

42 {
43  PSINGLE_LIST_ENTRY ListEntry;
45 
46  /* Make sure there is something on the ready list */
47  ASSERT(Prcb->DeferredReadyListHead.Next != NULL);
48 
49  /* Get the first entry and clear the list */
50  ListEntry = Prcb->DeferredReadyListHead.Next;
51  Prcb->DeferredReadyListHead.Next = NULL;
52 
53  /* Start processing loop */
54  do
55  {
56  /* Get the thread and advance to the next entry */
57  Thread = CONTAINING_RECORD(ListEntry, KTHREAD, SwapListEntry);
58  ListEntry = ListEntry->Next;
59 
60  /* Make the thread ready */
61  KiDeferredReadyThread(Thread);
62  } while (ListEntry != NULL);
63 
64  /* Make sure the ready list is still empty */
65  ASSERT(Prcb->DeferredReadyListHead.Next == NULL);
66 }
Definition: ntbasedef.h:627
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID FASTCALL KiDeferredReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:79
smooth NULL
Definition: ftsmooth.c:513
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:628
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
VOID FASTCALL KiQueueReadyThread ( IN PKTHREAD  Thread,
IN PKPRCB  Prcb 
)

Definition at line 70 of file thrdschd.c.

Referenced by KiDecrementerTrap().

72 {
73  /* Call the macro. We keep the API for compatibility with ASM code */
75 }
FORCEINLINE VOID KxQueueReadyThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: ke_x.h:1343
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID NTAPI KiReadyThread ( IN PKTHREAD  Thread)

Definition at line 429 of file thrdschd.c.

Referenced by KeReadyThread(), KeSetEventBoostPriority(), KeSignalGateBoostPriority(), KiAttachProcess(), KiInsertQueue(), and KiUnwaitThread().

430 {
431  IN PKPROCESS Process = Thread->ApcState.Process;
432 
433  /* Check if the process is paged out */
434  if (Process->State != ProcessInMemory)
435  {
436  /* We don't page out processes in ROS */
437  ASSERT(FALSE);
438  }
439  else if (!Thread->KernelStackResident)
440  {
441  /* Increase the stack count */
442  ASSERT(Process->StackCount != MAXULONG_PTR);
443  Process->StackCount++;
444 
445  /* Set the thread to transition */
446  ASSERT(Thread->State != Transition);
447  Thread->State = Transition;
448 
449  /* The stack is always resident in ROS */
450  ASSERT(FALSE);
451  }
452  else
453  {
454  /* Insert the thread on the deferred ready list */
456  }
457 }
#define IN
Definition: typedefs.h:39
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID KiInsertDeferredReadyList(IN PKTHREAD Thread)
Definition: ke_x.h:179
#define MAXULONG_PTR
Definition: basetsd.h:102
#define FALSE
Definition: types.h:117
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
PKTHREAD FASTCALL KiSelectNextThread ( IN PKPRCB  Prcb)

Definition at line 328 of file thrdschd.c.

Referenced by KeRevertToUserAffinityThread(), and KeSetSystemAffinityThread().

329 {
331 
332  /* Select a ready thread */
333  Thread = KiSelectReadyThread(0, Prcb);
334  if (!Thread)
335  {
336  /* Didn't find any, get the current idle thread */
337  Thread = Prcb->IdleThread;
338 
339  /* Enable idle scheduling */
340  InterlockedOrSetMember(&KiIdleSummary, Prcb->SetMember);
341  Prcb->IdleSchedule = TRUE;
342 
343  /* FIXME: SMT support */
344  ASSERTMSG("SMP: Not yet implemented\n", FALSE);
345  }
346 
347  /* Sanity checks and return the thread */
348  ASSERT(Thread != NULL);
349  ASSERT((Thread->BasePriority == 0) || (Thread->Priority != 0));
350  return Thread;
351 }
#define TRUE
Definition: types.h:120
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SCHAR Priority
Definition: ketypes.h:974
#define FALSE
Definition: types.h:117
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
smooth NULL
Definition: ftsmooth.c:513
SCHAR BasePriority
Definition: ketypes.h:1209
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define InterlockedOrSetMember(Destination, SetMember)
Definition: thrdschd.c:19
ULONG_PTR KiIdleSummary
Definition: thrdschd.c:25
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
KAFFINITY FASTCALL KiSetAffinityThread ( IN PKTHREAD  Thread,
IN KAFFINITY  Affinity 
)

Definition at line 685 of file thrdschd.c.

Referenced by KeSetAffinityProcess(), and KeSetAffinityThread().

687 {
688  KAFFINITY OldAffinity;
689 
690  /* Get the current affinity */
691  OldAffinity = Thread->UserAffinity;
692 
693  /* Make sure that the affinity is valid */
694  if (((Affinity & Thread->ApcState.Process->Affinity) != (Affinity)) ||
695  (!Affinity))
696  {
697  /* Bugcheck the system */
698  KeBugCheck(INVALID_AFFINITY_SET);
699  }
700 
701  /* Update the new affinity */
702  Thread->UserAffinity = Affinity;
703 
704  /* Check if system affinity is disabled */
705  if (!Thread->SystemAffinityActive)
706  {
707 #ifdef CONFIG_SMP
708  /* FIXME: TODO */
709  DPRINT1("Affinity support disabled!\n");
710 #endif
711  }
712 
713  /* Return the old affinity */
714  return OldAffinity;
715 }
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1469
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:170
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
ULONG_PTR KAFFINITY
Definition: compat.h:75
#define DPRINT1
Definition: precomp.h:8
VOID FASTCALL KiSetPriorityThread ( IN PKTHREAD  Thread,
IN KPRIORITY  Priority 
)

Definition at line 511 of file thrdschd.c.

Referenced by ExpBoostOwnerThread(), KeBoostPriorityThread(), KeSetBasePriorityThread(), KeSetPriorityAndQuantumProcess(), and KeSetPriorityThread().

513 {
514  PKPRCB Prcb;
516  BOOLEAN RequestInterrupt = FALSE;
517  KPRIORITY OldPriority;
518  PKTHREAD NewThread;
519  ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
520 
521  /* Check if priority changed */
522  if (Thread->Priority != Priority)
523  {
524  /* Loop priority setting in case we need to start over */
525  for (;;)
526  {
527  /* Choose action based on thread's state */
528  if (Thread->State == Ready)
529  {
530  /* Make sure we're not on the ready queue */
531  if (!Thread->ProcessReadyQueue)
532  {
533  /* Get the PRCB for the thread and lock it */
534  Processor = Thread->NextProcessor;
535  Prcb = KiProcessorBlock[Processor];
536  KiAcquirePrcbLock(Prcb);
537 
538  /* Make sure the thread is still ready and on this CPU */
539  if ((Thread->State == Ready) &&
540  (Thread->NextProcessor == Prcb->Number))
541  {
542  /* Sanity check */
543  ASSERT((Prcb->ReadySummary &
544  PRIORITY_MASK(Thread->Priority)));
545 
546  /* Remove it from the current queue */
547  if (RemoveEntryList(&Thread->WaitListEntry))
548  {
549  /* Update the ready summary */
551  Priority);
552  }
553 
554  /* Update priority */
555  Thread->Priority = (SCHAR)Priority;
556 
557  /* Re-insert it at its current priority */
559 
560  /* Release the PRCB Lock */
561  KiReleasePrcbLock(Prcb);
562  }
563  else
564  {
565  /* Release the lock and loop again */
566  KiReleasePrcbLock(Prcb);
567  continue;
568  }
569  }
570  else
571  {
572  /* It's already on the ready queue, just update priority */
573  Thread->Priority = (SCHAR)Priority;
574  }
575  }
576  else if (Thread->State == Standby)
577  {
578  /* Get the PRCB for the thread and lock it */
579  Processor = Thread->NextProcessor;
580  Prcb = KiProcessorBlock[Processor];
581  KiAcquirePrcbLock(Prcb);
582 
583  /* Check if we're still the next thread to run */
584  if (Thread == Prcb->NextThread)
585  {
586  /* Get the old priority and update ours */
587  OldPriority = Thread->Priority;
588  Thread->Priority = (SCHAR)Priority;
589 
590  /* Check if there was a change */
591  if (Priority < OldPriority)
592  {
593  /* Find a new thread */
594  NewThread = KiSelectReadyThread(Priority + 1, Prcb);
595  if (NewThread)
596  {
597  /* Found a new one, set it on standby */
598  NewThread->State = Standby;
599  Prcb->NextThread = NewThread;
600 
601  /* Dispatch our thread */
603  }
604  }
605 
606  /* Release the PRCB lock */
607  KiReleasePrcbLock(Prcb);
608  }
609  else
610  {
611  /* Release the lock and try again */
612  KiReleasePrcbLock(Prcb);
613  continue;
614  }
615  }
616  else if (Thread->State == Running)
617  {
618  /* Get the PRCB for the thread and lock it */
619  Processor = Thread->NextProcessor;
620  Prcb = KiProcessorBlock[Processor];
621  KiAcquirePrcbLock(Prcb);
622 
623  /* Check if we're still the current thread running */
624  if (Thread == Prcb->CurrentThread)
625  {
626  /* Get the old priority and update ours */
627  OldPriority = Thread->Priority;
628  Thread->Priority = (SCHAR)Priority;
629 
630  /* Check if there was a change and there's no new thread */
631  if ((Priority < OldPriority) && !(Prcb->NextThread))
632  {
633  /* Find a new thread */
634  NewThread = KiSelectReadyThread(Priority + 1, Prcb);
635  if (NewThread)
636  {
637  /* Found a new one, set it on standby */
638  NewThread->State = Standby;
639  Prcb->NextThread = NewThread;
640 
641  /* Request an interrupt */
642  RequestInterrupt = TRUE;
643  }
644  }
645 
646  /* Release the lock and check if we need an interrupt */
647  KiReleasePrcbLock(Prcb);
648  if (RequestInterrupt)
649  {
650  /* Check if we're running on another CPU */
651  if (KeGetCurrentProcessorNumber() != Processor)
652  {
653  /* We are, send an IPI */
654  KiIpiSend(AFFINITY_MASK(Processor), IPI_DPC);
655  }
656  }
657  }
658  else
659  {
660  /* Thread changed, release lock and restart */
661  KiReleasePrcbLock(Prcb);
662  continue;
663  }
664  }
665  else if (Thread->State == DeferredReady)
666  {
667  /* FIXME: TODO */
668  DPRINT1("Deferred state not yet supported\n");
669  ASSERT(FALSE);
670  }
671  else
672  {
673  /* Any other state, just change priority */
674  Thread->Priority = (SCHAR)Priority;
675  }
676 
677  /* If we got here, then thread state was consistent, so bail out */
678  break;
679  }
680  }
681 }
#define TRUE
Definition: types.h:120
#define PRIORITY_MASK(Id)
Definition: ke.h:149
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
FORCEINLINE VOID KiInsertDeferredReadyList(IN PKTHREAD Thread)
Definition: ke_x.h:179
_In_ KPRIORITY Priority
Definition: kefuncs.h:516
_In_ UCHAR Processor
Definition: kefuncs.h:695
#define AFFINITY_MASK(Id)
Definition: ke.h:148
struct _KTHREAD * NextThread
Definition: ketypes.h:567
LONG KPRIORITY
Definition: compat.h:454
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:325
#define FALSE
Definition: types.h:117
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
#define IPI_DPC
Definition: ketypes.h:233
unsigned char BOOLEAN
signed char SCHAR
Definition: sqltypes.h:14
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
Definition: ketypes.h:370
VOID FASTCALL KiIpiSend(KAFFINITY TargetSet, ULONG IpiRequest)
ULONG ReadySummary
Definition: ketypes.h:726
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
PKPRCB KiProcessorBlock[]
Definition: krnlinit.c:32
#define DPRINT1
Definition: precomp.h:8
volatile UCHAR State
Definition: ketypes.h:997
USHORT Number
Definition: ketypes.h:559
unsigned int ULONG
Definition: retypes.h:1
#define HIGH_PRIORITY
LONG_PTR FASTCALL KiSwapThread ( IN PKTHREAD  CurrentThread,
IN PKPRCB  Prcb 
)

Definition at line 355 of file thrdschd.c.

Referenced by KeDelayExecutionThread(), KeRemoveQueue(), KeTerminateThread(), KeWaitForGate(), KeWaitForMultipleObjects(), and KeWaitForSingleObject().

357 {
359  KIRQL WaitIrql;
360  LONG_PTR WaitStatus;
361  PKTHREAD NextThread;
363 
364  /* Acquire the PRCB lock */
365  KiAcquirePrcbLock(Prcb);
366 
367  /* Get the next thread */
368  NextThread = Prcb->NextThread;
369  if (NextThread)
370  {
371  /* Already got a thread, set it up */
372  Prcb->NextThread = NULL;
373  Prcb->CurrentThread = NextThread;
374  NextThread->State = Running;
375  }
376  else
377  {
378  /* Try to find a ready thread */
379  NextThread = KiSelectReadyThread(0, Prcb);
380  if (NextThread)
381  {
382  /* Switch to it */
383  Prcb->CurrentThread = NextThread;
384  NextThread->State = Running;
385  }
386  else
387  {
388  /* Set the idle summary */
389  InterlockedOrSetMember(&KiIdleSummary, Prcb->SetMember);
390 
391  /* Schedule the idle thread */
392  NextThread = Prcb->IdleThread;
393  Prcb->CurrentThread = NextThread;
394  NextThread->State = Running;
395  }
396  }
397 
398  /* Sanity check and release the PRCB */
399  ASSERT(CurrentThread != Prcb->IdleThread);
400  KiReleasePrcbLock(Prcb);
401 
402  /* Save the wait IRQL */
403  WaitIrql = CurrentThread->WaitIrql;
404 
405  /* Swap contexts */
406  ApcState = KiSwapContext(WaitIrql, CurrentThread);
407 
408  /* Get the wait status */
409  WaitStatus = CurrentThread->WaitStatus;
410 
411  /* Check if we need to deliver APCs */
412  if (ApcState)
413  {
414  /* Lower to APC_LEVEL */
416 
417  /* Deliver APCs */
419  ASSERT(WaitIrql == 0);
420  }
421 
422  /* Lower IRQL back to what it was and return the wait status */
423  KeLowerIrql(WaitIrql);
424  return WaitStatus;
425 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
smooth NULL
Definition: ftsmooth.c:513
unsigned char BOOLEAN
#define InterlockedOrSetMember(Destination, SetMember)
Definition: thrdschd.c:19
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
ULONG_PTR KiIdleSummary
Definition: thrdschd.c:25
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1411
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
volatile UCHAR State
Definition: ketypes.h:997
VOID NTAPI KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: apc.c:302
#define APC_LEVEL
Definition: env_spec_w32.h:695
NTSTATUS NTAPI NtYieldExecution ( VOID  )

Definition at line 744 of file thrdschd.c.

Referenced by IntReadConsole(), KeDelayExecutionThread(), KiInitializeKernel(), and SwitchToThread().

745 {
747  KIRQL OldIrql;
748  PKPRCB Prcb;
749  PKTHREAD Thread, NextThread;
750 
751  /* NB: No instructions (other than entry code) should preceed this line */
752 
753  /* Fail if there's no ready summary */
755 
756  /* Now get the current thread, set the status... */
757  Status = STATUS_NO_YIELD_PERFORMED;
758  Thread = KeGetCurrentThread();
759 
760  /* Raise IRQL to synch and get the KPRCB now */
761  OldIrql = KeRaiseIrqlToSynchLevel();
762  Prcb = KeGetCurrentPrcb();
763 
764  /* Now check if there's still a ready summary */
765  if (Prcb->ReadySummary)
766  {
767  /* Acquire thread and PRCB lock */
768  KiAcquireThreadLock(Thread);
769  KiAcquirePrcbLock(Prcb);
770 
771  /* Find a new thread to run if none was selected */
772  if (!Prcb->NextThread) Prcb->NextThread = KiSelectReadyThread(1, Prcb);
773 
774  /* Make sure we still have a next thread to schedule */
775  NextThread = Prcb->NextThread;
776  if (NextThread)
777  {
778  /* Reset quantum and recalculate priority */
779  Thread->Quantum = Thread->QuantumReset;
780  Thread->Priority = KiComputeNewPriority(Thread, 1);
781 
782  /* Release the thread lock */
783  KiReleaseThreadLock(Thread);
784 
785  /* Set context swap busy */
786  KiSetThreadSwapBusy(Thread);
787 
788  /* Set the new thread as running */
789  Prcb->NextThread = NULL;
790  Prcb->CurrentThread = NextThread;
791  NextThread->State = Running;
792 
793  /* Setup a yield wait and queue the thread */
794  Thread->WaitReason = WrYieldExecution;
795  KxQueueReadyThread(Thread, Prcb);
796 
797  /* Make it wait at APC_LEVEL */
798  Thread->WaitIrql = APC_LEVEL;
799 
800  /* Sanity check */
801  ASSERT(OldIrql <= DISPATCH_LEVEL);
802 
803  /* Swap to new thread */
804  KiSwapContext(APC_LEVEL, Thread);
805  Status = STATUS_SUCCESS;
806  }
807  else
808  {
809  /* Release the PRCB and thread lock */
810  KiReleasePrcbLock(Prcb);
811  KiReleaseThreadLock(Thread);
812  }
813  }
814 
815  /* Lower IRQL and return */
816  KeLowerIrql(OldIrql);
817  return Status;
818 }
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
FORCEINLINE VOID KiReleasePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:224
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define STATUS_NO_YIELD_PERFORMED
Definition: ntstatus.h:150
return STATUS_SUCCESS
Definition: btrfs.c:2664
FORCEINLINE VOID KiSetThreadSwapBusy(IN PKTHREAD Thread)
Definition: ke_x.h:204
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
SCHAR Priority
Definition: ketypes.h:974
struct _KTHREAD * NextThread
Definition: ketypes.h:567
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
FORCEINLINE SCHAR KiComputeNewPriority(IN PKTHREAD Thread, IN SCHAR Adjustment)
Definition: ke_x.h:1458
UCHAR KIRQL
Definition: env_spec_w32.h:591
FORCEINLINE VOID KxQueueReadyThread(IN PKTHREAD Thread, IN PKPRCB Prcb)
Definition: ke_x.h:1343
#define KiGetCurrentReadySummary()
Definition: thrdschd.c:736
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:214
smooth NULL
Definition: ftsmooth.c:513
UCHAR WaitReason
Definition: ketypes.h:1249
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Status
Definition: gdiplustypes.h:24
UCHAR QuantumReset
Definition: ketypes.h:1300
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
ULONG ReadySummary
Definition: ketypes.h:726
LONG NTSTATUS
Definition: DriverTester.h:11
FORCEINLINE PKTHREAD KiSelectReadyThread(IN KPRIORITY Priority, IN PKPRCB Prcb)
Definition: ke_x.h:1408
volatile UCHAR State
Definition: ketypes.h:997
#define KeGetCurrentThread
Definition: hal.h:44
#define APC_LEVEL
Definition: env_spec_w32.h:695
KIRQL WaitIrql
Definition: ketypes.h:999
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156

Variable Documentation

ULONG_PTR KiIdleSMTSummary

Definition at line 26 of file thrdschd.c.