Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenlock.c
Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (C) Microsoft Corporation, 1990 - 1998 00004 00005 Module Name: 00006 00007 lock.c 00008 00009 Abstract: 00010 00011 This is the NT SCSI port driver. 00012 00013 Environment: 00014 00015 kernel mode only 00016 00017 Notes: 00018 00019 This module is a driver dll for scsi miniports. 00020 00021 Revision History: 00022 00023 --*/ 00024 00025 #include "classp.h" 00026 #include "debug.h" 00027 00028 00029 LONG LockHighWatermark = 0; 00030 LONG LockLowWatermark = 0; 00031 LONG MaxLockedMinutes = 5; 00032 00033 // 00034 // Structure used for tracking remove lock allocations in checked builds 00035 // 00036 typedef struct _REMOVE_TRACKING_BLOCK { 00037 struct _REMOVE_TRACKING_BLOCK *NextBlock; 00038 PVOID Tag; 00039 LARGE_INTEGER TimeLocked; 00040 PCSTR File; 00041 ULONG Line; 00042 } REMOVE_TRACKING_BLOCK, *PREMOVE_TRACKING_BLOCK; 00043 00044 00045 /*++//////////////////////////////////////////////////////////////////////////// 00046 00047 ClassAcquireRemoveLockEx() 00048 00049 Routine Description: 00050 00051 This routine is called to acquire the remove lock on the device object. 00052 While the lock is held, the caller can assume that no pending pnp REMOVE 00053 requests will be completed. 00054 00055 The lock should be acquired immediately upon entering a dispatch routine. 00056 It should also be acquired before creating any new reference to the 00057 device object if there's a chance of releasing the reference before the 00058 new one is done. 00059 00060 This routine will return TRUE if the lock was successfully acquired or 00061 FALSE if it cannot be because the device object has already been removed. 00062 00063 Arguments: 00064 00065 DeviceObject - the device object to lock 00066 00067 Tag - Used for tracking lock allocation and release. If an irp is 00068 specified when acquiring the lock then the same Tag must be 00069 used to release the lock before the Tag is completed. 00070 00071 Return Value: 00072 00073 The value of the IsRemoved flag in the device extension. If this is 00074 non-zero then the device object has received a Remove irp and non-cleanup 00075 IRP's should fail. 00076 00077 If the value is REMOVE_COMPLETE, the caller should not even release the 00078 lock. 00079 00080 --*/ 00081 ULONG 00082 ClassAcquireRemoveLockEx( 00083 IN PDEVICE_OBJECT DeviceObject, 00084 IN OPTIONAL PVOID Tag, 00085 IN PCSTR File, 00086 IN ULONG Line 00087 ) 00088 { 00089 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 00090 LONG lockValue; 00091 00092 00093 00094 // 00095 // Grab the remove lock 00096 // 00097 lockValue = InterlockedIncrement(&commonExtension->RemoveLock); 00098 00099 #if DBG 00100 00101 DebugPrint((ClassDebugRemoveLock, "ClassAcquireRemoveLock: " 00102 "Acquired for Object %p & irp %p - count is %d\n", 00103 DeviceObject, Tag, lockValue)); 00104 00105 ASSERTMSG("ClassAcquireRemoveLock - lock value was negative : ", 00106 (lockValue > 0)); 00107 00108 ASSERTMSG("RemoveLock increased to meet LockHighWatermark", 00109 ((LockHighWatermark == 0) || 00110 (lockValue != LockHighWatermark))); 00111 00112 if (commonExtension->IsRemoved != REMOVE_COMPLETE){ 00113 PREMOVE_TRACKING_BLOCK trackingBlock; 00114 00115 trackingBlock = ExAllocatePool(NonPagedPool, 00116 sizeof(REMOVE_TRACKING_BLOCK)); 00117 00118 if(trackingBlock == NULL) { 00119 00120 KIRQL oldIrql; 00121 00122 KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, 00123 &oldIrql); 00124 00125 commonExtension->RemoveTrackingUntrackedCount++; 00126 00127 DebugPrint((ClassDebugWarning, ">>>>>ClassAcquireRemoveLock: " 00128 "Cannot track Tag %p - currently %d untracked requsts\n", 00129 Tag, commonExtension->RemoveTrackingUntrackedCount)); 00130 00131 KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, 00132 oldIrql); 00133 } 00134 else { 00135 PREMOVE_TRACKING_BLOCK *removeTrackingList = 00136 (PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList; 00137 00138 KIRQL oldIrql; 00139 00140 trackingBlock->Tag = Tag; 00141 00142 trackingBlock->File = File; 00143 trackingBlock->Line = Line; 00144 00145 KeQueryTickCount((&trackingBlock->TimeLocked)); 00146 00147 KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, 00148 &oldIrql); 00149 00150 while(*removeTrackingList != NULL) { 00151 00152 if((*removeTrackingList)->Tag > Tag) { 00153 break; 00154 } 00155 00156 if((*removeTrackingList)->Tag == Tag) { 00157 00158 DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: " 00159 "already tracking Tag %p\n", Tag)); 00160 DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: " 00161 "acquired in file %s on line %d\n", 00162 (*removeTrackingList)->File, 00163 (*removeTrackingList)->Line)); 00164 ASSERT(FALSE); 00165 } 00166 00167 removeTrackingList = &((*removeTrackingList)->NextBlock); 00168 } 00169 00170 trackingBlock->NextBlock = *removeTrackingList; 00171 *removeTrackingList = trackingBlock; 00172 00173 KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, 00174 oldIrql); 00175 00176 } 00177 } 00178 00179 #endif 00180 00181 return (commonExtension->IsRemoved); 00182 } 00183 00184 /*++//////////////////////////////////////////////////////////////////////////// 00185 00186 ClassReleaseRemoveLock() 00187 00188 Routine Description: 00189 00190 This routine is called to release the remove lock on the device object. It 00191 must be called when finished using a previously locked reference to the 00192 device object. If an Tag was specified when acquiring the lock then the 00193 same Tag must be specified when releasing the lock. 00194 00195 When the lock count reduces to zero, this routine will signal the waiting 00196 remove Tag to delete the device object. As a result the DeviceObject 00197 pointer should not be used again once the lock has been released. 00198 00199 Arguments: 00200 00201 DeviceObject - the device object to lock 00202 00203 Tag - The irp (if any) specified when acquiring the lock. This is used 00204 for lock tracking purposes 00205 00206 Return Value: 00207 00208 none 00209 00210 --*/ 00211 VOID 00212 ClassReleaseRemoveLock( 00213 IN PDEVICE_OBJECT DeviceObject, 00214 IN OPTIONAL PIRP Tag 00215 ) 00216 { 00217 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 00218 LONG lockValue; 00219 00220 #if DBG 00221 PREMOVE_TRACKING_BLOCK *listEntry = 00222 (PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList; 00223 00224 BOOLEAN found = FALSE; 00225 00226 LONGLONG maxCount; 00227 00228 BOOLEAN isRemoved = (commonExtension->IsRemoved == REMOVE_COMPLETE); 00229 00230 KIRQL oldIrql; 00231 00232 if(isRemoved) { 00233 DBGTRAP(("ClassReleaseRemoveLock: REMOVE_COMPLETE set; this should never happen")); 00234 InterlockedDecrement(&(commonExtension->RemoveLock)); 00235 return; 00236 } 00237 00238 // 00239 // Check the tick count and make sure this thing hasn't been locked 00240 // for more than MaxLockedMinutes. 00241 // 00242 00243 maxCount = KeQueryTimeIncrement() * 10; // microseconds 00244 maxCount *= 1000; // milliseconds 00245 maxCount *= 1000; // seconds 00246 maxCount *= 60; // minutes 00247 maxCount *= MaxLockedMinutes; 00248 00249 DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " 00250 "maxCount = %0I64x\n", maxCount)); 00251 00252 KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, 00253 &oldIrql); 00254 00255 while(*listEntry != NULL) { 00256 00257 PREMOVE_TRACKING_BLOCK block; 00258 LARGE_INTEGER difference; 00259 00260 block = *listEntry; 00261 00262 KeQueryTickCount((&difference)); 00263 00264 difference.QuadPart -= block->TimeLocked.QuadPart; 00265 00266 DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " 00267 "Object %p (tag %p) locked for %I64d ticks\n", 00268 DeviceObject, block->Tag, difference.QuadPart)); 00269 00270 if(difference.QuadPart >= maxCount) { 00271 00272 DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " 00273 "Object %p (tag %p) locked for %I64d ticks - TOO LONG\n", 00274 DeviceObject, block->Tag, difference.QuadPart)); 00275 DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " 00276 "Lock acquired in file %s on line %d\n", 00277 block->File, block->Line)); 00278 ASSERT(FALSE); 00279 } 00280 00281 if((found == FALSE) && ((*listEntry)->Tag == Tag)) { 00282 00283 *listEntry = block->NextBlock; 00284 ExFreePool(block); 00285 found = TRUE; 00286 00287 } else { 00288 00289 listEntry = &((*listEntry)->NextBlock); 00290 00291 } 00292 } 00293 00294 if(!found) { 00295 if(commonExtension->RemoveTrackingUntrackedCount == 0) { 00296 DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " 00297 "Couldn't find Tag %p in the lock tracking list\n", 00298 Tag)); 00299 ASSERT(FALSE); 00300 } else { 00301 DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: " 00302 "Couldn't find Tag %p in the lock tracking list - " 00303 "may be one of the %d untracked requests still " 00304 "outstanding\n", 00305 Tag, 00306 commonExtension->RemoveTrackingUntrackedCount)); 00307 00308 commonExtension->RemoveTrackingUntrackedCount--; 00309 ASSERT(commonExtension->RemoveTrackingUntrackedCount >= 0); 00310 } 00311 } 00312 00313 KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, 00314 oldIrql); 00315 00316 #endif 00317 00318 lockValue = InterlockedDecrement(&commonExtension->RemoveLock); 00319 00320 DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " 00321 "Released for Object %p & irp %p - count is %d\n", 00322 DeviceObject, Tag, lockValue)); 00323 00324 ASSERT(lockValue >= 0); 00325 00326 ASSERTMSG("RemoveLock decreased to meet LockLowWatermark", 00327 ((LockLowWatermark == 0) || !(lockValue == LockLowWatermark))); 00328 00329 if(lockValue == 0) { 00330 00331 ASSERT(commonExtension->IsRemoved); 00332 00333 // 00334 // The device needs to be removed. Signal the remove event 00335 // that it's safe to go ahead. 00336 // 00337 00338 DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: " 00339 "Release for object %p & irp %p caused lock to go to zero\n", 00340 DeviceObject, Tag)); 00341 00342 KeSetEvent(&commonExtension->RemoveEvent, 00343 IO_NO_INCREMENT, 00344 FALSE); 00345 00346 } 00347 return; 00348 } 00349 00350 /*++//////////////////////////////////////////////////////////////////////////// 00351 00352 ClassCompleteRequest() 00353 00354 Routine Description: 00355 00356 This routine is a wrapper around (and should be used instead of) 00357 IoCompleteRequest. It is used primarily for debugging purposes. 00358 The routine will assert if the Irp being completed is still holding 00359 the release lock. 00360 00361 Arguments: 00362 00363 DeviceObject - the device object that was handling this request 00364 00365 Irp - the irp to be completed by IoCompleteRequest 00366 00367 PriorityBoost - the priority boost to pass to IoCompleteRequest 00368 00369 Return Value: 00370 00371 none 00372 00373 --*/ 00374 VOID 00375 ClassCompleteRequest( 00376 IN PDEVICE_OBJECT DeviceObject, 00377 IN PIRP Irp, 00378 IN CCHAR PriorityBoost 00379 ) 00380 { 00381 00382 #if DBG 00383 PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; 00384 PREMOVE_TRACKING_BLOCK *listEntry = 00385 (PREMOVE_TRACKING_BLOCK*)&commonExtension->RemoveTrackingList; 00386 00387 KIRQL oldIrql; 00388 00389 KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock, 00390 &oldIrql); 00391 00392 while(*listEntry != NULL) { 00393 00394 if((*listEntry)->Tag == Irp) { 00395 break; 00396 } 00397 00398 listEntry = &((*listEntry)->NextBlock); 00399 } 00400 00401 if(*listEntry != NULL) { 00402 00403 DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: " 00404 "Irp %p completed while still holding the remove lock\n", 00405 Irp)); 00406 DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: " 00407 "Lock acquired in file %s on line %d\n", 00408 (*listEntry)->File, (*listEntry)->Line)); 00409 ASSERT(FALSE); 00410 } 00411 00412 KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql); 00413 #endif 00414 00415 IoCompleteRequest(Irp, PriorityBoost); 00416 return; 00417 } // end ClassCompleteRequest() 00418 Generated on Sat May 26 2012 04:22:58 for ReactOS by
1.7.6.1
|