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
#include "ki.h"
00028
00029
00030
00031
00032
00033 #define MAXIMUM_DPC_LIST_SIZE 16
00034
00035 typedef struct _DPC_ENTRY {
00036 PRKDPC Dpc;
00037 PKDEFERRED_ROUTINE Routine;
00038 PVOID
Context;
00039 }
DPC_ENTRY, *
PDPC_ENTRY;
00040
00041
00042
PRKTHREAD
00043 KiQuantumEnd (
00044 VOID
00045 )
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 {
00069
00070 KPRIORITY NewPriority;
00071 KIRQL OldIrql;
00072 PKPRCB Prcb;
00073 KPRIORITY Priority;
00074
PKPROCESS Process;
00075
PRKTHREAD Thread;
00076
PRKTHREAD NextThread;
00077
00078
00079
00080
00081
00082 Prcb =
KeGetCurrentPrcb();
00083 Thread =
KeGetCurrentThread();
00084
KiLockDispatcherDatabase(&OldIrql);
00085
00086
00087
00088
00089
00090
00091
if (Thread->
Quantum <= 0) {
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 Process = Thread->
ApcState.
Process;
00102
if ((Process->
DisableQuantum !=
FALSE) &&
00103 (Thread->
Priority >= LOW_REALTIME_PRIORITY)) {
00104 Thread->
Quantum = MAXCHAR;
00105
00106 }
else {
00107 Thread->
Quantum = Process->
ThreadQuantum;
00108
00109
00110
00111
00112
00113
00114
00115 Priority = Thread->
Priority;
00116
if (Priority < LOW_REALTIME_PRIORITY) {
00117 NewPriority = Priority - Thread->
PriorityDecrement - 1;
00118
if (NewPriority < Thread->
BasePriority) {
00119 NewPriority = Thread->
BasePriority;
00120 }
00121
00122 Thread->
PriorityDecrement = 0;
00123
00124 }
else {
00125 NewPriority = Priority;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
if (Priority != NewPriority) {
00136
KiSetPriorityThread(Thread, NewPriority);
00137
00138 }
else {
00139
if (Prcb->NextThread ==
NULL) {
00140 NextThread =
KiFindReadyThread(Thread->
NextProcessor, Priority);
00141
00142
if (NextThread !=
NULL) {
00143 NextThread->
State =
Standby;
00144 Prcb->NextThread = NextThread;
00145 }
00146
00147 }
else {
00148 Thread->
Preempted =
FALSE;
00149 }
00150 }
00151 }
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 NextThread = Prcb->NextThread;
00161
if (NextThread ==
NULL) {
00162
KiUnlockDispatcherDatabase(OldIrql);
00163 }
00164
00165
return NextThread;
00166 }
00167
00168
#if DBG
00169
00170
00171
VOID
00172 KiCheckTimerTable (
00173 IN ULARGE_INTEGER CurrentTime
00174 )
00175
00176 {
00177
00178 ULONG
Index;
00179 PLIST_ENTRY ListHead;
00180 PLIST_ENTRY NextEntry;
00181 KIRQL OldIrql;
00182
PKTIMER Timer;
00183
00184
00185
00186
00187
00188
00189
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
00190
Index = 0;
00191
do {
00192 ListHead = &
KiTimerTableListHead[
Index];
00193 NextEntry = ListHead->Flink;
00194
while (NextEntry != ListHead) {
00195 Timer = CONTAINING_RECORD(NextEntry,
KTIMER, TimerListEntry);
00196 NextEntry = NextEntry->Flink;
00197
if (Timer->
DueTime.QuadPart <= CurrentTime.QuadPart) {
00198 DbgBreakPoint();
00199 }
00200 }
00201
00202
Index += 1;
00203 }
while(
Index <
TIMER_TABLE_SIZE);
00204
00205
00206
00207
00208
00209
KeLowerIrql(OldIrql);
00210
return;
00211 }
00212
00213
#endif
00214
00215
00216
VOID
00217 KiTimerExpiration (
00218 IN
PKDPC TimerDpc,
00219 IN PVOID DeferredContext,
00220 IN PVOID SystemArgument1,
00221 IN PVOID SystemArgument2
00222 )
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 {
00249 ULARGE_INTEGER CurrentTime;
00250 LIST_ENTRY ExpiredListHead;
00251 LONG HandLimit;
00252 LONG
Index;
00253 PLIST_ENTRY ListHead;
00254 PLIST_ENTRY NextEntry;
00255 KIRQL OldIrql;
00256
PKTIMER Timer;
00257
00258
00259
00260
00261
00262
00263
KiLockDispatcherDatabase(&OldIrql);
00264 KiQueryInterruptTime((PLARGE_INTEGER)&CurrentTime);
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 HandLimit = (LONG)KiQueryLowTickCount();
00277
if (((ULONG)(HandLimit - PtrToLong(SystemArgument1))) >=
TIMER_TABLE_SIZE) {
00278
Index = - 1;
00279 HandLimit =
TIMER_TABLE_SIZE - 1;
00280
00281 }
else {
00282
Index = (PtrToLong(SystemArgument1) - 1) & (
TIMER_TABLE_SIZE - 1);
00283 HandLimit &= (
TIMER_TABLE_SIZE - 1);
00284 }
00285
00286 InitializeListHead(&ExpiredListHead);
00287
do {
00288
Index = (
Index + 1) & (
TIMER_TABLE_SIZE - 1);
00289 ListHead = &
KiTimerTableListHead[
Index];
00290 NextEntry = ListHead->Flink;
00291
while (NextEntry != ListHead) {
00292 Timer = CONTAINING_RECORD(NextEntry,
KTIMER, TimerListEntry);
00293
if (Timer->
DueTime.QuadPart <= CurrentTime.QuadPart) {
00294
00295
00296
00297
00298
00299
00300
00301 RemoveEntryList(&Timer->
TimerListEntry);
00302 InsertTailList(&ExpiredListHead, &Timer->
TimerListEntry);
00303 NextEntry = ListHead->Flink;
00304
00305 }
else {
00306
break;
00307 }
00308 }
00309
00310 }
while(
Index != HandLimit);
00311
00312
#if DBG
00313
00314
if ((PtrToUlong(SystemArgument2) == 0) && (
KeNumberProcessors == 1)) {
00315 KiCheckTimerTable(CurrentTime);
00316 }
00317
00318
#endif
00319
00320
00321
00322
00323
00324
00325
00326
00327
KiTimerListExpire(&ExpiredListHead, OldIrql);
00328
return;
00329 }
00330
00331
VOID
00332
FASTCALL
00333 KiTimerListExpire (
00334 IN PLIST_ENTRY ExpiredListHead,
00335 IN KIRQL OldIrql
00336 )
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 {
00361
00362 LONG
Count;
00363
PKDPC Dpc;
00364
DPC_ENTRY DpcList[
MAXIMUM_DPC_LIST_SIZE];
00365 LONG
Index;
00366 LARGE_INTEGER Interval;
00367 KIRQL OldIrql1;
00368 LARGE_INTEGER SystemTime;
00369
PKTIMER Timer;
00370
00371
00372
00373
00374
00375 KiQuerySystemTime(&SystemTime);
00376
00377
00378
00379
00380
00381
00382
00383 RestartScan:
00384
Count = 0;
00385
while (ExpiredListHead->Flink != ExpiredListHead) {
00386 Timer = CONTAINING_RECORD(ExpiredListHead->Flink,
KTIMER, TimerListEntry);
00387
KiRemoveTreeTimer(Timer);
00388 Timer->
Header.
SignalState = 1;
00389
if (IsListEmpty(&Timer->
Header.
WaitListHead) ==
FALSE) {
00390
KiWaitTest(Timer,
TIMER_EXPIRE_INCREMENT);
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
if (Timer->
Period != 0) {
00403 Interval.QuadPart = Int32x32To64(Timer->
Period, - 10 * 1000);
00404
while (!
KiInsertTreeTimer(Timer, Interval)) {
00405 ;
00406 }
00407 }
00408
00409
if (Timer->
Dpc !=
NULL) {
00410 Dpc = Timer->
Dpc;
00411
00412
00413
00414
00415
00416
00417
00418
#if defined(NT_UP)
00419
00420 DpcList[
Count].
Dpc = Dpc;
00421 DpcList[
Count].
Routine = Dpc->
DeferredRoutine;
00422 DpcList[
Count].
Context = Dpc->
DeferredContext;
00423
Count += 1;
00424
if (
Count ==
MAXIMUM_DPC_LIST_SIZE) {
00425
break;
00426 }
00427
00428
#else
00429
00430
if ((Dpc->
Number >=
MAXIMUM_PROCESSORS) &&
00431 (((ULONG)Dpc->
Number -
MAXIMUM_PROCESSORS) != (ULONG)KeGetCurrentProcessorNumber())) {
00432
KeInsertQueueDpc(Dpc,
00433 ULongToPtr(SystemTime.LowPart),
00434 ULongToPtr(SystemTime.HighPart));
00435
00436 }
else {
00437 DpcList[
Count].
Dpc = Dpc;
00438 DpcList[
Count].
Routine = Dpc->
DeferredRoutine;
00439 DpcList[
Count].
Context = Dpc->
DeferredContext;
00440
Count += 1;
00441
if (
Count ==
MAXIMUM_DPC_LIST_SIZE) {
00442
break;
00443 }
00444 }
00445
00446
#endif
00447
00448 }
00449 }
00450
00451
00452
00453
00454
00455
if (
Count != 0) {
00456
KiUnlockDispatcherDatabase(
DISPATCH_LEVEL);
00457
Index = 0;
00458
do {
00459
00460
#if DBG && (defined(i386) || defined(ALPHA))
00461
00462
00463
00464
00465
00466
00467
00468
KeGetCurrentPrcb()->DebugDpcTime = 0;
00469
#endif
00470
00471 (DpcList[
Index].
Routine)(DpcList[
Index].
Dpc,
00472 DpcList[
Index].
Context,
00473 ULongToPtr(SystemTime.LowPart),
00474 ULongToPtr(SystemTime.HighPart));
00475
00476
00477
Index += 1;
00478 }
while (
Index <
Count);
00479
00480
00481
00482
00483
00484
00485
if (
Count ==
MAXIMUM_DPC_LIST_SIZE) {
00486
KiLockDispatcherDatabase(&OldIrql1);
00487
goto RestartScan;
00488 }
00489
00490
KeLowerIrql(OldIrql);
00491
00492 }
else {
00493
KiUnlockDispatcherDatabase(OldIrql);
00494 }
00495
00496
return;
00497 }