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
00031
#include "ki.h"
00032
00033
00034
00035
00036
00037
00038 #define ASSERT_THREAD(E) { \
00039
ASSERT((E)->Header.Type == ThreadObject); \
00040
}
00041
00042
VOID
00043 KeInitializeThread (
00044 IN
PKTHREAD Thread,
00045 IN PVOID KernelStack,
00046 IN PKSYSTEM_ROUTINE SystemRoutine,
00047 IN PKSTART_ROUTINE StartRoutine OPTIONAL,
00048 IN PVOID StartContext OPTIONAL,
00049 IN PCONTEXT ContextFrame OPTIONAL,
00050 IN PVOID Teb OPTIONAL,
00051 IN
PKPROCESS Process
00052 )
00053
00054
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
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 {
00110
00111 ULONG
Index;
00112 KIRQL OldIrql;
00113
PKTIMER Timer;
00114
PKWAIT_BLOCK WaitBlock;
00115
00116
00117
00118
00119
00120
00121 Thread->Header.Type =
ThreadObject;
00122 Thread->Header.Size =
sizeof(
KTHREAD) /
sizeof(LONG);
00123 InitializeListHead(&Thread->Header.WaitListHead);
00124
00125
00126
00127
00128
00129 InitializeListHead(&Thread->MutantListHead);
00130
00131
00132
00133
00134
00135
for (
Index = 0;
Index < (
THREAD_WAIT_OBJECTS + 1);
Index += 1) {
00136 Thread->WaitBlock[
Index].Thread = Thread;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 Thread->AutoAlignment = Process->AutoAlignment;
00148 Thread->EnableStackSwap =
TRUE;
00149 Thread->KernelStackResident =
TRUE;
00150
00151
00152
00153
00154
00155
00156
00157
00158 Thread->ServiceTable = (PVOID)&
KeServiceDescriptorTable[0];
00159
00160
00161
00162
00163
00164
00165 Thread->ApcStatePointer[0] = &Thread->ApcState;
00166 Thread->ApcStatePointer[1] = &Thread->SavedApcState;
00167 InitializeListHead(&Thread->ApcState.ApcListHead[
KernelMode]);
00168 InitializeListHead(&Thread->ApcState.ApcListHead[
UserMode]);
00169 Thread->ApcState.Process = Process;
00170 Thread->ApcQueueable =
TRUE;
00171
00172
00173
00174
00175
00176
00177
KeInitializeApc(&Thread->SuspendApc,
00178 Thread,
00179
OriginalApcEnvironment,
00180 (
PKKERNEL_ROUTINE)
KiSuspendNop,
00181 (
PKRUNDOWN_ROUTINE)
NULL,
00182
KiSuspendThread,
00183
KernelMode,
00184
NULL);
00185
00186
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0
L, 2
L);
00187
00188
00189
00190
00191
00192
00193
00194
00195 Timer = &Thread->Timer;
00196
KeInitializeTimer(Timer);
00197 WaitBlock = &Thread->WaitBlock[
TIMER_WAIT_BLOCK];
00198 WaitBlock->
Object = Timer;
00199 WaitBlock->
WaitKey = (CSHORT)STATUS_TIMEOUT;
00200 WaitBlock->
WaitType = WaitAny;
00201 WaitBlock->
WaitListEntry.Flink = &Timer->
Header.
WaitListHead;
00202 WaitBlock->
WaitListEntry.Blink = &Timer->
Header.
WaitListHead;
00203
00204
00205
00206
00207
00208
KeInitializeSpinLock(&Thread->ApcQueueLock);
00209
00210
00211
00212
00213
00214 Thread->Teb = Teb;
00215
00216
00217
00218
00219
00220 Thread->InitialStack = KernelStack;
00221 Thread->StackBase = KernelStack;
00222 Thread->StackLimit = (PVOID)((ULONG_PTR)KernelStack - KERNEL_STACK_SIZE);
00223
KiInitializeContextThread(Thread,
00224 SystemRoutine,
00225 StartRoutine,
00226 StartContext,
00227 ContextFrame);
00228
00229
00230
00231
00232
00233
00234 Thread->BasePriority = Process->BasePriority;
00235 Thread->Priority = Thread->BasePriority;
00236 Thread->Affinity = Process->Affinity;
00237 Thread->UserAffinity = Process->Affinity;
00238 Thread->SystemAffinityActive =
FALSE;
00239 Thread->Quantum = Process->ThreadQuantum;
00240 Thread->State =
Initialized;
00241 Thread->DisableBoost = Process->DisableBoost;
00242
00243
#ifdef i386
00244
00245 Thread->Iopl = Process->Iopl;
00246
00247
#endif
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
KiLockDispatcherDatabase(&OldIrql);
00259 InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);
00260
if (Process->StackCount == MAXSHORT) {
00261 Process->StackCount = 1;
00262
00263 }
else {
00264 Process->StackCount += 1;
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274 Process->ThreadSeed += 1;
00275 Thread->IdealProcessor = (UCHAR)(Process->ThreadSeed %
KeNumberProcessors);
00276
KiUnlockDispatcherDatabase(OldIrql);
00277
return;
00278 }
00279
00280 BOOLEAN
00281 KeAlertThread (
00282 IN
PKTHREAD Thread,
00283 IN KPROCESSOR_MODE AlertMode
00284 )
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 {
00309
00310 BOOLEAN Alerted;
00311 KIRQL OldIrql;
00312
00313
ASSERT_THREAD(Thread);
00314
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00315
00316
00317
00318
00319
00320
00321
KiLockDispatcherDatabase(&OldIrql);
00322 KiAcquireSpinLock(&Thread->ApcQueueLock);
00323
00324
00325
00326
00327
00328
00329 Alerted = Thread->Alerted[AlertMode];
00330
00331
00332
00333
00334
00335
00336
if (Alerted ==
FALSE) {
00337
00338
00339
00340
00341
00342
00343
00344
if ((Thread->State ==
Waiting) && (Thread->Alertable ==
TRUE) &&
00345 (AlertMode <= Thread->WaitMode)) {
00346
KiUnwaitThread(Thread, STATUS_ALERTED,
ALERT_INCREMENT);
00347
00348 }
else {
00349 Thread->Alerted[AlertMode] =
TRUE;
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359 KiReleaseSpinLock(&Thread->ApcQueueLock);
00360
KiUnlockDispatcherDatabase(OldIrql);
00361
return Alerted;
00362 }
00363
00364 ULONG
00365 KeAlertResumeThread (
00366 IN
PKTHREAD Thread
00367 )
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 {
00388
00389 ULONG OldCount;
00390 KIRQL OldIrql;
00391
00392
ASSERT_THREAD(Thread);
00393
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00394
00395
00396
00397
00398
00399
00400
KiLockDispatcherDatabase(&OldIrql);
00401 KiAcquireSpinLock(&Thread->ApcQueueLock);
00402
00403
00404
00405
00406
00407
00408
if (Thread->Alerted[
KernelMode] ==
FALSE) {
00409
00410
00411
00412
00413
00414
00415
00416
if ((Thread->State ==
Waiting) && (Thread->Alertable ==
TRUE)) {
00417
KiUnwaitThread(Thread, STATUS_ALERTED,
ALERT_INCREMENT);
00418
00419 }
else {
00420 Thread->Alerted[
KernelMode] =
TRUE;
00421 }
00422 }
00423
00424
00425
00426
00427
00428 OldCount = Thread->SuspendCount;
00429
00430
00431
00432
00433
00434
if (OldCount != 0) {
00435 Thread->SuspendCount -= 1;
00436
00437
00438
00439
00440
00441
00442
if ((Thread->SuspendCount == 0) && (Thread->FreezeCount == 0)) {
00443 Thread->SuspendSemaphore.Header.SignalState += 1;
00444
KiWaitTest(&Thread->SuspendSemaphore,
RESUME_INCREMENT);
00445 }
00446 }
00447
00448
00449
00450
00451
00452
00453 KiReleaseSpinLock(&Thread->ApcQueueLock);
00454
KiUnlockDispatcherDatabase(OldIrql);
00455
return OldCount;
00456 }
00457
00458
VOID
00459 KeBoostPriorityThread (
00460 IN
PKTHREAD Thread,
00461 IN KPRIORITY Increment
00462 )
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 {
00485
00486 KIRQL OldIrql;
00487
00488
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00489
00490
00491
00492
00493
00494
KiLockDispatcherDatabase(&OldIrql);
00495
00496
00497
00498
00499
00500
00501
if (Thread->Priority < LOW_REALTIME_PRIORITY) {
00502
KiBoostPriorityThread(Thread,
Increment);
00503 }
00504
00505
00506
00507
00508
00509
00510
KiUnlockDispatcherDatabase(OldIrql);
00511
return;
00512 }
00513
00514 KAFFINITY
00515 KeConfineThread (
00516 VOID
00517 )
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536 {
00537
00538 KAFFINITY Affinity;
00539 KIRQL OldIrql;
00540
PKTHREAD Thread;
00541
00542
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00543
00544
00545
00546
00547
00548 Thread =
KeGetCurrentThread();
00549
KiLockDispatcherDatabase(&OldIrql);
00550
00551
00552
00553
00554
00555
00556 Affinity = Thread->
Affinity;
00557 Thread->
Affinity = (KAFFINITY)(1 << Thread->
NextProcessor);
00558
00559
00560
00561
00562
00563
00564
KiUnlockDispatcherDatabase(OldIrql);
00565
00566
00567
00568
00569
00570
return Affinity;
00571 }
00572
00573 BOOLEAN
00574 KeDisableApcQueuingThread (
00575 IN
PKTHREAD Thread
00576 )
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 {
00595
00596 BOOLEAN ApcQueueable;
00597 KIRQL OldIrql;
00598
00599
ASSERT_THREAD(Thread);
00600
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00601
00602
00603
00604
00605
00606
KiLockDispatcherDatabase(&OldIrql);
00607
00608
00609
00610
00611
00612
00613 ApcQueueable = Thread->ApcQueueable;
00614 Thread->ApcQueueable =
FALSE;
00615
00616
00617
00618
00619
00620
00621
KiUnlockDispatcherDatabase(OldIrql);
00622
00623
00624
00625
00626
00627
return ApcQueueable;
00628 }
00629
00630 BOOLEAN
00631 KeEnableApcQueuingThread (
00632 IN
PKTHREAD Thread
00633 )
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 {
00652
00653 BOOLEAN ApcQueueable;
00654 KIRQL OldIrql;
00655
00656
ASSERT_THREAD(Thread);
00657
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00658
00659
00660
00661
00662
00663
KiLockDispatcherDatabase(&OldIrql);
00664
00665
00666
00667
00668
00669
00670 ApcQueueable = Thread->ApcQueueable;
00671 Thread->ApcQueueable =
TRUE;
00672
00673
00674
00675
00676
00677
00678
KiUnlockDispatcherDatabase(OldIrql);
00679
00680
00681
00682
00683
00684
return ApcQueueable;
00685 }
00686
00687 ULONG
00688 KeForceResumeThread (
00689 IN
PKTHREAD Thread
00690 )
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 {
00711
00712 ULONG OldCount;
00713 KIRQL OldIrql;
00714
00715
ASSERT_THREAD(Thread);
00716
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00717
00718
00719
00720
00721
00722
KiLockDispatcherDatabase(&OldIrql);
00723
00724
00725
00726
00727
00728 OldCount = Thread->SuspendCount + Thread->FreezeCount;
00729
00730
00731
00732
00733
00734
00735
if (OldCount != 0) {
00736 Thread->FreezeCount = 0;
00737 Thread->SuspendCount = 0;
00738 Thread->SuspendSemaphore.Header.SignalState += 1;
00739
KiWaitTest(&Thread->SuspendSemaphore,
RESUME_INCREMENT);
00740 }
00741
00742
00743
00744
00745
00746
00747
KiUnlockDispatcherDatabase(OldIrql);
00748
00749
00750
00751
00752
00753
return OldCount;
00754 }
00755
00756
VOID
00757 KeFreezeAllThreads (
00758 VOID
00759 )
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 {
00780
00781
PKTHREAD CurrentThread;
00782 PLIST_ENTRY ListHead;
00783 PLIST_ENTRY NextEntry;
00784
PKPROCESS Process;
00785
PKTHREAD Thread;
00786
PETHREAD EThread;
00787 ULONG OldCount;
00788 KIRQL OldIrql;
00789
00790
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00791
00792
00793
00794
00795
00796
00797
00798
00799 CurrentThread =
KeGetCurrentThread();
00800 Process = CurrentThread->
ApcState.
Process;
00801
KiLockDispatcherDatabase(&OldIrql);
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
while (CurrentThread->
FreezeCount != 0) {
00812
KiUnlockDispatcherDatabase(OldIrql);
00813
KiLockDispatcherDatabase(&OldIrql);
00814 }
00815
00816
KeEnterCriticalRegion();
00817
00818
00819
00820
00821
00822 ListHead = &Process->
ThreadListHead;
00823 NextEntry = ListHead->Flink;
00824
do {
00825
00826
00827
00828
00829
00830
00831 Thread = CONTAINING_RECORD(NextEntry,
KTHREAD, ThreadListEntry);
00832
if (Thread != CurrentThread) {
00833
00834 EThread = (
PETHREAD) Thread;
00835
if ( EThread->
ThreadListEntry.Flink ==
NULL ) {
00836 ;
00837 }
else {
00838
00839
00840
00841
00842
00843
00844 OldCount = Thread->
FreezeCount;
00845
00846
ASSERT(OldCount != MAXIMUM_SUSPEND_COUNT);
00847
00848 Thread->
FreezeCount += 1;
00849
if ((OldCount == 0) && (Thread->
SuspendCount == 0)) {
00850
if (
KiInsertQueueApc(&Thread->
SuspendApc,
RESUME_INCREMENT) ==
FALSE) {
00851 Thread->
SuspendSemaphore.
Header.
SignalState -= 1;
00852 }
00853 }
00854 }
00855 }
00856 NextEntry = NextEntry->Flink;
00857 }
while (NextEntry != ListHead);
00858
00859
00860
00861
00862
00863
00864
KiUnlockDispatcherDatabase(OldIrql);
00865
return;
00866 }
00867
00868 BOOLEAN
00869 KeQueryAutoAlignmentThread (
00870 IN
PKTHREAD Thread
00871 )
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 {
00893
00894
ASSERT_THREAD(Thread);
00895
00896
00897
00898
00899
00900
return Thread->AutoAlignment;
00901 }
00902
00903 LONG
00904 KeQueryBasePriorityThread (
00905 IN
PKTHREAD Thread
00906 )
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 {
00926
00927 LONG
Increment;
00928 KIRQL OldIrql;
00929
PKPROCESS Process;
00930
00931
ASSERT_THREAD(Thread);
00932
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
00933
00934
00935
00936
00937
00938
KiLockDispatcherDatabase(&OldIrql);
00939
00940
00941
00942
00943
00944
00945
00946
00947 Process = Thread->ApcStatePointer[0]->Process;
00948
Increment = Thread->BasePriority - Process->
BasePriority;
00949
if (Thread->Saturation != 0) {
00950
Increment = ((HIGH_PRIORITY + 1) / 2) * Thread->Saturation;
00951 }
00952
00953
00954
00955
00956
00957
00958
KiUnlockDispatcherDatabase(OldIrql);
00959
00960
00961
00962
00963
00964
return Increment;
00965 }
00966
00967 KPRIORITY
00968 KeQueryPriorityThread (
00969 IN
PKTHREAD Thread
00970 )
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988 {
00989
return Thread->Priority;
00990 }
00991
00992 BOOLEAN
00993 KeReadStateThread (
00994 IN
PKTHREAD Thread
00995 )
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 {
01014
01015
ASSERT_THREAD(Thread);
01016
01017
01018
01019
01020
01021
return (BOOLEAN)Thread->Header.SignalState;
01022 }
01023
01024
VOID
01025 KeReadyThread (
01026 IN
PKTHREAD Thread
01027 )
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 {
01051
01052 KIRQL OldIrql;
01053
01054
ASSERT_THREAD(Thread);
01055
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01056
01057
01058
01059
01060
01061
KiLockDispatcherDatabase(&OldIrql);
01062
01063
01064
01065
01066
01067
KiReadyThread(Thread);
01068
01069
01070
01071
01072
01073
01074
KiUnlockDispatcherDatabase(OldIrql);
01075
return;
01076 }
01077
01078 ULONG
01079 KeResumeThread (
01080 IN
PKTHREAD Thread
01081 )
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 {
01101
01102 ULONG OldCount;
01103 KIRQL OldIrql;
01104
01105
ASSERT_THREAD(Thread);
01106
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01107
01108
01109
01110
01111
01112
KiLockDispatcherDatabase(&OldIrql);
01113
01114
01115
01116
01117
01118 OldCount = Thread->SuspendCount;
01119
01120
01121
01122
01123
01124
if (OldCount != 0) {
01125 Thread->SuspendCount -= 1;
01126
01127
01128
01129
01130
01131
01132
if ((Thread->SuspendCount == 0) && (Thread->FreezeCount == 0)) {
01133 Thread->SuspendSemaphore.Header.SignalState += 1;
01134
KiWaitTest(&Thread->SuspendSemaphore,
RESUME_INCREMENT);
01135 }
01136 }
01137
01138
01139
01140
01141
01142
01143
KiUnlockDispatcherDatabase(OldIrql);
01144
01145
01146
01147
01148
01149
return OldCount;
01150 }
01151
01152
VOID
01153 KeRevertToUserAffinityThread (
01154 VOID
01155 )
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 {
01175
01176
PRKTHREAD CurrentThread;
01177
PRKTHREAD NextThread;
01178 KIRQL OldIrql;
01179 PKPRCB Prcb;
01180
01181
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01182
ASSERT(
KeGetCurrentThread()->SystemAffinityActive !=
FALSE);
01183
01184
01185
01186
01187
01188 CurrentThread =
KeGetCurrentThread();
01189
KiLockDispatcherDatabase(&OldIrql);
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199 CurrentThread->
Affinity = CurrentThread->
UserAffinity;
01200 CurrentThread->
SystemAffinityActive =
FALSE;
01201 Prcb =
KeGetCurrentPrcb();
01202
if (((Prcb->SetMember & CurrentThread->
Affinity) == 0) &&
01203 (Prcb->NextThread ==
NULL)) {
01204 NextThread =
KiSelectNextThread(CurrentThread);
01205 NextThread->
State =
Standby;
01206 Prcb->NextThread = NextThread;
01207 }
01208
01209
01210
01211
01212
01213
KiUnlockDispatcherDatabase(OldIrql);
01214
return;
01215 }
01216
01217
VOID
01218 KeRundownThread (
01219 )
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 {
01242
01243
PKMUTANT Mutant;
01244 PLIST_ENTRY NextEntry;
01245 KIRQL OldIrql;
01246
PKTHREAD Thread;
01247
01248
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01249
01250
01251
01252
01253
01254
#if 0
01255
01256
KiRundownChannel();
01257
01258
#endif
01259
01260
01261
01262
01263
01264 Thread =
KeGetCurrentThread();
01265
KiLockDispatcherDatabase(&OldIrql);
01266
01267
01268
01269
01270
01271
01272
01273 NextEntry = Thread->
MutantListHead.Flink;
01274
while (NextEntry != &Thread->
MutantListHead) {
01275 Mutant = CONTAINING_RECORD(NextEntry,
KMUTANT, MutantListEntry);
01276
if (Mutant->
ApcDisable != 0) {
01277
KeBugCheckEx(THREAD_TERMINATE_HELD_MUTEX,
01278 (ULONG_PTR)Thread,
01279 (ULONG_PTR)Mutant, 0, 0);
01280 }
01281
01282 RemoveEntryList(&Mutant->
MutantListEntry);
01283 Mutant->
Header.
SignalState = 1;
01284 Mutant->
Abandoned =
TRUE;
01285 Mutant->
OwnerThread = (
PKTHREAD)
NULL;
01286
if (IsListEmpty(&Mutant->
Header.
WaitListHead) !=
TRUE) {
01287
KiWaitTest(Mutant,
MUTANT_INCREMENT);
01288 }
01289
01290 NextEntry = Thread->
MutantListHead.Flink;
01291 }
01292
01293
01294
01295
01296
01297
KiUnlockDispatcherDatabase(OldIrql);
01298
return;
01299 }
01300
01301 KAFFINITY
01302 KeSetAffinityThread (
01303 IN
PKTHREAD Thread,
01304 IN KAFFINITY Affinity
01305 )
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 {
01334
01335 KAFFINITY OldAffinity;
01336 KIRQL OldIrql;
01337 PKPRCB Prcb;
01338
PKPROCESS Process;
01339 ULONG Processor;
01340 KPRIORITY ThreadPriority;
01341
PRKTHREAD Thread1;
01342
01343
ASSERT_THREAD(Thread);
01344
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01345
01346
01347
01348
01349
01350
KiLockDispatcherDatabase(&OldIrql);
01351
01352
01353
01354
01355
01356
01357 OldAffinity = Thread->UserAffinity;
01358 Process = Thread->ApcStatePointer[0]->Process;
01359
01360
01361
01362
01363
01364
01365
if (((Affinity & Process->
Affinity) != (Affinity)) || (!Affinity)) {
01366
KeBugCheck(
INVALID_AFFINITY_SET);
01367 }
01368
01369
01370
01371
01372
01373
01374
01375
01376 Thread->UserAffinity = Affinity;
01377
if (Thread->SystemAffinityActive ==
FALSE) {
01378 Thread->Affinity = Affinity;
01379
switch (Thread->State) {
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
case Ready:
01390
if (Thread->ProcessReadyQueue ==
FALSE) {
01391 RemoveEntryList(&Thread->WaitListEntry);
01392 ThreadPriority = Thread->Priority;
01393
if (IsListEmpty(&
KiDispatcherReadyListHead[ThreadPriority]) !=
FALSE) {
01394
ClearMember(ThreadPriority,
KiReadySummary);
01395 }
01396
01397
KiReadyThread(Thread);
01398 }
01399
01400
break;
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
case Standby:
01412 Processor = Thread->NextProcessor;
01413 Prcb =
KiProcessorBlock[Processor];
01414
if ((Prcb->SetMember & Affinity) == 0) {
01415 Prcb->NextThread =
NULL;
01416 Thread1 =
KiSelectNextThread(Thread);
01417 Thread1->
State =
Standby;
01418 Prcb->NextThread = Thread1;
01419
KiReadyThread(Thread);
01420 }
01421
01422
break;
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
case Running:
01435 Processor = Thread->NextProcessor;
01436 Prcb =
KiProcessorBlock[Processor];
01437
if (((Prcb->SetMember & Affinity) == 0) &&
01438 (Prcb->NextThread ==
NULL)) {
01439 Thread1 =
KiSelectNextThread(Thread);
01440 Thread1->
State =
Standby;
01441 Prcb->NextThread = Thread1;
01442
KiRequestDispatchInterrupt(Processor);
01443 }
01444
01445
break;
01446
01447
01448
01449
01450
01451
01452
default:
01453
break;
01454 }
01455 }
01456
01457
01458
01459
01460
01461
01462
KiUnlockDispatcherDatabase(OldIrql);
01463
return OldAffinity;
01464 }
01465
01466
VOID
01467 KeSetSystemAffinityThread (
01468 IN KAFFINITY Affinity
01469 )
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488 {
01489
01490
PRKTHREAD CurrentThread;
01491
PRKTHREAD NextThread;
01492 KIRQL OldIrql;
01493 PKPRCB Prcb;
01494
01495
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01496
ASSERT((Affinity &
KeActiveProcessors) != 0);
01497
01498
01499
01500
01501
01502 CurrentThread =
KeGetCurrentThread();
01503
KiLockDispatcherDatabase(&OldIrql);
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 CurrentThread->
Affinity = Affinity;
01514 CurrentThread->
SystemAffinityActive =
TRUE;
01515 Prcb =
KeGetCurrentPrcb();
01516
if (((Prcb->SetMember & CurrentThread->
Affinity) == 0) &&
01517 (Prcb->NextThread ==
NULL)) {
01518 NextThread =
KiSelectNextThread(CurrentThread);
01519 NextThread->
State =
Standby;
01520 Prcb->NextThread = NextThread;
01521 }
01522
01523
01524
01525
01526
01527
KiUnlockDispatcherDatabase(OldIrql);
01528
return;
01529 }
01530
01531 LONG
01532 KeSetBasePriorityThread (
01533 IN
PKTHREAD Thread,
01534 IN LONG Increment
01535 )
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 {
01563
01564 KPRIORITY NewBase;
01565 KPRIORITY NewPriority;
01566 KPRIORITY OldBase;
01567 LONG OldIncrement;
01568 KIRQL OldIrql;
01569
PKPROCESS Process;
01570
01571
ASSERT_THREAD(Thread);
01572
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01573
01574
01575
01576
01577
01578
KiLockDispatcherDatabase(&OldIrql);
01579
01580
01581
01582
01583
01584
01585 Process = Thread->ApcStatePointer[0]->Process;
01586 OldBase = Thread->
BasePriority;
01587 OldIncrement = OldBase - Process->
BasePriority;
01588
if (Thread->Saturation != 0) {
01589 OldIncrement = ((HIGH_PRIORITY + 1) / 2) * Thread->Saturation;
01590 }
01591
01592 Thread->Saturation =
FALSE;
01593
if (
abs(
Increment) >= (HIGH_PRIORITY + 1) / 2) {
01594 Thread->Saturation = (
Increment > 0) ? 1 : -1;
01595 }
01596
01597
01598
01599
01600
01601
01602
01603 NewBase = Process->
BasePriority +
Increment;
01604
if (Process->
BasePriority >= LOW_REALTIME_PRIORITY) {
01605
if (NewBase < LOW_REALTIME_PRIORITY) {
01606 NewBase = LOW_REALTIME_PRIORITY;
01607
01608 }
else if (NewBase > HIGH_PRIORITY) {
01609 NewBase = HIGH_PRIORITY;
01610 }
01611
01612
01613
01614
01615
01616 NewPriority = NewBase;
01617
01618 }
else {
01619
if (NewBase >= LOW_REALTIME_PRIORITY) {
01620 NewBase = LOW_REALTIME_PRIORITY - 1;
01621
01622 }
else if (NewBase <= LOW_PRIORITY) {
01623 NewBase = 1;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
if (Thread->Saturation != 0) {
01633 NewPriority = NewBase;
01634
01635 }
else {
01636 NewPriority = Thread->Priority +
01637 (NewBase - OldBase) - Thread->PriorityDecrement;
01638
01639
if (NewPriority >= LOW_REALTIME_PRIORITY) {
01640 NewPriority = LOW_REALTIME_PRIORITY - 1;
01641 }
01642 }
01643 }
01644
01645
01646
01647
01648
01649
01650
01651 Thread->BasePriority = (SCHAR)NewBase;
01652 Thread->DecrementCount = 0;
01653 Thread->PriorityDecrement = 0;
01654
if (NewPriority != Thread->Priority) {
01655 Thread->Quantum = Process->
ThreadQuantum;
01656
KiSetPriorityThread(Thread, NewPriority);
01657 }
01658
01659
01660
01661
01662
01663
01664
KiUnlockDispatcherDatabase(OldIrql);
01665
01666
01667
01668
01669
01670
return OldIncrement;
01671 }
01672
01673 LOGICAL
01674 KeSetDisableBoostThread (
01675 IN
PKTHREAD Thread,
01676 IN LOGICAL Disable
01677 )
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698 {
01699
01700 LOGICAL DisableBoost;
01701 KIRQL OldIrql;
01702
01703
ASSERT_THREAD(Thread);
01704
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01705
01706
01707
01708
01709
01710
KiLockDispatcherDatabase(&OldIrql);
01711
01712
01713
01714
01715
01716
01717 DisableBoost = Thread->DisableBoost;
01718 Thread->DisableBoost = (BOOLEAN)Disable;
01719
01720
01721
01722
01723
01724
01725
KiUnlockDispatcherDatabase(OldIrql);
01726
01727
01728
01729
01730
01731
return DisableBoost;
01732 }
01733
01734 CCHAR
01735 KeSetIdealProcessorThread (
01736 IN
PKTHREAD Thread,
01737 IN CCHAR Processor
01738 )
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 {
01761
01762 CCHAR OldProcessor;
01763 KIRQL OldIrql;
01764
PKPROCESS Process;
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
ASSERT(Processor <=
MAXIMUM_PROCESSORS);
01777
01778
KiLockDispatcherDatabase(&OldIrql);
01779 OldProcessor = Thread->IdealProcessor;
01780
if (Processor <
MAXIMUM_PROCESSORS) {
01781 Thread->IdealProcessor = Processor;
01782
01783 }
else {
01784 Process = Thread->ApcState.Process;
01785 Process->
ThreadSeed += 1;
01786 Thread->IdealProcessor = (UCHAR)(Process->
ThreadSeed %
KeNumberProcessors);
01787 }
01788
01789
01790
01791
01792
01793
01794
KiUnlockDispatcherDatabase(OldIrql);
01795
return OldProcessor;
01796 }
01797
01798 BOOLEAN
01799 KeSetKernelStackSwapEnable (
01800 IN BOOLEAN Enable
01801 )
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820 {
01821
01822 BOOLEAN OldState;
01823
PKTHREAD Thread;
01824
01825
01826
01827
01828
01829
01830
01831 Thread =
KeGetCurrentThread();
01832 OldState = Thread->
EnableStackSwap;
01833 Thread->
EnableStackSwap = Enable;
01834
return OldState;
01835 }
01836
01837 KPRIORITY
01838 KeSetPriorityThread (
01839 IN
PKTHREAD Thread,
01840 IN KPRIORITY Priority
01841 )
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864 {
01865
01866 KIRQL OldIrql;
01867 KPRIORITY OldPriority;
01868
PKPROCESS Process;
01869
01870
ASSERT_THREAD(Thread);
01871
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01872
ASSERT(((Priority != 0) || (Thread->BasePriority == 0)) &&
01873 (Priority <= HIGH_PRIORITY));
01874
01875
ASSERT(KeIsExecutingDpc() ==
FALSE);
01876
01877
01878
01879
01880
01881
KiLockDispatcherDatabase(&OldIrql);
01882
01883
01884
01885
01886
01887
01888
01889
01890 OldPriority = Thread->Priority;
01891 Process = Thread->ApcStatePointer[0]->Process;
01892 Thread->Quantum = Process->
ThreadQuantum;
01893 Thread->DecrementCount = 0;
01894 Thread->PriorityDecrement = 0;
01895
KiSetPriorityThread(Thread, Priority);
01896
01897
01898
01899
01900
01901
01902
KiUnlockDispatcherDatabase(OldIrql);
01903
01904
01905
01906
01907
01908
return OldPriority;
01909 }
01910
01911 ULONG
01912 KeSuspendThread (
01913 IN
PKTHREAD Thread
01914 )
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933 {
01934
01935 ULONG OldCount;
01936 KIRQL OldIrql;
01937
01938
ASSERT_THREAD(Thread);
01939
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
01940
01941
01942
01943
01944
01945
KiLockDispatcherDatabase(&OldIrql);
01946
01947
01948
01949
01950
01951 OldCount = Thread->SuspendCount;
01952
01953
01954
01955
01956
01957
01958
01959
if (OldCount == MAXIMUM_SUSPEND_COUNT) {
01960
01961
01962
01963
01964
01965
KiUnlockDispatcherDatabase(OldIrql);
01966
ExRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
01967 }
01968
01969
01970
01971
01972
01973
01974 Thread->SuspendCount += 1;
01975
if ((OldCount == 0) && (Thread->FreezeCount == 0)) {
01976
if (
KiInsertQueueApc(&Thread->SuspendApc,
RESUME_INCREMENT) ==
FALSE) {
01977 Thread->SuspendSemaphore.Header.SignalState -= 1;
01978 }
01979 }
01980
01981
01982
01983
01984
01985
01986
KiUnlockDispatcherDatabase(OldIrql);
01987
01988
01989
01990
01991
01992
return OldCount;
01993 }
01994
01995
VOID
01996 KeTerminateThread (
01997 IN KPRIORITY Increment
01998 )
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020 {
02021
02022
PRKTHREAD NextThread;
02023 KIRQL OldIrql;
02024
PKPROCESS Process;
02025
PRKQUEUE Queue;
02026
PRKTHREAD Thread;
02027
02028
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
02029
02030
02031
02032
02033
02034 Thread =
KeGetCurrentThread();
02035
KiLockDispatcherDatabase(&OldIrql);
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050 InsertTailList(&
PsReaperListHead, &((
PETHREAD)Thread)->TerminationPortList);
02051
if (
PsReaperActive ==
FALSE) {
02052
PsReaperActive =
TRUE;
02053
KiInsertQueue(&
ExWorkerQueue[
HyperCriticalWorkQueue].WorkerQueue,
02054 &
PsReaperWorkItem.
List,
02055
FALSE);
02056 }
02057
02058
02059
02060
02061
02062
02063
02064 Queue = Thread->Queue;
02065
if (Queue !=
NULL) {
02066 RemoveEntryList(&Thread->QueueListEntry);
02067
KiActivateWaiterQueue(Queue);
02068 }
02069
02070
02071
02072
02073
02074
02075 Thread->Header.SignalState =
TRUE;
02076
if (IsListEmpty(&Thread->Header.WaitListHead) !=
TRUE) {
02077
KiWaitTest((PVOID)Thread,
Increment);
02078 }
02079
02080
02081
02082
02083
02084 RemoveEntryList(&Thread->
ThreadListEntry);
02085
02086
02087
02088
02089
02090
02091
02092 Thread->State =
Terminated;
02093 Process = Thread->ApcState.Process;
02094 Process->
StackCount -= 1;
02095
if (Process->
StackCount == 0) {
02096
if (Process->
ThreadListHead.Flink != &Process->
ThreadListHead) {
02097 Process->
State =
ProcessInTransition;
02098 InsertTailList(&
KiProcessOutSwapListHead, &Process->
SwapListEntry);
02099
KiSwapEvent.
Header.
SignalState = 1;
02100
if (IsListEmpty(&
KiSwapEvent.
Header.
WaitListHead) ==
FALSE) {
02101
KiWaitTest(&
KiSwapEvent,
BALANCE_INCREMENT);
02102 }
02103 }
02104 }
02105
02106
02107
02108
02109
02110
KiRundownThread(Thread);
02111
02112
02113
02114
02115
02116
KiSwapThread();
02117
return;
02118 }
02119
02120 BOOLEAN
02121 KeTestAlertThread (
02122 IN KPROCESSOR_MODE AlertMode
02123 )
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145 {
02146
02147 BOOLEAN Alerted;
02148 KIRQL OldIrql;
02149
PKTHREAD Thread;
02150
02151
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
02152
02153
02154
02155
02156
02157
02158 Thread =
KeGetCurrentThread();
02159
KiLockDispatcherDatabase(&OldIrql);
02160 KiAcquireSpinLock(&Thread->
ApcQueueLock);
02161
02162
02163
02164
02165
02166
02167
02168
02169 Alerted = Thread->
Alerted[AlertMode];
02170
if (Alerted ==
TRUE) {
02171 Thread->
Alerted[AlertMode] =
FALSE;
02172
02173 }
else if ((AlertMode ==
UserMode) &&
02174 (IsListEmpty(&Thread->
ApcState.
ApcListHead[
UserMode]) !=
TRUE)) {
02175 Thread->
ApcState.
UserApcPending =
TRUE;
02176 }
02177
02178
02179
02180
02181
02182
02183
02184 KiReleaseSpinLock(&Thread->
ApcQueueLock);
02185
KiUnlockDispatcherDatabase(OldIrql);
02186
return Alerted;
02187 }
02188
02189
VOID
02190 KeThawAllThreads (
02191 VOID
02192 )
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211 {
02212
02213 PLIST_ENTRY ListHead;
02214 PLIST_ENTRY NextEntry;
02215
PKPROCESS Process;
02216
PKTHREAD Thread;
02217 ULONG OldCount;
02218 KIRQL OldIrql;
02219
02220
ASSERT(KeGetCurrentIrql() <=
DISPATCH_LEVEL);
02221
02222
02223
02224
02225
02226
02227
02228 Process =
KeGetCurrentThread()->ApcState.Process;
02229
KiLockDispatcherDatabase(&OldIrql);
02230 ListHead = &Process->
ThreadListHead;
02231 NextEntry = ListHead->Flink;
02232
do {
02233
02234
02235
02236
02237
02238
02239 Thread = CONTAINING_RECORD(NextEntry,
KTHREAD, ThreadListEntry);
02240 OldCount = Thread->
FreezeCount;
02241
if (OldCount != 0) {
02242 Thread->
FreezeCount -= 1;
02243
02244
02245
02246
02247
02248
02249
if ((Thread->
SuspendCount == 0) && (Thread->
FreezeCount == 0)) {
02250 Thread->
SuspendSemaphore.
Header.
SignalState += 1;
02251
KiWaitTest(&Thread->
SuspendSemaphore,
RESUME_INCREMENT);
02252 }
02253 }
02254
02255 NextEntry = NextEntry->Flink;
02256 }
while (NextEntry != ListHead);
02257
02258
02259
02260
02261
02262
02263
KiUnlockDispatcherDatabase(OldIrql);
02264
KeLeaveCriticalRegion();
02265
return;
02266 }
02267