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

region.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Module Name: 00004 00005 session.c 00006 00007 Abstract: 00008 00009 This module implements the region space management code. 00010 00011 Author: 00012 00013 18-Feb-1999 00014 00015 Environment: 00016 00017 Kernel mode only. 00018 00019 Revision History: 00020 00021 --*/ 00022 00023 #include "ki.h" 00024 #include "mm.h" 00025 #include "..\..\mm\mi.h" 00026 00027 VOID 00028 KiSetRegionRegister ( 00029 PVOID VirtualAddress, 00030 ULONGLONG Contents 00031 ); 00032 00033 00034 #define KiMakeValidRegionRegister(Rid, Ps) \ 00035 (((ULONGLONG)Rid << RR_RID) | (Ps << RR_PS) | (1 << RR_VE)) 00036 00037 ULONG KiMaximumRid = MAXIMUM_RID; 00038 00039 00040 VOID 00041 KiSyncNewRegionIdTarget ( 00042 IN PULONG SignalDone, 00043 IN PVOID Parameter1, 00044 IN PVOID Parameter2, 00045 IN PVOID Parameter3 00046 ) 00047 00048 /*++ 00049 00050 Routine Description: 00051 00052 This is the target function for synchronizing the region Ids 00053 00054 Arguments: 00055 00056 SignalDone Supplies a pointer to a variable that is cleared when the 00057 requested operation has been performed. 00058 00059 Parameter1 - Parameter3 - Not used. 00060 00061 Return Value: 00062 00063 None. 00064 00065 --*/ 00066 00067 { 00068 #if !defined(NT_UP) 00069 00070 PKTHREAD Thread; 00071 PKPROCESS Process; 00072 PREGION_MAP_INFO ProcessRegion; 00073 PREGION_MAP_INFO MappedSession; 00074 ULONG NewRid; 00075 00076 // 00077 // Flush the entire TB on the current processor. 00078 // 00079 00080 Thread = KeGetCurrentThread(); 00081 Process = Thread->ApcState.Process; 00082 ProcessRegion = &Process->ProcessRegion; 00083 MappedSession = Process->SessionMapInfo; 00084 00085 KiAcquireSpinLock(&KiMasterRidLock); 00086 00087 if (ProcessRegion->SequenceNumber != KiMasterSequence) { 00088 00089 KiMasterRid += 1; 00090 00091 ProcessRegion->RegionId = KiMasterRid; 00092 ProcessRegion->SequenceNumber = KiMasterSequence; 00093 00094 KiSetRegionRegister(MM_LOWEST_USER_ADDRESS, 00095 KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT)); 00096 00097 } 00098 00099 if (MappedSession->SequenceNumber != KiMasterSequence) { 00100 00101 KiMasterRid += 1; 00102 00103 MappedSession->RegionId = KiMasterRid; 00104 MappedSession->SequenceNumber = KiMasterSequence; 00105 00106 KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 00107 KiMakeValidRegionRegister(MappedSession->RegionId, PAGE_SHIFT)); 00108 } 00109 00110 00111 KiReleaseSpinLock(&KiMasterRidLock); 00112 00113 KiIpiSignalPacketDone(SignalDone); 00114 00115 KeFlushCurrentTb(); 00116 00117 #endif 00118 return; 00119 } 00120 00121 BOOLEAN 00122 KiSyncNewRegionId( 00123 IN PREGION_MAP_INFO ProcessRegion, 00124 IN PREGION_MAP_INFO SessionRegion 00125 ) 00126 /*++ 00127 00128 Routine Description: 00129 00130 Generate a new region id and synchronze the region Ids on all the processors 00131 if necessary. If the region ids wrap then flush all processor TLB's. 00132 00133 Arguments: 00134 00135 ProcessRegion - Supplies a pointer to REGION_MAP_INFO for the user space. 00136 SessionRegion - Supplies a pointer to REGION_MAP_INFO for the session space. 00137 00138 Return Value: 00139 00140 FALSE -- when region id has not been recycled. 00141 00142 TRUE -- when region id has been recycled. 00143 00144 Notes: 00145 00146 This routine called by KiSwapProcess, KeAttachSessionSpace and 00147 KeCreateSessionSpace. 00148 00149 Environment: 00150 00151 Kernel mode. 00152 KiLockDispaterLock or LockQueuedDispatcherLock is held 00153 00154 --*/ 00155 00156 { 00157 BOOLEAN RidRecycled = FALSE; 00158 KAFFINITY TargetProcessors; 00159 ULONG i; 00160 00161 // 00162 // Invalidate the ForwardProgressTb buffer 00163 // 00164 00165 for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) { 00166 00167 PCR->ForwardProgressBuffer[(i*2)+1] = 0; 00168 00169 } 00170 00171 KiAcquireSpinLock(&KiMasterRidLock); 00172 00173 if ((ProcessRegion->SequenceNumber == KiMasterSequence) && 00174 (SessionRegion->SequenceNumber == KiMasterSequence)) { 00175 00176 goto not_recycled; 00177 00178 } 00179 00180 if (ProcessRegion->SequenceNumber != KiMasterSequence) { 00181 00182 if (KiMasterRid + 1 > KiMaximumRid) { 00183 00184 RidRecycled = TRUE; 00185 00186 } else { 00187 00188 KiMasterRid += 1; 00189 ProcessRegion->RegionId = KiMasterRid; 00190 ProcessRegion->SequenceNumber = KiMasterSequence; 00191 } 00192 00193 } 00194 00195 if ((RidRecycled == FALSE) && 00196 (SessionRegion->SequenceNumber != KiMasterSequence)) { 00197 00198 if (KiMasterRid + 1 > KiMaximumRid) { 00199 00200 RidRecycled = TRUE; 00201 00202 } else { 00203 00204 KiMasterRid += 1; 00205 SessionRegion->RegionId = KiMasterRid; 00206 SessionRegion->SequenceNumber = KiMasterSequence; 00207 } 00208 } 00209 00210 if (RidRecycled == FALSE) { 00211 00212 goto not_recycled; 00213 00214 } 00215 00216 // 00217 // Region Id must be recycled 00218 // 00219 00220 KiMasterRid = START_PROCESS_RID; 00221 00222 // 00223 // Since KiMasterSequence is 64-bit wide, it will not be recycled in your life time. 00224 // 00225 00226 if (KiMasterSequence + 1 > MAXIMUM_SEQUENCE) { 00227 00228 KiMasterSequence = START_SEQUENCE; 00229 00230 } else { 00231 00232 KiMasterSequence += 1; 00233 } 00234 00235 // 00236 // update new process's ProcessRid and ProcessSequence 00237 // 00238 00239 ProcessRegion->RegionId = KiMasterRid; 00240 ProcessRegion->SequenceNumber = KiMasterSequence; 00241 00242 KiSetRegionRegister(MM_LOWEST_USER_ADDRESS, 00243 KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT)); 00244 00245 KiMasterRid += 1; 00246 00247 SessionRegion->RegionId = KiMasterRid; 00248 SessionRegion->SequenceNumber = KiMasterSequence; 00249 00250 KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 00251 KiMakeValidRegionRegister(SessionRegion->RegionId, PAGE_SHIFT)); 00252 00253 // 00254 // release mutex for master region id lock 00255 // 00256 00257 KiReleaseSpinLock(&KiMasterRidLock); 00258 00259 #if !defined(NT_UP) 00260 00261 // 00262 // broadcast Region Id sync 00263 // 00264 00265 TargetProcessors = KeActiveProcessors; 00266 TargetProcessors &= PCR->NotMember; 00267 00268 if (TargetProcessors != 0) { 00269 KiIpiSendPacket(TargetProcessors, 00270 KiSyncNewRegionIdTarget, 00271 (PVOID)TRUE, 00272 NULL, 00273 NULL); 00274 } 00275 00276 #endif 00277 00278 KeFlushCurrentTb(); 00279 00280 00281 #if !defined(NT_UP) 00282 00283 // 00284 // Wait until all target processors have finished. 00285 // 00286 00287 if (TargetProcessors != 0) { 00288 KiIpiStallOnPacketTargets(TargetProcessors); 00289 } 00290 00291 #endif 00292 00293 return TRUE; 00294 00295 00296 not_recycled: 00297 00298 KiSetRegionRegister(MM_LOWEST_USER_ADDRESS, 00299 KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT)); 00300 00301 KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 00302 KiMakeValidRegionRegister(SessionRegion->RegionId, PAGE_SHIFT)); 00303 00304 // 00305 // release mutex for master region id lock 00306 // 00307 00308 KiReleaseSpinLock(&KiMasterRidLock); 00309 00310 return FALSE; 00311 00312 } 00313 00314 VOID 00315 KeEnableSessionSharing( 00316 PREGION_MAP_INFO SessionMapInfo 00317 ) 00318 /*++ 00319 00320 Routine Description: 00321 00322 This routine enables session sharing by the other processes. 00323 00324 Arguments: 00325 00326 SessionMapInfo - Supplies a session map info to be shared. 00327 00328 Return Value: 00329 00330 None. 00331 00332 Environment: 00333 00334 Kernel mode. 00335 00336 --*/ 00337 { 00338 PKPROCESS Process; 00339 PKTHREAD Thread; 00340 KIRQL OldIrql; 00341 00342 Thread = KeGetCurrentThread(); 00343 Process = Thread->ApcState.Process; 00344 00345 // 00346 // Raise IRQL to dispatcher level and lock the dispatcher database. 00347 // 00348 00349 KiLockDispatcherDatabase(&OldIrql); 00350 00351 SessionMapInfo->RegionId = Process->SessionRegion.RegionId; 00352 SessionMapInfo->SequenceNumber = Process->SessionRegion.SequenceNumber; 00353 00354 Process->SessionMapInfo = SessionMapInfo; 00355 00356 // 00357 // unlock the dispatcher database 00358 // 00359 00360 KiUnlockDispatcherDatabase(OldIrql); 00361 } 00362 00363 VOID 00364 KeDisableSessionSharing( 00365 PREGION_MAP_INFO SessionMapInfo 00366 ) 00367 /*++ 00368 00369 Routine Description: 00370 00371 This routine disables session sharing by the other process. 00372 00373 Arguments: 00374 00375 SessionMapInfo - Supplies a session map info to be disabled 00376 for sharing. 00377 00378 Return Value: 00379 00380 None. 00381 00382 Environment: 00383 00384 Kernel mode. 00385 00386 --*/ 00387 { 00388 PKPROCESS Process; 00389 PKTHREAD Thread; 00390 KIRQL OldIrql; 00391 00392 Thread = KeGetCurrentThread(); 00393 Process = Thread->ApcState.Process; 00394 00395 // 00396 // Raise IRQL to dispatcher level and lock the dispatcher database. 00397 // 00398 00399 KiLockDispatcherDatabase(&OldIrql); 00400 00401 Process->SessionRegion.RegionId = SessionMapInfo->RegionId; 00402 Process->SessionRegion.SequenceNumber = SessionMapInfo->SequenceNumber; 00403 Process->SessionMapInfo = &Process->SessionRegion; 00404 00405 // 00406 // unlock the dispatcher database 00407 // 00408 00409 KiUnlockDispatcherDatabase(OldIrql); 00410 } 00411 00412 VOID 00413 KeAttachSessionSpace( 00414 PREGION_MAP_INFO SessionMapInfo 00415 ) 00416 /*++ 00417 00418 Routine Description: 00419 00420 This routine attaches a session map info to the current process. 00421 00422 Arguments: 00423 00424 SessionMapInfo - Supplies a session map info to be attached. 00425 00426 Return Value: 00427 00428 None. 00429 00430 Environment: 00431 00432 Kernel mode. 00433 00434 --*/ 00435 { 00436 KIRQL OldIrql; 00437 PKTHREAD Thread; 00438 PKPROCESS Process; 00439 00440 Thread = KeGetCurrentThread(); 00441 Process = Thread->ApcState.Process; 00442 00443 // 00444 // Raise IRQL to dispatcher level and lock the dispatcher database. 00445 // 00446 00447 KiLockDispatcherDatabase(&OldIrql); 00448 00449 ASSERT(SessionMapInfo != NULL); 00450 00451 // 00452 // Attach the given session map 00453 // 00454 00455 Process->SessionMapInfo = SessionMapInfo; 00456 00457 KiSyncNewRegionId(&Process->ProcessRegion, SessionMapInfo); 00458 00459 // 00460 // unlock the dispatcher database 00461 // 00462 00463 KiUnlockDispatcherDatabase(OldIrql); 00464 00465 } 00466 00467 VOID 00468 KiSyncSessionTarget( 00469 IN PULONG SignalDone, 00470 IN PKPROCESS Process, 00471 IN PVOID Parameter1, 00472 IN PVOID Parameter2 00473 ) 00474 /*++ 00475 00476 Routine Description: 00477 00478 This is the target function for synchronizing the new session 00479 region id. This routine is called when the session space is removed 00480 and all the processors need to be notified. 00481 00482 Arguments: 00483 00484 SignalDone - Supplies a pointer to a variable that is cleared when the 00485 requested operation has been performed. 00486 00487 Process - Supplies a KPROCESS pointer which needs to be sync'ed. 00488 00489 Return Value: 00490 00491 None. 00492 00493 Environment: 00494 00495 Kernel mode. 00496 00497 --*/ 00498 { 00499 #if !defined(NT_UP) 00500 00501 PKTHREAD Thread; 00502 ULONG NewRid; 00503 00504 // 00505 // Flush the entire TB on the current processor. 00506 // 00507 00508 Thread = KeGetCurrentThread(); 00509 00510 // 00511 // check to see if the current process is the process that needs to be 00512 // sync'ed 00513 // 00514 00515 if (Process == Thread->ApcState.Process) { 00516 00517 KiAcquireSpinLock(&KiMasterRidLock); 00518 00519 // 00520 // disable the session region. 00521 // 00522 00523 KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 00524 KiMakeValidRegionRegister(Process->SessionMapInfo->RegionId, PAGE_SHIFT)); 00525 00526 KiReleaseSpinLock(&KiMasterRidLock); 00527 00528 // 00529 // flush the entire tb. 00530 // 00531 00532 KeFlushCurrentTb(); 00533 } 00534 00535 KiIpiSignalPacketDone(SignalDone); 00536 00537 #endif 00538 return; 00539 } 00540 00541 00542 VOID 00543 KeDetachSessionSpace( 00544 VOID 00545 ) 00546 /*++ 00547 00548 Routine Description: 00549 00550 This routine removes the session space and synchronize the all threads on 00551 the other processors. 00552 00553 Arguments: 00554 00555 DeleteSessionMapInfo - if TRUE, the session map info will be deleted. 00556 if FALSE, the session map info will not be deleted. 00557 00558 Return Value: 00559 00560 None. 00561 00562 Environment: 00563 00564 Kernel mode. 00565 00566 --*/ 00567 { 00568 KIRQL OldIrql; 00569 PKTHREAD Thread; 00570 PKPROCESS Process; 00571 #if !defined(NT_UP) 00572 KAFFINITY TargetProcessors; 00573 #endif 00574 00575 // 00576 // Raise IRQL to dispatcher level and lock the dispatcher database. 00577 // 00578 00579 KiLockDispatcherDatabase(&OldIrql); 00580 00581 Thread = KeGetCurrentThread(); 00582 Process = Thread->ApcState.Process; 00583 00584 // 00585 // Lock the region Id resource. 00586 // 00587 00588 KiAcquireSpinLock(&KiMasterRidLock); 00589 00590 Process->SessionMapInfo = &Process->SessionRegion; 00591 00592 KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 00593 KiMakeValidRegionRegister(Process->SessionMapInfo->RegionId, PAGE_SHIFT)); 00594 00595 // 00596 // Unlock the region Id resource. 00597 // 00598 00599 KiReleaseSpinLock(&KiMasterRidLock); 00600 00601 #if !defined(NT_UP) 00602 00603 // 00604 // broadcast Region Id sync 00605 // 00606 00607 TargetProcessors = KeActiveProcessors; 00608 TargetProcessors &= PCR->NotMember; 00609 00610 if (TargetProcessors != 0) { 00611 KiIpiSendPacket(TargetProcessors, 00612 KiSyncSessionTarget, 00613 Process, 00614 NULL, 00615 NULL); 00616 } 00617 00618 #endif 00619 00620 // 00621 // Unlock the dispatcher database 00622 // 00623 00624 KiUnlockDispatcherDatabase(OldIrql); 00625 } 00626 00627 VOID 00628 KeAddSessionSpace( 00629 PKPROCESS Process, 00630 PREGION_MAP_INFO SessionMapInfo 00631 ) 00632 /*++ 00633 00634 Routine Description: 00635 00636 Add the session map info to the KPROCESS of the new process. 00637 00638 Arguments: 00639 00640 Process - Supplies a pointer to the process being created. 00641 00642 SessionMapInfo - Supplies a pointer to the SessionMapInfo. 00643 00644 Return Value: 00645 00646 None. 00647 00648 Environment: 00649 00650 Kernel mode, APCs disabled. 00651 00652 Remarks: 00653 00654 KiLockDispaterLock or LockQueuedDispatcherLock is not necessary 00655 since the process has not run yet. 00656 00657 --*/ 00658 { 00659 KIRQL OldIrql; 00660 00661 ASSERT (Process->SessionMapInfo == NULL); 00662 00663 // KiLockDispatcherDatabase(&OldIrql); 00664 00665 Process->SessionMapInfo = SessionMapInfo; 00666 00667 // KiUnLockDispatherDatabase(OldIrql); 00668 00669 } 00670

Generated on Sat May 15 19:41:37 2004 for test by doxygen 1.3.7