00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "exp.h"
00025
00026
00027
00028
00029
00030 typedef enum _BALANCE_OBJECT {
00031
TimerExpiration,
00032
ThreadSetManagerEvent,
00033
MaximumBalanceObject
00034 }
BALANCE_OBJECT;
00035
00036
00037
00038
00039
00040
C_ASSERT(MaximumBalanceObject < THREAD_WAIT_OBJECTS);
00041
00042
00043
00044
00045
00046
00047
00048 #define DELAYED_WORK_QUEUE_PRIORITY (12 - NORMAL_BASE_PRIORITY)
00049 #define CRITICAL_WORK_QUEUE_PRIORITY (13 - NORMAL_BASE_PRIORITY)
00050 #define HYPER_CRITICAL_WORK_QUEUE_PRIORITY (15 - NORMAL_BASE_PRIORITY)
00051
00052
00053
00054
00055
00056 #define MAX_ADDITIONAL_THREADS 16
00057 #define MAX_ADDITIONAL_DYNAMIC_THREADS 16
00058
00059 #define SMALL_NUMBER_OF_THREADS 2
00060 #define MEDIUM_NUMBER_OF_THREADS 3
00061 #define LARGE_NUMBER_OF_THREADS 5
00062
00063
00064
00065
00066
00067 #define DYNAMIC_THREAD_TIMEOUT ((LONGLONG)10 * 60 * 1000 * 1000 * 10)
00068
00069
00070
00071
00072
00073 #define THREAD_SET_INTERVAL (1 * 1000 * 1000 * 10)
00074
00075
00076
00077
00078
00079
00080 #define DYNAMIC_WORKER_THREAD 0x80000000
00081
00082
00083
00084
00085
00086 EX_WORK_QUEUE ExWorkerQueue[
MaximumWorkQueue];
00087
00088
00089
00090
00091
00092 ULONG
ExpAdditionalCriticalWorkerThreads;
00093 ULONG
ExpAdditionalDelayedWorkerThreads;
00094
00095 ULONG
ExCriticalWorkerThreads;
00096 ULONG
ExDelayedWorkerThreads;
00097
00098
00099
00100
00101
00102 KEVENT ExThreadSetManagerEvent;
00103
00104
VOID
00105
ExpCheckDynamicThreadCount( VOID );
00106
00107
NTSTATUS
00108
ExpCreateWorkerThread(
00109
WORK_QUEUE_TYPE QueueType,
00110 BOOLEAN Dynamic
00111 );
00112
00113
VOID
00114
ExpDetectWorkerThreadDeadlock( VOID );
00115
00116
VOID
00117
ExpWorkerThreadBalanceManager(
00118 IN PVOID StartContext
00119 );
00120
00121
00122
00123
00124
00125
VOID
00126
ExpWorkerThread(
00127 IN PVOID StartContext
00128 );
00129
00130
#if DBG
00131
00132 EXCEPTION_DISPOSITION
00133 ExpWorkerThreadFilter(
00134 IN PWORKER_THREAD_ROUTINE WorkerRoutine,
00135 IN PVOID Parameter,
00136 IN PEXCEPTION_POINTERS ExceptionInfo
00137 );
00138
00139
#endif
00140
00141 PVOID
00142
ExpCheckForWorker(
00143 IN PVOID p,
00144 IN ULONG Size
00145 );
00146
00147
00148
#ifdef ALLOC_PRAGMA
00149
#pragma alloc_text(INIT, ExpWorkerInitialization)
00150
#pragma alloc_text(PAGE, ExpCheckDynamicThreadCount)
00151
#pragma alloc_text(PAGE, ExpCreateWorkerThread)
00152
#pragma alloc_text(PAGE, ExpDetectWorkerThreadDeadlock)
00153
#pragma alloc_text(PAGE, ExpWorkerThreadBalanceManager)
00154
#endif
00155
00156
00157 BOOLEAN
00158 __inline
00159 ExpNewThreadNecessary(
00160 IN WORK_QUEUE_TYPE QueueType
00161 )
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 {
00181
PEX_WORK_QUEUE Queue;
00182
00183 Queue = &
ExWorkerQueue[QueueType];
00184
00185
if (Queue->
MakeThreadsAsNecessary !=
FALSE &&
00186 IsListEmpty( &Queue->
WorkerQueue.
EntryListHead ) ==
FALSE &&
00187 Queue->
WorkerQueue.
CurrentCount < Queue->
WorkerQueue.
MaximumCount &&
00188 Queue->
DynamicThreadCount <
MAX_ADDITIONAL_DYNAMIC_THREADS) {
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
return TRUE;
00208
00209 }
else {
00210
00211
00212
00213
00214
00215
return FALSE;
00216 }
00217 }
00218
00219 BOOLEAN
00220 ExpWorkerInitialization(
00221 VOID
00222 )
00223
00224 {
00225
00226 ULONG
Index;
00227 OBJECT_ATTRIBUTES
ObjectAttributes;
00228 ULONG NumberOfDelayedThreads;
00229 ULONG NumberOfCriticalThreads;
00230
NTSTATUS Status;
00231 HANDLE Thread;
00232 BOOLEAN NtAs;
00233
WORK_QUEUE_TYPE WorkQueueType;
00234
00235
00236
00237
00238
00239 NtAs =
MmIsThisAnNtAsSystem();
00240
switch (
MmQuerySystemSize()) {
00241
case MmSmallSystem:
00242 NumberOfDelayedThreads =
MEDIUM_NUMBER_OF_THREADS;
00243
if (
MmNumberOfPhysicalPages > ((12*1024*1024)/
PAGE_SIZE) ) {
00244 NumberOfCriticalThreads =
MEDIUM_NUMBER_OF_THREADS;
00245 }
else {
00246 NumberOfCriticalThreads =
SMALL_NUMBER_OF_THREADS;
00247 }
00248
break;
00249
00250
case MmMediumSystem:
00251 NumberOfDelayedThreads =
MEDIUM_NUMBER_OF_THREADS;
00252 NumberOfCriticalThreads =
MEDIUM_NUMBER_OF_THREADS;
00253
if ( NtAs ) {
00254 NumberOfCriticalThreads +=
MEDIUM_NUMBER_OF_THREADS;
00255 }
00256
break;
00257
00258
case MmLargeSystem:
00259 NumberOfDelayedThreads =
MEDIUM_NUMBER_OF_THREADS;
00260 NumberOfCriticalThreads =
LARGE_NUMBER_OF_THREADS;
00261
if ( NtAs ) {
00262 NumberOfCriticalThreads +=
LARGE_NUMBER_OF_THREADS;
00263 }
00264
break;
00265
00266
default:
00267 NumberOfDelayedThreads =
SMALL_NUMBER_OF_THREADS;
00268 NumberOfCriticalThreads =
SMALL_NUMBER_OF_THREADS;
00269 }
00270
00271
00272
00273
00274
00275
00276
if (
ExpAdditionalCriticalWorkerThreads >
MAX_ADDITIONAL_THREADS ) {
00277
ExpAdditionalCriticalWorkerThreads =
MAX_ADDITIONAL_THREADS;
00278 }
00279
00280
if (
ExpAdditionalDelayedWorkerThreads >
MAX_ADDITIONAL_THREADS ) {
00281
ExpAdditionalDelayedWorkerThreads =
MAX_ADDITIONAL_THREADS;
00282 }
00283
00284
00285
00286
00287
00288
for (WorkQueueType = 0; WorkQueueType <
MaximumWorkQueue; WorkQueueType++) {
00289
00290 RtlZeroMemory(&
ExWorkerQueue[WorkQueueType],
00291
sizeof(
EX_WORK_QUEUE));
00292
00293
KeInitializeQueue(&
ExWorkerQueue[WorkQueueType].WorkerQueue, 0);
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
ExWorkerQueue[
CriticalWorkQueue].
MakeThreadsAsNecessary =
TRUE;
00306
00307
00308
00309
00310
00311
KeInitializeEvent(&
ExThreadSetManagerEvent,
00312 SynchronizationEvent,
00313
FALSE);
00314
00315
00316
00317
00318
00319
00320 InitializeObjectAttributes(&
ObjectAttributes,
NULL, 0,
NULL,
NULL);
00321
00322
00323
00324
00325
00326
for (
Index = 0;
Index < (NumberOfCriticalThreads +
ExpAdditionalCriticalWorkerThreads);
Index += 1) {
00327
00328
00329
00330
00331
00332
Status =
ExpCreateWorkerThread(
CriticalWorkQueue,
FALSE );
00333
if (!
NT_SUCCESS(
Status)) {
00334
break;
00335 }
00336
ExCriticalWorkerThreads++;
00337 }
00338
00339
00340
for (
Index = 0;
Index < (NumberOfDelayedThreads +
ExpAdditionalDelayedWorkerThreads);
Index += 1) {
00341
00342
00343
00344
00345
00346
Status =
ExpCreateWorkerThread(
DelayedWorkQueue,
FALSE );
00347
if (!
NT_SUCCESS(
Status)) {
00348
break;
00349 }
00350
00351
ExDelayedWorkerThreads++;
00352 }
00353
00354
Status =
ExpCreateWorkerThread(
HyperCriticalWorkQueue,
FALSE );
00355
00356
00357
00358
00359
00360
Status =
PsCreateSystemThread(&Thread,
00361 THREAD_ALL_ACCESS,
00362 &
ObjectAttributes,
00363 0
L,
00364
NULL,
00365
ExpWorkerThreadBalanceManager,
00366
NULL);
00367
if (
NT_SUCCESS(
Status)) {
00368 ZwClose( Thread );
00369 }
00370
00371
return (BOOLEAN)
NT_SUCCESS(
Status);
00372 }
00373
00374
VOID
00375 ExQueueWorkItem(
00376 IN
PWORK_QUEUE_ITEM WorkItem,
00377 IN WORK_QUEUE_TYPE QueueType
00378 )
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 {
00404
00405
ASSERT(QueueType <
MaximumWorkQueue);
00406
ASSERT(WorkItem->List.Flink ==
NULL);
00407
00408
00409
00410
00411
00412
KeInsertQueue(&
ExWorkerQueue[QueueType].WorkerQueue, &WorkItem->List);
00413
00414
00415
00416
00417
00418
00419
if (
ExpNewThreadNecessary(QueueType) !=
FALSE) {
00420
00421
KeSetEvent( &
ExThreadSetManagerEvent,
00422 0,
00423
FALSE );
00424 }
00425
00426
return;
00427 }
00428
00429
00430
VOID
00431 ExpWorkerThreadBalanceManager(
00432 IN PVOID StartContext
00433 )
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 {
00457
KTIMER PeriodTimer;
00458 LARGE_INTEGER DueTime;
00459 PVOID WaitObjects[
MaximumBalanceObject];
00460
NTSTATUS Status;
00461
00462
PAGED_CODE();
00463
00464
00465
00466
00467
00468
00469
KeSetBasePriorityThread(
KeGetCurrentThread(),
00470
CRITICAL_WORK_QUEUE_PRIORITY+1);
00471
00472
00473
00474
00475
00476
KeInitializeTimer(&PeriodTimer);
00477 DueTime.QuadPart = -
THREAD_SET_INTERVAL;
00478
00479
00480
00481
00482
00483 WaitObjects[
TimerExpiration] = (PVOID)&PeriodTimer;
00484 WaitObjects[
ThreadSetManagerEvent] = (PVOID)&
ExThreadSetManagerEvent;
00485
00486
00487
00488
00489
00490
while(
TRUE ) {
00491
00492
00493
00494
00495
00496
KeSetTimer(&PeriodTimer, DueTime,
NULL);
00497
00498
00499
00500
00501
00502
00503
Status =
KeWaitForMultipleObjects(
MaximumBalanceObject,
00504 WaitObjects,
00505 WaitAny,
00506
Executive,
00507
KernelMode,
00508
FALSE,
00509
NULL,
00510
NULL);
00511
00512
switch (
Status) {
00513
00514
case TimerExpiration:
00515
00516
00517
00518
00519
00520
00521
ExpDetectWorkerThreadDeadlock();
00522
break;
00523
00524
case ThreadSetManagerEvent:
00525
00526
00527
00528
00529
00530
00531
ExpCheckDynamicThreadCount();
00532
break;
00533 }
00534 }
00535 }
00536
00537
VOID
00538 ExpWorkerThread(
00539 IN PVOID StartContext
00540 )
00541
00542 {
00543
00544 PLIST_ENTRY Entry;
00545
WORK_QUEUE_TYPE QueueType;
00546
PWORK_QUEUE_ITEM WorkItem;
00547
KPROCESSOR_MODE WaitMode;
00548 LARGE_INTEGER TimeoutValue;
00549 PLARGE_INTEGER Timeout;
00550
PETHREAD Thread;
00551 BOOLEAN DynamicThread;
00552
PEX_WORK_QUEUE WorkerQueue;
00553 PVOID WorkerRoutine;
00554 PVOID Parameter;
00555
00556 WaitMode =
UserMode;
00557
00558
00559
00560
00561
00562
if (((ULONG_PTR)StartContext &
DYNAMIC_WORKER_THREAD) == 0) {
00563
00564
00565
00566
00567
00568
00569
00570 Timeout =
NULL;
00571
00572 }
else {
00573
00574
00575
00576
00577
00578
00579 TimeoutValue.QuadPart = -
DYNAMIC_THREAD_TIMEOUT;
00580 Timeout = &TimeoutValue;
00581 }
00582
00583 Thread =
PsGetCurrentThread();
00584
00585
00586
00587
00588
00589
00590
00591 QueueType = (
WORK_QUEUE_TYPE)
00592 ((ULONG_PTR)StartContext & ~
DYNAMIC_WORKER_THREAD);
00593
00594 WorkerQueue = &
ExWorkerQueue[QueueType];
00595
00596
switch ( QueueType ) {
00597
00598
case HyperCriticalWorkQueue:
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611 WaitMode =
KernelMode;
00612
break;
00613
00614
case CriticalWorkQueue:
00615
if (
MmIsThisAnNtAsSystem() ) {
00616 WaitMode =
KernelMode;
00617 }
00618
00619
break;
00620 }
00621
00622
#if defined(REMOTE_BOOT)
00623
00624
00625
00626
00627
00628
if (
IoRemoteBootClient) {
00629
KeSetKernelStackSwapEnable(
FALSE);
00630 }
00631
#endif // defined(REMOTE_BOOT)
00632
00633
00634
00635
00636
00637
00638
do {
00639
00640
while (
TRUE) {
00641
00642
00643
00644
00645
00646
00647
00648
00649 Entry =
KeRemoveQueue(&WorkerQueue->
WorkerQueue,
00650 WaitMode,
00651 Timeout);
00652
if ((ULONG_PTR)Entry != STATUS_TIMEOUT) {
00653
00654
00655
00656
00657
00658
00659
break;
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
if (IsListEmpty( &Thread->
IrpList ) ==
FALSE) {
00673
00674
00675
00676
00677
00678
continue;
00679 }
00680
00681
00682
00683
00684
00685
#if DBG
00686
DbgPrint(
"EXWORKER: Dynamic type %d thread no longer needed,"
00687
" terminating.\n",
00688 QueueType );
00689
#endif
00690
00691 InterlockedDecrement(
00692 &WorkerQueue->
DynamicThreadCount );
00693
00694
#if defined(REMOTE_BOOT)
00695
00696
00697
00698
00699
00700
if (
IoRemoteBootClient) {
00701
KeSetKernelStackSwapEnable(
TRUE);
00702 }
00703
#endif // defined(REMOTE_BOOT)
00704
00705
return;
00706 }
00707
00708
00709
00710
00711
00712 InterlockedIncrement( &WorkerQueue->
WorkItemsProcessed );
00713
00714 WorkItem = CONTAINING_RECORD(Entry,
WORK_QUEUE_ITEM,
List);
00715 WorkerRoutine = WorkItem->
WorkerRoutine;
00716 Parameter = WorkItem->
Parameter;
00717
00718
00719
00720
00721
00722
#if DBG
00723
00724
try {
00725
00726 ((
PWORKER_THREAD_ROUTINE)WorkerRoutine)(Parameter);
00727
00728
if (KeGetCurrentIrql() != 0) {
00729
DbgPrint(
"EXWORKER: worker exit at IRQL %d, worker routine %x, "
00730
"parameter %x, item %x\n",
00731 KeGetCurrentIrql(), WorkerRoutine, Parameter, WorkItem);
00732
00733 DbgBreakPoint();
00734 }
00735
00736
00737
00738
00739
if (Thread->
Tcb.
KernelApcDisable != 0) {
00740
DbgPrint(
"EXWORKER: worker exit with APCs disabled, worker routine %x, "
00741
"parameter %x, item %x\n",
00742 WorkerRoutine, Parameter, WorkItem);
00743
00744 DbgBreakPoint();
00745 Thread->
Tcb.
KernelApcDisable = 0;
00746 }
00747
00748
if (Thread->
ActiveImpersonationInfo) {
00749
KeBugCheckEx(
00750 IMPERSONATING_WORKER_THREAD,
00751 (ULONG_PTR)WorkerRoutine,
00752 (ULONG_PTR)Parameter,
00753 (ULONG_PTR)WorkItem,
00754 0);
00755 }
00756
00757 } except( ExpWorkerThreadFilter(WorkerRoutine,
00758 Parameter,
00759 GetExceptionInformation() )) {
00760 }
00761
00762
#else
00763
00764 ((
PWORKER_THREAD_ROUTINE)WorkerRoutine)(Parameter);
00765
00766
00767
00768
00769
00770
00771
00772
00773
if (Thread->
Tcb.
KernelApcDisable != 0) {
00774
DbgPrint(
"EXWORKER: worker exit with APCs disabled, worker routine %x, "
00775
"parameter %x, item %x\n",
00776 WorkerRoutine, Parameter, WorkItem);
00777
00778 Thread->
Tcb.
KernelApcDisable = 0;
00779 }
00780
00781
if (KeGetCurrentIrql() != 0) {
00782
KeBugCheckEx(
00783 WORKER_THREAD_RETURNED_AT_BAD_IRQL,
00784 (ULONG_PTR)WorkerRoutine,
00785 (ULONG_PTR)KeGetCurrentIrql(),
00786 (ULONG_PTR)Parameter,
00787 (ULONG_PTR)WorkItem
00788 );
00789 }
00790
00791
if (Thread->
ActiveImpersonationInfo) {
00792
KeBugCheckEx(
00793 IMPERSONATING_WORKER_THREAD,
00794 (ULONG_PTR)WorkerRoutine,
00795 (ULONG_PTR)Parameter,
00796 (ULONG_PTR)WorkItem,
00797 0
00798 );
00799 }
00800
#endif
00801
00802 }
while(
TRUE);
00803 }
00804
00805
VOID
00806 ExpCheckDynamicThreadCount( VOID )
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 {
00829
WORK_QUEUE_TYPE QueueType;
00830
00831
PAGED_CODE();
00832
00833
00834
00835
00836
00837
for (QueueType = 0; QueueType <
MaximumWorkQueue; QueueType++) {
00838
00839
if (
ExpNewThreadNecessary(QueueType)) {
00840
00841
00842
00843
00844
00845
00846
00847
ExpCreateWorkerThread(QueueType,
TRUE);
00848 }
00849 }
00850 }
00851
00852
VOID
00853 ExpDetectWorkerThreadDeadlock( VOID )
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 {
00873 LONG QueueDepth;
00874 ULONG
Index;
00875 LONG ThreadCount;
00876 LONG NewThreadCount;
00877
NTSTATUS Status;
00878 HANDLE Thread;
00879 OBJECT_ATTRIBUTES
ObjectAttributes;
00880
PEX_WORK_QUEUE Queue;
00881
00882
PAGED_CODE();
00883
00884
00885
00886
00887
00888
for (
Index = 0;
Index <
MaximumWorkQueue;
Index += 1) {
00889
00890 Queue = &
ExWorkerQueue[
Index];
00891
00892
ASSERT( Queue->
DynamicThreadCount <=
00893
MAX_ADDITIONAL_DYNAMIC_THREADS );
00894
00895
if (Queue->
QueueDepthLastPass > 0 &&
00896
00897 Queue->
WorkItemsProcessed ==
00898 Queue->
WorkItemsProcessedLastPass &&
00899
00900 Queue->
DynamicThreadCount <
00901
MAX_ADDITIONAL_DYNAMIC_THREADS) {
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
#if DBG
00914
DbgPrint(
"EXWORKER: Work item deadlock detected, creating "
00915
"type %d worker thread\n",
00916
Index );
00917
#endif
00918
00919
00920
00921
00922
00923
00924
00925
00926
ExpCreateWorkerThread(
Index,
TRUE);
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936 Queue->
WorkItemsProcessedLastPass = Queue->
WorkItemsProcessed;
00937 Queue->
QueueDepthLastPass =
KeReadStateQueue( &Queue->
WorkerQueue );
00938 }
00939 }
00940
00941
#if DBG
00942
00943 EXCEPTION_DISPOSITION
00944 ExpWorkerThreadFilter(
00945 IN PWORKER_THREAD_ROUTINE WorkerRoutine,
00946 IN PVOID Parameter,
00947 IN PEXCEPTION_POINTERS ExceptionInfo
00948 )
00949 {
00950 KdPrint((
"EXWORKER: exception in worker routine %p(%p)\n", WorkerRoutine, Parameter));
00951 KdPrint((
" exception record at %p\n", ExceptionInfo->ExceptionRecord));
00952 KdPrint((
" context record at %p\n",ExceptionInfo->ContextRecord));
00953
00954
try {
00955 DbgBreakPoint();
00956
00957 } except (EXCEPTION_EXECUTE_HANDLER) {
00958
00959
00960
00961
00962
return(
EXCEPTION_CONTINUE_SEARCH);
00963 }
00964
00965
return(
EXCEPTION_EXECUTE_HANDLER);
00966 }
00967
00968
#endif
00969
00970
NTSTATUS
00971 ExpCreateWorkerThread(
00972 WORK_QUEUE_TYPE QueueType,
00973 BOOLEAN Dynamic
00974 )
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 {
01005 OBJECT_ATTRIBUTES
ObjectAttributes;
01006
NTSTATUS Status;
01007 HANDLE
ThreadHandle;
01008 ULONG Context;
01009 ULONG BasePriority;
01010
PETHREAD Thread;
01011
01012 InitializeObjectAttributes(&
ObjectAttributes,
NULL, 0,
NULL,
NULL);
01013
01014 Context = QueueType;
01015
if (Dynamic !=
FALSE) {
01016 Context |=
DYNAMIC_WORKER_THREAD;
01017 }
01018
01019
Status =
PsCreateSystemThread(&
ThreadHandle,
01020 THREAD_ALL_ACCESS,
01021 &
ObjectAttributes,
01022 0
L,
01023
NULL,
01024
ExpWorkerThread,
01025 (PVOID)Context);
01026
if (!
NT_SUCCESS(
Status)) {
01027
#if DBG
01028
DbgPrint(
"EXWORKER: Worker thread creation failed, status %08x\n",
01029
Status);
01030
#endif
01031
return Status;
01032 }
01033
01034
if (Dynamic !=
FALSE) {
01035
01036
#if DBG
01037
DbgPrint(
"EXWORKER: Created dynamic thread type %d, %d total\n",
01038 QueueType,
01039
ExWorkerQueue[QueueType].DynamicThreadCount);
01040
#endif
01041
01042 InterlockedIncrement( &
ExWorkerQueue[QueueType].DynamicThreadCount );
01043 }
01044
01045
01046
01047
01048
01049
switch (QueueType) {
01050
01051
case HyperCriticalWorkQueue:
01052
01053 BasePriority =
HYPER_CRITICAL_WORK_QUEUE_PRIORITY;
01054
break;
01055
01056
case CriticalWorkQueue:
01057
01058 BasePriority =
CRITICAL_WORK_QUEUE_PRIORITY;
01059
break;
01060
01061
case DelayedWorkQueue:
01062
01063 BasePriority =
DELAYED_WORK_QUEUE_PRIORITY;
01064
break;
01065 }
01066
01067
01068
01069
01070
01071
Status =
ObReferenceObjectByHandle(
ThreadHandle,
01072 THREAD_SET_INFORMATION,
01073
PsThreadType,
01074
KernelMode,
01075 (PVOID *)&Thread,
01076
NULL );
01077
if (
NT_SUCCESS(
Status)) {
01078
01079
KeSetBasePriorityThread( &Thread->Tcb, BasePriority );
01080
ObDereferenceObject( Thread );
01081
01082 }
else {
01083
01084
01085
01086
01087
01088
01089
01090 }
01091
01092 ZwClose(
ThreadHandle );
01093
return Status;
01094 }
01095
01096 PVOID
01097 ExpCheckForWorker(
01098 IN PVOID p,
01099 IN ULONG Size
01100 )
01101
01102 {
01103 KIRQL OldIrql;
01104 PLIST_ENTRY Entry;
01105 PCHAR BeginBlock;
01106 PCHAR EndBlock;
01107
WORK_QUEUE_TYPE wqt;
01108
01109 BeginBlock = (PCHAR)p;
01110 EndBlock = (PCHAR)p +
Size;
01111
01112
KiLockDispatcherDatabase (&OldIrql);
01113
for (wqt =
CriticalWorkQueue; wqt <
MaximumWorkQueue; wqt++) {
01114
for (Entry = (PLIST_ENTRY)
ExWorkerQueue[wqt].
WorkerQueue.
EntryListHead.Flink;
01115 Entry && (Entry != (PLIST_ENTRY) &
ExWorkerQueue[wqt].
WorkerQueue.
EntryListHead);
01116 Entry = Entry->Flink) {
01117
if (((PCHAR) Entry >= BeginBlock) && ((PCHAR) Entry < EndBlock)) {
01118
KeBugCheckEx(WORKER_INVALID,
01119 0x0,
01120 (ULONG_PTR)Entry,
01121 (ULONG_PTR)BeginBlock,
01122 (ULONG_PTR)EndBlock);
01123
01124 }
01125 }
01126 }
01127
KiUnlockDispatcherDatabase (OldIrql);
01128
01129
return NULL;
01130 }