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

remlock.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 00005 Module Name: 00006 00007 remlock.c 00008 00009 Abstract: 00010 00011 This is the NT SCSI port driver. 00012 00013 Authors: 00014 00015 Peter Wieland 00016 Kenneth Ray 00017 00018 Environment: 00019 00020 kernel mode only 00021 00022 Notes: 00023 00024 This module is a driver dll for scsi miniports. 00025 00026 Revision History: 00027 00028 --*/ 00029 00030 #include <nt.h> 00031 #include <ntrtl.h> 00032 #include <ntos.h> 00033 00034 #include <remlock.h> 00035 00036 #define MinutesToTicks(x) \ 00037 (ULONGLONG) KeQueryTimeIncrement() * \ 00038 10 * \ 00039 1000 * \ 00040 1000 * \ 00041 60 * \ 00042 x 00043 // 10 -> microseconds, 1000 -> miliseconds, 1000 -> seconds, 60 -> minutes 00044 00045 // LIST_ENTRY RtlpRemoveLockList; 00046 00047 NTSYSAPI 00048 PRTL_REMOVE_LOCK 00049 NTAPI 00050 RtlAllocateRemoveLock( 00051 IN ULONG MaxLockedMinutes, 00052 IN ULONG AllocateTag, 00053 IN ULONG HighWatermark 00054 ) 00055 /*++ 00056 00057 Routine Description: 00058 00059 This routine is called to initialize the remove lock for a device object. 00060 00061 --*/ 00062 { 00063 PRTL_REMOVE_LOCK lock; 00064 00065 lock = ExAllocatePoolWithTag (NonPagedPool, 00066 sizeof (RTL_REMOVE_LOCK), 00067 AllocateTag); 00068 00069 if (lock) { 00070 00071 lock->Signature = RTL_REMOVE_LOCK_SIG; 00072 lock->Removed = FALSE; 00073 lock->IoCount = 1; 00074 KeInitializeEvent(&lock->RemoveEvent, SynchronizationEvent, FALSE); 00075 #if DBG 00076 lock->HighWatermark = HighWatermark; 00077 lock->MaxLockedMinutes = MaxLockedMinutes; 00078 lock->AllocateTag = AllocateTag; 00079 KeInitializeSpinLock (&lock->Spin); 00080 lock->Blocks.Link = NULL; 00081 #endif 00082 } 00083 00084 return lock; 00085 } 00086 00087 00088 NTSYSAPI 00089 NTSTATUS 00090 NTAPI 00091 RtlAcquireRemoveLockEx( 00092 IN PRTL_REMOVE_LOCK RemoveLock, 00093 IN OPTIONAL PVOID Tag, 00094 IN PCSTR File, 00095 IN ULONG Line 00096 ) 00097 00098 /*++ 00099 00100 Routine Description: 00101 00102 This routine is called to acquire the remove lock for a device object. 00103 While the lock is held, the caller can assume that no pending pnp REMOVE 00104 requests will be completed. 00105 00106 The lock should be acquired immediately upon entering a dispatch routine. 00107 It should also be acquired before creating any new reference to the 00108 device object if there's a chance of releasing the reference before the 00109 new one is done. 00110 00111 Arguments: 00112 00113 RemoveLock - A pointer to an initialized REMOVE_LOCK structure. 00114 00115 Tag - Used for tracking lock allocation and release. If an irp is 00116 specified when acquiring the lock then the same Tag must be 00117 used to release the lock before the Tag is completed. 00118 00119 File - set to __FILE__ as the location in the code where the lock was taken. 00120 00121 Line - set to __LINE__. 00122 00123 Return Value: 00124 00125 Returns whether or not the remove lock was obtained. 00126 If successful the caller should continue with work calling 00127 RtlReleaseRemoveLock when finished. 00128 00129 If not successful the lock was not obtained. The caller should abort the 00130 work but not call RtlReleaseRemoveLock. 00131 00132 --*/ 00133 00134 { 00135 LONG lockValue; 00136 NTSTATUS status; 00137 00138 #if DBG 00139 PRTL_REMOVE_LOCK_TRACKING_BLOCK trackingBlock; 00140 #endif 00141 00142 // 00143 // Grab the remove lock 00144 // 00145 00146 lockValue = InterlockedIncrement(&RemoveLock->IoCount); 00147 00148 ASSERTMSG("RtlAcquireRemoveLock - lock value was negative : ", 00149 (lockValue > 0)); 00150 00151 ASSERTMSG("RemoveLock increased to meet LockHighWatermark", 00152 ((0 == RemoveLock->HighWatermark) || 00153 (lockValue <= RemoveLock->HighWatermark))); 00154 00155 if (! RemoveLock->Removed) { 00156 00157 #if DBG 00158 trackingBlock = ExAllocatePoolWithTag( 00159 NonPagedPool, 00160 sizeof(RTL_REMOVE_LOCK_TRACKING_BLOCK), 00161 RemoveLock->AllocateTag); 00162 00163 RtlZeroMemory (trackingBlock, 00164 sizeof (RTL_REMOVE_LOCK_TRACKING_BLOCK)); 00165 00166 if (NULL == trackingBlock) { 00167 00168 ASSERTMSG ("insufficient resources", FALSE); 00169 00170 } else { 00171 00172 KIRQL oldIrql; 00173 00174 trackingBlock->Tag = Tag; 00175 trackingBlock->File = File; 00176 trackingBlock->Line = Line; 00177 00178 KeQueryTickCount(&trackingBlock->TimeLocked); 00179 00180 KeAcquireSpinLock (&RemoveLock->Spin, &oldIrql); 00181 trackingBlock->Link = RemoveLock->Blocks.Link; 00182 RemoveLock->Blocks.Link = trackingBlock; 00183 KeReleaseSpinLock(&RemoveLock->Spin, oldIrql); 00184 } 00185 #endif 00186 00187 status = STATUS_SUCCESS; 00188 00189 } else { 00190 00191 if (0 == InterlockedDecrement (&RemoveLock->IoCount)) { 00192 KeSetEvent (&RemoveLock->RemoveEvent, 0, FALSE); 00193 } 00194 status = STATUS_DELETE_PENDING; 00195 } 00196 00197 return status; 00198 } 00199 00200 00201 NTSYSAPI 00202 VOID 00203 NTAPI 00204 RtlReleaseRemoveLock( 00205 IN PRTL_REMOVE_LOCK RemoveLock, 00206 IN PVOID Tag 00207 ) 00208 00209 /*++ 00210 00211 Routine Description: 00212 00213 This routine is called to release the remove lock on the device object. It 00214 must be called when finished using a previously locked reference to the 00215 device object. If an Tag was specified when acquiring the lock then the 00216 same Tag must be specified when releasing the lock. 00217 00218 When the lock count reduces to zero, this routine will signal the waiting 00219 event to release the waiting thread deleting the device object protected 00220 by this lock. 00221 00222 Arguments: 00223 00224 DeviceObject - the device object to lock 00225 00226 Tag - The tag (if any) specified when acquiring the lock. This is used 00227 for lock tracking purposes 00228 00229 Return Value: 00230 00231 none 00232 00233 --*/ 00234 00235 { 00236 LONG lockValue; 00237 00238 #if DBG 00239 KIRQL oldIrql; 00240 LARGE_INTEGER difference; 00241 BOOLEAN found; 00242 LONGLONG maxTime; 00243 00244 PRTL_REMOVE_LOCK_TRACKING_BLOCK last; 00245 PRTL_REMOVE_LOCK_TRACKING_BLOCK current; 00246 00247 // 00248 // Check the tick count and make sure this thing hasn't been locked 00249 // for more than MaxLockedMinutes. 00250 // 00251 00252 found = FALSE; 00253 KeAcquireSpinLock(&RemoveLock->Spin, &oldIrql); 00254 last = (&RemoveLock->Blocks); 00255 current = last->Link; 00256 // 00257 // Note the first one is the sentinal 00258 // 00259 00260 while (NULL != current) { 00261 00262 KeQueryTickCount((&difference)); 00263 difference.QuadPart -= current->TimeLocked.QuadPart; 00264 maxTime = MinutesToTicks (RemoveLock->MaxLockedMinutes); 00265 00266 if (maxTime && (maxTime < difference.QuadPart)) { 00267 00268 KdPrint(("RtlReleaseRemoveLock: Lock %#08lx (tag %#08lx) locked " 00269 "for %I64d ticks - TOO LONG\n", 00270 RemoveLock, 00271 current->Tag, 00272 difference.QuadPart)); 00273 00274 KdPrint(("RtlReleaseRemoveLock: Lock acquired in file " 00275 "%s on line %d\n", 00276 current->File, 00277 current->Line)); 00278 ASSERT(FALSE); 00279 } 00280 00281 if ((!found) && (current->Tag == Tag)) { 00282 found = TRUE; 00283 last->Link = current->Link; 00284 ExFreePool (current); 00285 current = last->Link; 00286 continue; 00287 } 00288 00289 last = current; 00290 current = current->Link; 00291 } 00292 00293 KeReleaseSpinLock(&RemoveLock->Spin, oldIrql); 00294 00295 if (!found) { 00296 00297 KdPrint (("RtlReleaseRemoveLock: Couldn't find Tag %#08lx " 00298 "in the lock tracking list\n", 00299 Tag)); 00300 ASSERT(FALSE); 00301 } 00302 #endif 00303 00304 lockValue = InterlockedDecrement(&RemoveLock->IoCount); 00305 00306 ASSERT(0 <= lockValue); 00307 00308 if (0 == lockValue) { 00309 00310 ASSERT (RemoveLock->Removed); 00311 00312 // 00313 // The device needs to be removed. Signal the remove event 00314 // that it's safe to go ahead. 00315 // 00316 00317 KeSetEvent(&RemoveLock->RemoveEvent, 00318 IO_NO_INCREMENT, 00319 FALSE); 00320 } 00321 return; 00322 } 00323 00324 00325 NTSYSAPI 00326 VOID 00327 NTAPI 00328 RtlReleaseRemoveLockAndWait ( 00329 IN PRTL_REMOVE_LOCK RemoveLock, 00330 IN PVOID Tag 00331 ) 00332 00333 /*++ 00334 00335 Routine Description: 00336 00337 This routine is called when the client would like to delete the remove- 00338 locked resource. 00339 This routine will block until all the remove locks have completed. 00340 00341 This routine MUST be called after acquiring once more the lock. 00342 00343 Arguments: 00344 00345 RemoveLock - 00346 00347 Return Value: 00348 00349 none 00350 00351 --*/ 00352 { 00353 LONG ioCount; 00354 00355 PAGED_CODE (); 00356 00357 RemoveLock->Removed = TRUE; 00358 00359 ioCount = InterlockedDecrement (&RemoveLock->IoCount); 00360 ASSERT (0 < ioCount); 00361 00362 if (0 < InterlockedDecrement (&RemoveLock->IoCount)) { 00363 KeWaitForSingleObject (&RemoveLock->RemoveEvent, 00364 Executive, 00365 KernelMode, 00366 FALSE, 00367 NULL); 00368 } 00369 00370 #if DBG 00371 ASSERT (RemoveLock->Blocks.Link); 00372 if (Tag != RemoveLock->Blocks.Link->Tag) { 00373 KdPrint (("RtlRelaseRemoveLockAndWait last tag invalid %x %x\n", 00374 Tag, 00375 RemoveLock->Blocks.Link->Tag)); 00376 00377 ASSERT (Tag != RemoveLock->Blocks.Link->Tag); 00378 } 00379 00380 ExFreePool (RemoveLock->Blocks.Link); 00381 #endif 00382 00383 } 00384 00385

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