00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
#include "ki.h"
00031
00032
00033
00034
00035
00036
00037
00038
#if defined(_COLLECT_SWITCH_DATA_)
00039
00040
#define KiIncrementSwitchCounter(Member) KeThreadSwitchCounters.Member += 1
00041
00042
#else
00043
00044 #define KiIncrementSwitchCounter(Member)
00045
00046
#endif
00047
00048
VOID
00049 KiSuspendNop (
00050 IN
PKAPC Apc,
00051 IN OUT PKNORMAL_ROUTINE *NormalRoutine,
00052 IN OUT PVOID *NormalContext,
00053 IN OUT PVOID *SystemArgument1,
00054 IN OUT PVOID *SystemArgument2
00055 )
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 {
00085
00086
00087
00088
00089
00090
return;
00091 }
00092
00093
PKTHREAD
00094
FASTCALL
00095 KiFindReadyThread (
00096 IN ULONG Processor,
00097 IN KPRIORITY LowPriority
00098 )
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 {
00124
00125 ULONG HighPriority;
00126 PRLIST_ENTRY ListHead;
00127 PRLIST_ENTRY NextEntry;
00128 ULONG PrioritySet;
00129 KAFFINITY ProcessorSet;
00130
PRKTHREAD Thread;
00131
PRKTHREAD Thread1;
00132 ULONG TickLow;
00133 ULONG WaitTime;
00134
00135
00136
00137
00138
00139
00140 PrioritySet = (~((1 << LowPriority) - 1)) &
KiReadySummary;
00141
00142
#if !defined(NT_UP)
00143
00144 ProcessorSet = (KAFFINITY)(1 << Processor);
00145
00146
#endif
00147
00148
FindFirstSetLeftMember(PrioritySet, &HighPriority);
00149 ListHead = &
KiDispatcherReadyListHead[HighPriority];
00150 PrioritySet <<= (31 - HighPriority);
00151
while (PrioritySet != 0) {
00152
00153
00154
00155
00156
00157
00158
if ((LONG)PrioritySet < 0) {
00159 NextEntry = ListHead->Flink;
00160
00161
ASSERT(NextEntry != ListHead);
00162
00163
#if defined(NT_UP)
00164
00165 Thread = CONTAINING_RECORD(NextEntry,
KTHREAD, WaitListEntry);
00166 RemoveEntryList(&Thread->
WaitListEntry);
00167
if (IsListEmpty(ListHead)) {
00168
ClearMember(HighPriority,
KiReadySummary);
00169 }
00170
00171
return (
PKTHREAD)Thread;
00172
00173
#else
00174
00175
00176
00177
00178
00179
00180
while (NextEntry != ListHead) {
00181 Thread = CONTAINING_RECORD(NextEntry,
KTHREAD, WaitListEntry);
00182 NextEntry = NextEntry->Flink;
00183
if (Thread->
Affinity & ProcessorSet) {
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 TickLow = KiQueryLowTickCount();
00195 WaitTime = TickLow - Thread->
WaitTime;
00196
if ((
KiThreadSelectNotifyRoutine ?
00197 (
KiThreadSelectNotifyRoutine(((
PETHREAD)Thread)->Cid.UniqueThread) ==
FALSE) :
00198 (((ULONG)Thread->NextProcessor != Processor) &&
00199 ((ULONG)Thread->IdealProcessor != Processor))) &&
00200 (WaitTime < (
READY_SKIP_QUANTUM + 1)) &&
00201 (HighPriority < (LOW_REALTIME_PRIORITY + 9))) {
00202
00203
00204
00205
00206
00207
00208
00209
while (NextEntry != ListHead) {
00210 Thread1 = CONTAINING_RECORD(NextEntry,
00211
KTHREAD,
00212 WaitListEntry);
00213
00214 NextEntry = NextEntry->Flink;
00215
if ((Thread1->
Affinity & ProcessorSet) &&
00216 (
KiThreadSelectNotifyRoutine ?
00217 (
KiThreadSelectNotifyRoutine(((
PETHREAD)Thread)->Cid.UniqueThread) !=
FALSE) :
00218 (((ULONG)Thread1->
NextProcessor == Processor) ||
00219 ((ULONG)Thread1->
IdealProcessor == Processor)))) {
00220 Thread = Thread1;
00221
break;
00222 }
00223
00224 WaitTime = TickLow - Thread1->
WaitTime;
00225
if (WaitTime >= (
READY_SKIP_QUANTUM + 1)) {
00226
break;
00227 }
00228 }
00229 }
00230
00231
if (Processor == (ULONG)Thread->IdealProcessor) {
00232
KiIncrementSwitchCounter(FindIdeal);
00233
00234 }
else if (Processor == (ULONG)Thread->NextProcessor) {
00235
KiIncrementSwitchCounter(FindLast);
00236
00237 }
else {
00238
KiIncrementSwitchCounter(FindAny);
00239 }
00240
00241 Thread->NextProcessor = (CCHAR)Processor;
00242
00243 RemoveEntryList(&Thread->WaitListEntry);
00244
if (IsListEmpty(ListHead)) {
00245
ClearMember(HighPriority,
KiReadySummary);
00246 }
00247
00248
return (
PKTHREAD)Thread;
00249 }
00250 }
00251
00252
#endif
00253
00254 }
00255
00256 HighPriority -= 1;
00257 ListHead -= 1;
00258 PrioritySet <<= 1;
00259 };
00260
00261
00262
00263
00264
00265
return (
PKTHREAD)
NULL;
00266 }
00267
00268
VOID
00269
FASTCALL
00270 KiReadyThread (
00271 IN
PRKTHREAD Thread
00272 )
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 {
00297
00298 PRKPRCB Prcb;
00299 BOOLEAN Preempted;
00300 KPRIORITY Priority;
00301
PRKPROCESS Process;
00302 ULONG Processor;
00303 KPRIORITY ThreadPriority;
00304
PRKTHREAD Thread1;
00305 KAFFINITY IdleSet;
00306
00307
00308
00309
00310
00311
00312 Preempted = Thread->Preempted;
00313 Thread->Preempted =
FALSE;
00314 ThreadPriority = Thread->Priority;
00315 Thread->WaitTime = KiQueryLowTickCount();
00316
00317
00318
00319
00320
00321
00322 Process = Thread->ApcState.Process;
00323
if (Process->
State !=
ProcessInMemory) {
00324 Thread->
State =
Ready;
00325 Thread->ProcessReadyQueue =
TRUE;
00326 InsertTailList(&Process->
ReadyListHead, &Thread->WaitListEntry);
00327
if (Process->
State ==
ProcessOutOfMemory) {
00328 Process->
State =
ProcessInTransition;
00329 InsertTailList(&
KiProcessInSwapListHead, &Process->
SwapListEntry);
00330
KiSwapEvent.
Header.
SignalState = 1;
00331
if (IsListEmpty(&
KiSwapEvent.
Header.
WaitListHead) ==
FALSE) {
00332
KiWaitTest(&
KiSwapEvent,
BALANCE_INCREMENT);
00333 }
00334 }
00335
00336
return;
00337
00338 }
else if (Thread->KernelStackResident ==
FALSE) {
00339
00340
00341
00342
00343
00344
00345
00346
00347 Process->
StackCount += 1;
00348 Thread->State =
Transition;
00349 InsertTailList(&
KiStackInSwapListHead, &Thread->WaitListEntry);
00350
KiSwapEvent.
Header.
SignalState = 1;
00351
if (IsListEmpty(&
KiSwapEvent.
Header.
WaitListHead) ==
FALSE) {
00352
KiWaitTest(&
KiSwapEvent,
BALANCE_INCREMENT);
00353 }
00354
00355
return;
00356
00357 }
else {
00358
00359
00360
00361
00362
00363
00364
00365
00366
#if defined(NT_UP)
00367
00368 Prcb =
KiProcessorBlock[0];
00369
if (
KiIdleSummary != 0) {
00370
KiIdleSummary = 0;
00371
KiIncrementSwitchCounter(IdleLast);
00372 Prcb->NextThread = Thread;
00373 Thread->State =
Standby;
00374
00375
#else
00376
00377 IdleSet =
KiIdleSummary & Thread->Affinity;
00378
if (IdleSet != 0) {
00379 Prcb =
KeGetCurrentPrcb();
00380 Processor = Thread->IdealProcessor;
00381
if ((IdleSet & (1 << Processor)) == 0) {
00382 Processor = Thread->NextProcessor;
00383
if ((IdleSet & (1 << Processor)) == 0) {
00384
if ((IdleSet & Prcb->SetMember) == 0) {
00385
FindFirstSetLeftMember(IdleSet, &Processor);
00386
KiIncrementSwitchCounter(IdleAny);
00387
00388 }
else {
00389 Processor = Prcb->Number;
00390
KiIncrementSwitchCounter(IdleCurrent);
00391 }
00392
00393 }
else {
00394
KiIncrementSwitchCounter(IdleLast);
00395 }
00396
00397 }
else {
00398
KiIncrementSwitchCounter(IdleIdeal);
00399 }
00400
00401 Thread->NextProcessor = (CCHAR)Processor;
00402
ClearMember(Processor,
KiIdleSummary);
00403
KiProcessorBlock[Processor]->NextThread = Thread;
00404 Thread->State =
Standby;
00405
00406
if ((
PoSleepingSummary & (1 << Processor)) &&
00407 Processor != (ULONG) Prcb->Number) {
00408
KiIpiSend(1 << Processor,
IPI_DPC);
00409 }
00410
#endif
00411
00412
return;
00413
00414 }
else {
00415
00416
#if !defined(NT_UP)
00417
00418 Processor = Thread->IdealProcessor;
00419
if ((Thread->Affinity & (1 << Processor)) == 0) {
00420 Processor = Thread->NextProcessor;
00421
if ((Thread->Affinity & (1 << Processor)) == 0) {
00422
FindFirstSetLeftMember(Thread->Affinity, &Processor);
00423 }
00424 }
00425
00426 Thread->NextProcessor = (CCHAR)Processor;
00427 Prcb =
KiProcessorBlock[Processor];
00428
00429
#endif
00430
00431
if (Prcb->NextThread !=
NULL) {
00432 Thread1 = Prcb->NextThread;
00433
if (ThreadPriority > Thread1->
Priority) {
00434 Thread1->
Preempted =
TRUE;
00435 Prcb->NextThread = Thread;
00436 Thread->State =
Standby;
00437
KiReadyThread(Thread1);
00438
KiIncrementSwitchCounter(PreemptLast);
00439
return;
00440 }
00441
00442 }
else {
00443 Thread1 = Prcb->CurrentThread;
00444
if (ThreadPriority > Thread1->
Priority) {
00445 Thread1->
Preempted =
TRUE;
00446 Prcb->NextThread = Thread;
00447 Thread->State =
Standby;
00448
KiRequestDispatchInterrupt(Thread->NextProcessor);
00449
KiIncrementSwitchCounter(PreemptLast);
00450
return;
00451 }
00452 }
00453 }
00454 }
00455
00456
00457
00458
00459
00460
00461
00462
00463 Thread->State =
Ready;
00464
if (Preempted !=
FALSE) {
00465 InsertHeadList(&
KiDispatcherReadyListHead[ThreadPriority],
00466 &Thread->WaitListEntry);
00467
00468 }
else {
00469 InsertTailList(&
KiDispatcherReadyListHead[ThreadPriority],
00470 &Thread->WaitListEntry);
00471 }
00472
00473
SetMember(ThreadPriority,
KiReadySummary);
00474
return;
00475 }
00476
00477
PRKTHREAD
00478
FASTCALL
00479 KiSelectNextThread (
00480 IN
PRKTHREAD Thread
00481 )
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 {
00502
00503 PRKPRCB Prcb;
00504 ULONG Processor;
00505
PRKTHREAD Thread1;
00506
00507
00508
00509
00510
00511
#if !defined(NT_UP)
00512
00513 Processor = Thread->
NextProcessor;
00514 Prcb =
KiProcessorBlock[Processor];
00515
00516
#else
00517
00518 Prcb =
KiProcessorBlock[0];
00519
00520
#endif
00521
00522
00523
00524
00525
00526
00527
if ((Thread1 = Prcb->NextThread) !=
NULL) {
00528 Prcb->NextThread = (
PKTHREAD)
NULL;
00529
00530 }
else {
00531
00532
00533
00534
00535
00536
#if !defined(NT_UP)
00537
00538 Thread1 =
KiFindReadyThread(Processor, 0);
00539
00540
#else
00541
00542 Thread1 =
KiFindReadyThread(0, 0);
00543
00544
#endif
00545
00546
00547
00548
00549
00550
00551
if (Thread1 ==
NULL) {
00552
KiIncrementSwitchCounter(SwitchToIdle);
00553 Thread1 = Prcb->IdleThread;
00554
00555
#if !defined(NT_UP)
00556
00557
SetMember(Processor,
KiIdleSummary);
00558
00559
#else
00560
KiIdleSummary = 1;
00561
00562
#endif
00563
00564 }
00565 }
00566
00567
00568
00569
00570
00571
return Thread1;
00572 }
00573
00574
VOID
00575
FASTCALL
00576 KiSetPriorityThread (
00577 IN
PRKTHREAD Thread,
00578 IN KPRIORITY Priority
00579 )
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 {
00603
00604 PRKPRCB Prcb;
00605 ULONG Processor;
00606 KPRIORITY ThreadPriority;
00607
PRKTHREAD Thread1;
00608
00609
ASSERT(Priority <= HIGH_PRIORITY);
00610
00611
00612
00613
00614
00615 ThreadPriority = Thread->Priority;
00616
00617
00618
00619
00620
00621
00622
if (Priority != ThreadPriority) {
00623 Thread->Priority = (SCHAR)Priority;
00624
00625
00626
00627
00628
00629
switch (Thread->State) {
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
case Ready:
00640
if (Thread->ProcessReadyQueue ==
FALSE) {
00641 RemoveEntryList(&Thread->WaitListEntry);
00642
if (IsListEmpty(&
KiDispatcherReadyListHead[ThreadPriority])) {
00643
ClearMember(ThreadPriority,
KiReadySummary);
00644 }
00645
00646
if (Priority < ThreadPriority) {
00647 InsertTailList(&
KiDispatcherReadyListHead[Priority],
00648 &Thread->WaitListEntry);
00649
SetMember(Priority,
KiReadySummary);
00650
00651 }
else {
00652
KiReadyThread(Thread);
00653 }
00654 }
00655
00656
break;
00657
00658
00659
00660
00661
00662
00663
00664
00665
case Standby:
00666
00667
#if !defined(NT_UP)
00668
00669 Processor = Thread->NextProcessor;
00670
00671
#endif
00672
00673
if (Priority < ThreadPriority) {
00674
00675
#if !defined(NT_UP)
00676
00677 Thread1 =
KiFindReadyThread(Processor, Priority);
00678
00679
#else
00680
00681 Thread1 =
KiFindReadyThread(0, Priority);
00682
00683
#endif
00684
00685
if (Thread1 !=
NULL) {
00686
00687
#if !defined(NT_UP)
00688
00689 Prcb =
KiProcessorBlock[Processor];
00690
00691
#else
00692
00693 Prcb =
KiProcessorBlock[0];
00694
00695
#endif
00696
00697 Thread1->
State =
Standby;
00698 Prcb->NextThread = Thread1;
00699
KiReadyThread(Thread);
00700 }
00701 }
00702
00703
break;
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
case Running:
00714
00715
#if !defined(NT_UP)
00716
00717 Processor = Thread->NextProcessor;
00718 Prcb =
KiProcessorBlock[Processor];
00719
00720
#else
00721
00722 Prcb =
KiProcessorBlock[0];
00723
00724
#endif
00725
00726
if (Prcb->NextThread ==
NULL) {
00727
if (Priority < ThreadPriority) {
00728
00729
#if !defined(NT_UP)
00730
00731 Thread1 =
KiFindReadyThread(Processor, Priority);
00732
00733
#else
00734
00735 Thread1 =
KiFindReadyThread(0, Priority);
00736
00737
#endif
00738
00739
if (Thread1 !=
NULL) {
00740 Thread1->
State =
Standby;
00741 Prcb->NextThread = Thread1;
00742
00743
#if !defined(NT_UP)
00744
00745
KiRequestDispatchInterrupt(Processor);
00746
00747
#endif
00748
00749 }
00750 }
00751 }
00752
00753
break;
00754
00755
00756
00757
00758
00759
00760
00761
default:
00762
break;
00763 }
00764 }
00765
00766
return;
00767 }
00768
00769
VOID
00770 KiSuspendThread (
00771 IN PVOID NormalContext,
00772 IN PVOID SystemArgument1,
00773 IN PVOID SystemArgument2
00774 )
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 {
00797
00798
PRKTHREAD Thread;
00799
PKAPC Apc;
00800
00801
00802
00803
00804
00805
00806 Thread =
KeGetCurrentThread();
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
if ( Thread->
ApcState.
UserApcPending ) {
00818 Apc = CONTAINING_RECORD((Thread->
ApcState.
ApcListHead[
UserMode].Flink),
KAPC, ApcListEntry);
00819
if ( Apc->
KernelRoutine ==
PsExitSpecialApc ) {
00820
return;
00821 }
00822 }
00823
KeWaitForSingleObject(&Thread->
SuspendSemaphore,
00824
Suspended,
00825
KernelMode,
00826
FALSE,
00827 (PLARGE_INTEGER)
NULL);
00828
00829 }
00830
#if 0
00831
00832
VOID
00833 KiVerifyReadySummary (
00834 VOID
00835 )
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 {
00854
00855 ULONG
Index;
00856 ULONG Summary;
00857
PKTHREAD Thread;
00858
00859
extern ULONG
InitializationPhase;
00860
00861
00862
00863
00864
00865
if (
InitializationPhase == 2) {
00866
00867
00868
00869
00870
00871 Summary = 0;
00872
for (
Index = 0;
Index < MAXIMUM_PRIORITY;
Index += 1) {
00873
if (IsListEmpty(&KiDispatcherReadyListHead[Index]) ==
FALSE) {
00874 Summary |= (1 <<
Index);
00875 }
00876 }
00877
00878
00879
00880
00881
00882
00883
if (Summary !=
KiReadySummary) {
00884 DbgBreakPoint();
00885 }
00886
00887
00888
00889
00890
00891
00892
00893 Thread =
KeGetCurrentPrcb()->NextThread;
00894
if (Thread ==
NULL) {
00895 Thread =
KeGetCurrentPrcb()->CurrentThread;
00896 }
00897
00898
if ((1 << Thread->
Priority) < (Summary & ((1 << Thread->
Priority) - 1))) {
00899 DbgBreakPoint();
00900 }
00901 }
00902
00903
return;
00904 }
00905
#endif