Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

miscc.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989-1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 miscc.c 00008 00009 Abstract: 00010 00011 This module implements machine independent miscellaneous kernel functions. 00012 00013 Author: 00014 00015 David N. Cutler (davec) 13-May-1989 00016 00017 Environment: 00018 00019 Kernel mode only. 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "ki.h" 00026 00027 #ifdef ALLOC_PRAGMA 00028 #pragma alloc_text(PAGE, KeAddSystemServiceTable) 00029 #pragma alloc_text(PAGE, KeSetSwapContextNotifyRoutine) 00030 #pragma alloc_text(PAGE, KeSetTimeUpdateNotifyRoutine) 00031 #pragma alloc_text(PAGE, KeSetThreadSelectNotifyRoutine) 00032 #pragma alloc_text(PAGE, KeQueryActiveProcessors) 00033 #pragma alloc_text(PAGELK, KiCalibrateTimeAdjustment) 00034 #endif 00035 00036 00037 00038 00039 #undef KeEnterCriticalRegion 00040 VOID 00041 KeEnterCriticalRegion ( 00042 VOID 00043 ) 00044 00045 /*++ 00046 00047 Routine Description: 00048 00049 This function disables kernel APC's. 00050 00051 N.B. The following code does not require any interlocks. There are 00052 two cases of interest: 1) On an MP system, the thread cannot 00053 be running on two processors as once, and 2) if the thread is 00054 is interrupted to deliver a kernel mode APC which also calls 00055 this routine, the values read and stored will stack and unstack 00056 properly. 00057 00058 Arguments: 00059 00060 None. 00061 00062 Return Value: 00063 00064 None. 00065 00066 --*/ 00067 00068 { 00069 // 00070 // Simply directly disable kernel APCs. 00071 // 00072 00073 KeGetCurrentThread()->KernelApcDisable -= 1; 00074 return; 00075 } 00076 00077 00078 #undef KeLeaveCriticalRegion 00079 VOID 00080 KeLeaveCriticalRegion ( 00081 VOID 00082 ) 00083 00084 /*++ 00085 00086 Routine Description: 00087 00088 This function enables kernel APC's and requests an APC interrupt if 00089 appropriate. 00090 00091 Arguments: 00092 00093 None. 00094 00095 Return Value: 00096 00097 None. 00098 00099 --*/ 00100 00101 { 00102 00103 // 00104 // Increment the kernel APC disable count. If the resultant count is 00105 // zero and the thread's kernel APC List is not empty, then request an 00106 // APC interrupt. 00107 // 00108 // For multiprocessor performance, the following code utilizes the fact 00109 // that queuing an APC is done by first queuing the APC, then checking 00110 // the AST disable count. The following code increments the disable 00111 // count first, checks to determine if it is zero, and then checks the 00112 // kernel AST queue. 00113 // 00114 // See also KiInsertQueueApc(). 00115 // 00116 00117 KiLeaveCriticalRegion(); 00118 return; 00119 } 00120 00121 ULONGLONG 00122 KeQueryInterruptTime ( 00123 VOID 00124 ) 00125 00126 /*++ 00127 00128 Routine Description: 00129 00130 This function returns the current interrupt time by determining when the 00131 time is stable and then returning its value. 00132 00133 Arguments: 00134 00135 CurrentTime - Supplies a pointer to a variable that will receive the 00136 current system time. 00137 00138 Return Value: 00139 00140 None. 00141 00142 --*/ 00143 00144 { 00145 00146 LARGE_INTEGER CurrentTime; 00147 00148 KiQueryInterruptTime(&CurrentTime); 00149 return CurrentTime.QuadPart; 00150 } 00151 00152 VOID 00153 KeQuerySystemTime ( 00154 OUT PLARGE_INTEGER CurrentTime 00155 ) 00156 00157 /*++ 00158 00159 Routine Description: 00160 00161 This function returns the current system time by determining when the 00162 time is stable and then returning its value. 00163 00164 Arguments: 00165 00166 CurrentTime - Supplies a pointer to a variable that will receive the 00167 current system time. 00168 00169 Return Value: 00170 00171 None. 00172 00173 --*/ 00174 00175 { 00176 00177 KiQuerySystemTime(CurrentTime); 00178 return; 00179 } 00180 00181 VOID 00182 KeQueryTickCount ( 00183 OUT PLARGE_INTEGER CurrentCount 00184 ) 00185 00186 /*++ 00187 00188 Routine Description: 00189 00190 This function returns the current tick count by determining when the 00191 count is stable and then returning its value. 00192 00193 Arguments: 00194 00195 CurrentCount - Supplies a pointer to a variable that will receive the 00196 current tick count. 00197 00198 Return Value: 00199 00200 None. 00201 00202 --*/ 00203 00204 { 00205 00206 KiQueryTickCount(CurrentCount); 00207 return; 00208 } 00209 00210 ULONG 00211 KeQueryTimeIncrement ( 00212 VOID 00213 ) 00214 00215 /*++ 00216 00217 Routine Description: 00218 00219 This function returns the time increment value in 100ns units. This 00220 is the value that is added to the system time at each interval clock 00221 interrupt. 00222 00223 Arguments: 00224 00225 None. 00226 00227 Return Value: 00228 00229 The time increment value is returned as the function value. 00230 00231 --*/ 00232 00233 { 00234 00235 return KeMaximumIncrement; 00236 } 00237 00238 VOID 00239 KeSetDmaIoCoherency ( 00240 IN ULONG Attributes 00241 ) 00242 00243 /*++ 00244 00245 Routine Description: 00246 00247 This function sets (enables/disables) DMA I/O coherency with data 00248 caches. 00249 00250 Arguments: 00251 00252 Attributes - Supplies the set of DMA I/O coherency attributes for 00253 the host system. 00254 00255 Return Value: 00256 00257 None. 00258 00259 --*/ 00260 00261 { 00262 00263 KiDmaIoCoherency = Attributes; 00264 } 00265 00266 #if defined(i386) 00267 VOID 00268 KeSetProfileIrql ( 00269 IN KIRQL ProfileIrql 00270 ) 00271 00272 /*++ 00273 00274 Routine Description: 00275 00276 This function sets the profile IRQL. 00277 00278 N.B. There are only two valid values for synchronization IRQL: 00279 PROFILE_LEVEL and HIGH_LEVEL. 00280 00281 Arguments: 00282 00283 Irql - Supplies the synchronization IRQL value. 00284 00285 Return Value: 00286 00287 None. 00288 00289 --*/ 00290 00291 { 00292 00293 ASSERT((ProfileIrql == PROFILE_LEVEL) || (ProfileIrql == HIGH_LEVEL)); 00294 KiProfileIrql = ProfileIrql; 00295 } 00296 00297 #endif 00298 00299 #if defined(_ALPHA_) 00300 VOID 00301 KeSetSynchIrql ( 00302 IN KIRQL SynchIrql 00303 ) 00304 00305 /*++ 00306 00307 Routine Description: 00308 00309 This function sets the synchronization IRQL. 00310 00311 N.B. Synchronization IRQL may be any value between DISPATCH_LEVEL 00312 and SYNCH_LEVEL. 00313 00314 Arguments: 00315 00316 Irql - Supplies the synchronization IRQL value. 00317 00318 Return Value: 00319 00320 None. 00321 00322 --*/ 00323 00324 { 00325 00326 ASSERT((SynchIrql >= DISPATCH_LEVEL) && (SynchIrql <= SYNCH_LEVEL)); 00327 00328 KiSynchIrql = SynchIrql; 00329 } 00330 00331 #endif 00332 00333 00334 VOID 00335 KeSetSystemTime ( 00336 IN PLARGE_INTEGER NewTime, 00337 OUT PLARGE_INTEGER OldTime, 00338 IN BOOLEAN AdjustInterruptTime, 00339 IN PLARGE_INTEGER HalTimeToSet OPTIONAL 00340 ) 00341 00342 /*++ 00343 00344 Routine Description: 00345 00346 This function sets the system time to the specified value and updates 00347 timer queue entries to reflect the difference between the old system 00348 time and the new system time. 00349 00350 Arguments: 00351 00352 NewTime - Supplies a pointer to a variable that specifies the new system 00353 time. 00354 00355 OldTime - Supplies a pointer to a variable that will receive the previous 00356 system time. 00357 00358 AdjustInterruptTime - If TRUE the amount of time being adjusted is 00359 also applied to InterruptTime and TickCount. 00360 00361 HalTimeToSet - Supplies an optional time that if specified is to be used 00362 to set the time in the realtime clock. 00363 00364 Return Value: 00365 00366 None. 00367 00368 --*/ 00369 00370 { 00371 00372 LIST_ENTRY AbsoluteListHead; 00373 LIST_ENTRY ExpiredListHead; 00374 ULONG Index; 00375 PLIST_ENTRY ListHead; 00376 PLIST_ENTRY NextEntry; 00377 KIRQL OldIrql1; 00378 KIRQL OldIrql2; 00379 LARGE_INTEGER TimeDelta; 00380 TIME_FIELDS TimeFields; 00381 PKTIMER Timer; 00382 00383 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL); 00384 00385 // 00386 // If a realtime clock value is specified, then convert the time value 00387 // to time fields. 00388 // 00389 00390 if (ARGUMENT_PRESENT(HalTimeToSet)) { 00391 RtlTimeToTimeFields(HalTimeToSet, &TimeFields); 00392 } 00393 00394 // 00395 // Set affinity to the processor that keeps the system time, raise IRQL 00396 // to dispatcher level and lock the dispatcher database, then raise IRQL 00397 // to HIGH_LEVEL to synchronize with the clock interrupt routine. 00398 // 00399 00400 KeSetSystemAffinityThread((KAFFINITY)1); 00401 KiLockDispatcherDatabase(&OldIrql1); 00402 KeRaiseIrql(HIGH_LEVEL, &OldIrql2); 00403 00404 // 00405 // Save the previous system time, set the new system time, and set 00406 // the realtime clock, if a time value is specified. 00407 // 00408 00409 KiQuerySystemTime(OldTime); 00410 00411 #if defined(_WIN64) 00412 00413 SharedUserData->SystemHigh2Time = NewTime->HighPart; 00414 SharedUserData->SystemLowTime = NewTime->LowPart; 00415 SharedUserData->SystemHigh1Time = NewTime->HighPart; 00416 00417 #elif defined(ALPHA) 00418 00419 SharedUserData->SystemTime = *(PULONGLONG)NewTime; 00420 00421 #else 00422 00423 SharedUserData->SystemTime.High2Time = NewTime->HighPart; 00424 SharedUserData->SystemTime.LowPart = NewTime->LowPart; 00425 SharedUserData->SystemTime.High1Time = NewTime->HighPart; 00426 00427 #endif // defined(ALPHA) || defined(_IA64_) 00428 00429 if (ARGUMENT_PRESENT(HalTimeToSet)) { 00430 HalSetRealTimeClock(&TimeFields); 00431 } 00432 00433 // 00434 // Compute the difference between the previous system time and the new 00435 // system time. 00436 // 00437 00438 TimeDelta.QuadPart = NewTime->QuadPart - OldTime->QuadPart; 00439 00440 // 00441 // Update the boot time to reflect the delta. This keeps time based 00442 // on boot time constant 00443 // 00444 00445 KeBootTime.QuadPart = KeBootTime.QuadPart + TimeDelta.QuadPart; 00446 00447 // 00448 // Track the overall bias applied to the boot time. 00449 // 00450 00451 KeBootTimeBias = KeBootTimeBias + TimeDelta.QuadPart; 00452 00453 // 00454 // Lower IRQL to dispatch level and if needed adjust the physical 00455 // system interrupt time. 00456 // 00457 00458 KeLowerIrql(OldIrql2); 00459 if (AdjustInterruptTime) { 00460 00461 // 00462 // Adjust the physical time of the system 00463 // 00464 00465 AdjustInterruptTime = KiAdjustInterruptTime (TimeDelta.QuadPart); 00466 } 00467 00468 // 00469 // If the physical interrupt time of the system was not adjusted, 00470 // recompute any absolute timers in the system for the new 00471 // system time. 00472 // 00473 00474 if (!AdjustInterruptTime) { 00475 00476 // 00477 // Remove all absolute timers from the timer queue so their due time 00478 // can be recomputed. 00479 // 00480 00481 InitializeListHead(&AbsoluteListHead); 00482 for (Index = 0; Index < TIMER_TABLE_SIZE; Index += 1) { 00483 ListHead = &KiTimerTableListHead[Index]; 00484 NextEntry = ListHead->Flink; 00485 while (NextEntry != ListHead) { 00486 Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); 00487 NextEntry = NextEntry->Flink; 00488 if (Timer->Header.Absolute != FALSE) { 00489 RemoveEntryList(&Timer->TimerListEntry); 00490 InsertTailList(&AbsoluteListHead, &Timer->TimerListEntry); 00491 } 00492 } 00493 } 00494 00495 // 00496 // Recompute the due time and reinsert all absolute timers in the timer 00497 // tree. If a timer has already expired, then insert the timer in the 00498 // expired timer list. 00499 // 00500 00501 InitializeListHead(&ExpiredListHead); 00502 while (AbsoluteListHead.Flink != &AbsoluteListHead) { 00503 Timer = CONTAINING_RECORD(AbsoluteListHead.Flink, KTIMER, TimerListEntry); 00504 KiRemoveTreeTimer(Timer); 00505 Timer->DueTime.QuadPart -= TimeDelta.QuadPart; 00506 if (KiReinsertTreeTimer(Timer, Timer->DueTime) == FALSE) { 00507 Timer->Header.Inserted = TRUE; 00508 InsertTailList(&ExpiredListHead, &Timer->TimerListEntry); 00509 } 00510 } 00511 00512 // 00513 // If any of the attempts to reinsert a timer failed, then timers have 00514 // already expired and must be processed. 00515 // 00516 // N.B. The following function returns with the dispatcher database 00517 // unlocked. 00518 // 00519 00520 KiTimerListExpire(&ExpiredListHead, OldIrql1); 00521 00522 } else { 00523 00524 KiUnlockDispatcherDatabase(OldIrql1); 00525 00526 } 00527 00528 00529 // 00530 // Set affinity back to its original value. 00531 // 00532 00533 KeRevertToUserAffinityThread(); 00534 00535 // 00536 // Notify other components that the system time has been set 00537 // 00538 00539 PoNotifySystemTimeSet(); 00540 return; 00541 } 00542 00543 BOOLEAN 00544 KiAdjustInterruptTime ( 00545 IN LONGLONG TimeDelta 00546 ) 00547 /*++ 00548 00549 Routine Description: 00550 00551 This function moves the physical interrupt time of the system 00552 foreward by TimeDelta after a system wake has occurred. 00553 00554 Arguments: 00555 00556 TimeDelta - amount of time to bump foreward interrupt time, tick 00557 count and the perforamnce counter in 100ns units 00558 00559 Return Value: 00560 00561 None. 00562 00563 --*/ 00564 { 00565 ADJUST_INTERRUPT_TIME_CONTEXT Adjust; 00566 00567 // 00568 // Can only move time foreward 00569 // 00570 00571 if (TimeDelta < 0) { 00572 00573 return FALSE; 00574 00575 } else { 00576 00577 Adjust.KiNumber = KeNumberProcessors; 00578 Adjust.HalNumber = KeNumberProcessors; 00579 Adjust.Adjustment = (ULONGLONG) TimeDelta; 00580 Adjust.Barrier = 1; 00581 00582 KiIpiGenericCall ( 00583 (PKIPI_BROADCAST_WORKER) KiCalibrateTimeAdjustment, 00584 (ULONG_PTR)(&Adjust) 00585 ); 00586 00587 return TRUE; 00588 } 00589 } 00590 00591 VOID 00592 KiCalibrateTimeAdjustment ( 00593 PADJUST_INTERRUPT_TIME_CONTEXT Adjust 00594 ) 00595 /*++ 00596 00597 Routine Description: 00598 00599 Worker function for KiAdjustInterruptTime to calibrate the 00600 adjustment of time on all processors. 00601 00602 Arguments: 00603 00604 Adjust - context structure for operation 00605 00606 Return Value: 00607 00608 None. 00609 00610 --*/ 00611 { 00612 BOOLEAN Enable; 00613 LARGE_INTEGER InterruptTime; 00614 LARGE_INTEGER SetTime; 00615 LARGE_INTEGER PerfFreq; 00616 ULARGE_INTEGER li; 00617 LARGE_INTEGER NewTickCount; 00618 ULONG NewTickOffset; 00619 ULONG cl, divisor; 00620 00621 // 00622 // As each processor arrives, subtract one off the remaining processor 00623 // count. If this is the last processor to arrive compute the time 00624 // change, and signal all processor when to applied the performance 00625 // counter change. 00626 // 00627 00628 if (InterlockedDecrement((PLONG) &Adjust->KiNumber)) { 00629 00630 Enable = KiDisableInterrupts(); 00631 00632 // 00633 // It is possible to deadlock here if one or more of the 00634 // other processors gets and processes a freeze request 00635 // while this processor has interrupts disabled. Poll 00636 // for IPI_FREEZE requests until all processors are known 00637 // to be in this code and hence wont be requesting a 00638 // freeze. 00639 // 00640 00641 do { 00642 KiPollFreezeExecution(); 00643 } while (Adjust->KiNumber != (ULONG)-1); 00644 00645 // 00646 // Wait to perform the time set 00647 // 00648 00649 while (Adjust->Barrier) ; 00650 00651 } else { 00652 00653 // 00654 // Set timer expiration dpc to scan the timer queues once 00655 // for any expired timers 00656 // 00657 00658 KeRemoveQueueDpc (&KiTimerExpireDpc); 00659 KeInsertQueueDpc (&KiTimerExpireDpc, (PVOID) TIMER_TABLE_SIZE, NULL); 00660 00661 // 00662 // Disable interrupts and indicate that this processor is now 00663 // in final portion of this code. 00664 // 00665 00666 Enable = KiDisableInterrupts(); 00667 InterlockedDecrement((PLONG) &Adjust->KiNumber); 00668 00669 // 00670 // Get the current times 00671 // 00672 00673 KeQueryPerformanceCounter (&PerfFreq); 00674 InterruptTime.QuadPart = KeQueryInterruptTime() + Adjust->Adjustment; 00675 SetTime.QuadPart = InterruptTime.QuadPart + KeTimeIncrement / 2; 00676 00677 // 00678 // Compute performance counter for current SetTime 00679 // 00680 00681 // 00682 // Multiply SetTime * PerfCount and obtain 96bit result 00683 // in cl, li.LowPart, li.HighPart. Then divide the 96bit 00684 // result by 10,000,000 to get new performance counter value. 00685 // 00686 00687 li.QuadPart = RtlEnlargedUnsignedMultiply ( 00688 (ULONG) SetTime.LowPart, 00689 (ULONG) PerfFreq.LowPart 00690 ).QuadPart; 00691 00692 cl = li.LowPart; 00693 li.QuadPart = li.HighPart + 00694 RtlEnlargedUnsignedMultiply ( 00695 (ULONG) SetTime.LowPart, 00696 (ULONG) PerfFreq.HighPart 00697 ).QuadPart; 00698 00699 li.QuadPart = li.QuadPart + 00700 RtlEnlargedUnsignedMultiply ( 00701 (ULONG) SetTime.HighPart, 00702 (ULONG) PerfFreq.LowPart 00703 ).QuadPart; 00704 00705 li.HighPart = li.HighPart + SetTime.HighPart * PerfFreq.HighPart; 00706 00707 divisor = 10000000; 00708 Adjust->NewCount.HighPart = 00709 RtlEnlargedUnsignedDivide ( 00710 li, 00711 divisor, 00712 &li.HighPart 00713 ); 00714 00715 li.LowPart = cl; 00716 Adjust->NewCount.LowPart = 00717 RtlEnlargedUnsignedDivide ( 00718 li, 00719 divisor, 00720 NULL 00721 ); 00722 00723 // 00724 // Compute tick count and tick offset for current InterruptTime 00725 // 00726 00727 NewTickCount = RtlExtendedLargeIntegerDivide( 00728 InterruptTime, 00729 KeMaximumIncrement, 00730 &NewTickOffset 00731 ); 00732 00733 // 00734 // Apply changes to InterruptTime, TickCount, TickOffset, and the 00735 // performance counter 00736 // 00737 00738 KiTickOffset = KeMaximumIncrement - NewTickOffset; 00739 KeInterruptTimeBias += Adjust->Adjustment; 00740 SharedUserData->TickCountLow = NewTickCount.LowPart; 00741 00742 #if defined(_WIN64) 00743 00744 KeTickCount = NewTickCount.QuadPart; 00745 SharedUserData->InterruptHigh2Time = InterruptTime.HighPart; 00746 SharedUserData->InterruptTime = InterruptTime.QuadPart; 00747 00748 #elif defined(ALPHA) 00749 00750 KeTickCount = NewTickCount.QuadPart; 00751 SharedUserData->InterruptTime = InterruptTime.QuadPart; 00752 00753 #else 00754 KeTickCount.High2Time = NewTickCount.HighPart; 00755 KeTickCount.LowPart = NewTickCount.LowPart; 00756 KeTickCount.High1Time = NewTickCount.HighPart; 00757 00758 SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart; 00759 SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart; 00760 SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart; 00761 #endif 00762 00763 // 00764 // Apply the performance counter change 00765 // 00766 00767 Adjust->Barrier = 0; 00768 } 00769 00770 HalCalibratePerformanceCounter ( 00771 (volatile PLONG) &Adjust->HalNumber, 00772 (ULONGLONG) Adjust->NewCount.QuadPart 00773 ); 00774 00775 KiRestoreInterrupts(Enable); 00776 } 00777 00778 VOID 00779 KeSetTimeIncrement ( 00780 IN ULONG MaximumIncrement, 00781 IN ULONG MinimumIncrement 00782 ) 00783 00784 /*++ 00785 00786 Routine Description: 00787 00788 This function sets the time increment value in 100ns units. This 00789 value is added to the system time at each interval clock interrupt. 00790 00791 Arguments: 00792 00793 MaximumIncrement - Supplies the maximum time between clock interrupts 00794 in 100ns units supported by the host HAL. 00795 00796 MinimumIncrement - Supplies the minimum time between clock interrupts 00797 in 100ns units supported by the host HAL. 00798 00799 Return Value: 00800 00801 None. 00802 00803 --*/ 00804 00805 { 00806 00807 KeMaximumIncrement = MaximumIncrement; 00808 KeMinimumIncrement = max(MinimumIncrement, 10 * 1000); 00809 KeTimeAdjustment = MaximumIncrement; 00810 KeTimeIncrement = MaximumIncrement; 00811 KiTickOffset = MaximumIncrement; 00812 } 00813 00814 BOOLEAN 00815 KeAddSystemServiceTable( 00816 IN PULONG_PTR Base, 00817 IN PULONG Count OPTIONAL, 00818 IN ULONG Limit, 00819 IN PUCHAR Number, 00820 IN ULONG Index 00821 ) 00822 00823 /*++ 00824 00825 Routine Description: 00826 00827 This function allows the caller to add a system service table 00828 to the system 00829 00830 Arguments: 00831 00832 Base - Supplies the address of the system service table dispatch 00833 table. 00834 00835 Count - Supplies an optional pointer to a table of per system service 00836 counters. 00837 00838 Limit - Supplies the limit of the service table. Services greater 00839 than or equal to this limit will fail. 00840 00841 Arguments - Supplies the address of the argument count table. 00842 00843 Index - Supplies index of the service table. 00844 00845 Return Value: 00846 00847 TRUE - The operation was successful. 00848 00849 FALSE - the operation failed. A service table is already bound to 00850 the specified location, or the specified index is larger than 00851 the maximum allowed index. 00852 00853 --*/ 00854 00855 { 00856 00857 PAGED_CODE(); 00858 00859 // 00860 // If a system service table is already defined for the specified 00861 // index, then return FALSE. Otherwise, establish the new system 00862 // service table. 00863 // 00864 00865 if ((Index > NUMBER_SERVICE_TABLES - 1) || 00866 (KeServiceDescriptorTable[Index].Base != NULL) || 00867 (KeServiceDescriptorTableShadow[Index].Base != NULL)) { 00868 return FALSE; 00869 00870 } else { 00871 00872 // 00873 // If the service table index is equal to the Win32 table, then 00874 // only update the shadow system service table. Otherwise, both 00875 // the shadow and static system service tables are updated. 00876 // 00877 00878 KeServiceDescriptorTableShadow[Index].Base = Base; 00879 KeServiceDescriptorTableShadow[Index].Count = Count; 00880 KeServiceDescriptorTableShadow[Index].Limit = Limit; 00881 #if defined(_IA64_) 00882 00883 // 00884 // The global pointer associated with the table base is 00885 // placed just before the service table. 00886 // 00887 00888 KeServiceDescriptorTableShadow[Index].TableBaseGpOffset = 00889 (LONG)(*(Base-1) - (ULONG_PTR)Base); 00890 #endif 00891 KeServiceDescriptorTableShadow[Index].Number = Number; 00892 if (Index != 1) { 00893 KeServiceDescriptorTable[Index].Base = Base; 00894 KeServiceDescriptorTable[Index].Count = Count; 00895 KeServiceDescriptorTable[Index].Limit = Limit; 00896 #if defined(_IA64_) 00897 KeServiceDescriptorTable[Index].TableBaseGpOffset = 00898 (LONG)(*(Base-1) - (ULONG_PTR)Base); 00899 #endif 00900 KeServiceDescriptorTable[Index].Number = Number; 00901 } 00902 00903 return TRUE; 00904 } 00905 } 00906 00907 VOID 00908 FASTCALL 00909 KeSetSwapContextNotifyRoutine( 00910 IN PSWAP_CONTEXT_NOTIFY_ROUTINE NotifyRoutine 00911 ) 00912 /*++ 00913 00914 Routine Description: 00915 00916 This function sets the address of a callout routine which will be called 00917 at each context swtich. 00918 00919 Arguments: 00920 00921 NotifyRoutine - Supplies the address of the swap context notify callout 00922 routine. 00923 00924 Return Value: 00925 00926 None. 00927 00928 --*/ 00929 00930 { 00931 00932 PAGED_CODE(); 00933 00934 KiSwapContextNotifyRoutine = NotifyRoutine; 00935 return; 00936 } 00937 00938 VOID 00939 FASTCALL 00940 KeSetThreadSelectNotifyRoutine( 00941 IN PTHREAD_SELECT_NOTIFY_ROUTINE NotifyRoutine 00942 ) 00943 00944 /*++ 00945 00946 Routine Description: 00947 00948 This function sets the address of a callout routine which will be called 00949 when a thread is being selected for execution. 00950 00951 Arguments: 00952 00953 NotifyRoutine - Supplies the address of the thread select notify callout 00954 routine. 00955 00956 Return Value: 00957 00958 None. 00959 00960 --*/ 00961 00962 { 00963 00964 PAGED_CODE(); 00965 00966 KiThreadSelectNotifyRoutine = NotifyRoutine; 00967 return; 00968 } 00969 00970 VOID 00971 FASTCALL 00972 KeSetTimeUpdateNotifyRoutine( 00973 IN PTIME_UPDATE_NOTIFY_ROUTINE NotifyRoutine 00974 ) 00975 00976 /*++ 00977 00978 Routine Description: 00979 00980 This function sets the address of a callout routine which will be called 00981 each time the runtime for a thread is updated. 00982 00983 Arguments: 00984 00985 RoutineNotify - Supplies the address of the time update notify callout 00986 routine. 00987 00988 Return Value: 00989 00990 None. 00991 00992 --*/ 00993 00994 { 00995 00996 PAGED_CODE(); 00997 00998 KiTimeUpdateNotifyRoutine = NotifyRoutine; 00999 return; 01000 } 01001 01002 01003 KAFFINITY 01004 KeQueryActiveProcessors( 01005 VOID 01006 ) 01007 /*++ 01008 01009 Routine Description: 01010 01011 This function returns the current set of active processors 01012 in the system. 01013 01014 Arguments: 01015 01016 None. 01017 01018 Return Value: 01019 01020 KAFFINITY bitmask representing the set of active processors 01021 01022 --*/ 01023 01024 { 01025 PAGED_CODE(); 01026 01027 return(KeActiveProcessors); 01028 }

Generated on Sat May 15 19:40:49 2004 for test by doxygen 1.3.7