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

remlock.c File Reference

#include <nt.h>
#include <ntrtl.h>
#include <ntos.h>
#include <remlock.h>

Go to the source code of this file.

Defines

#define MinutesToTicks(x)

Functions

NTSYSAPI PRTL_REMOVE_LOCK
NTAPI 
RtlAllocateRemoveLock (IN ULONG MaxLockedMinutes, IN ULONG AllocateTag, IN ULONG HighWatermark)
NTSYSAPI NTSTATUS NTAPI RtlAcquireRemoveLockEx (IN PRTL_REMOVE_LOCK RemoveLock, IN OPTIONAL PVOID Tag, IN PCSTR File, IN ULONG Line)
NTSYSAPI VOID NTAPI RtlReleaseRemoveLock (IN PRTL_REMOVE_LOCK RemoveLock, IN PVOID Tag)
NTSYSAPI VOID NTAPI RtlReleaseRemoveLockAndWait (IN PRTL_REMOVE_LOCK RemoveLock, IN PVOID Tag)


Define Documentation

#define MinutesToTicks  ) 
 

Value:

(ULONGLONG) KeQueryTimeIncrement() * \ 10 * \ 1000 * \ 1000 * \ 60 * \ x

Definition at line 36 of file rtl/remlock.c.


Function Documentation

NTSYSAPI NTSTATUS NTAPI RtlAcquireRemoveLockEx IN PRTL_REMOVE_LOCK  RemoveLock,
IN OPTIONAL PVOID  Tag,
IN PCSTR  File,
IN ULONG  Line
 

Definition at line 91 of file rtl/remlock.c.

References ASSERTMSG, ExAllocatePoolWithTag, FALSE, File, KeAcquireSpinLock, KeQueryTickCount(), KeReleaseSpinLock(), KeSetEvent(), NonPagedPool, NTSTATUS(), and NULL.

00100 : 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 }

NTSYSAPI PRTL_REMOVE_LOCK NTAPI RtlAllocateRemoveLock IN ULONG  MaxLockedMinutes,
IN ULONG  AllocateTag,
IN ULONG  HighWatermark
 

Definition at line 50 of file rtl/remlock.c.

References ExAllocatePoolWithTag, FALSE, _RTL_REMOVE_LOCK::IoCount, KeInitializeEvent, KeInitializeSpinLock(), NonPagedPool, NULL, _RTL_REMOVE_LOCK::Removed, _RTL_REMOVE_LOCK::RemoveEvent, RTL_REMOVE_LOCK, RTL_REMOVE_LOCK_SIG, and _RTL_REMOVE_LOCK::Signature.

00057 : 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 }

NTSYSAPI VOID NTAPI RtlReleaseRemoveLock IN PRTL_REMOVE_LOCK  RemoveLock,
IN PVOID  Tag
 

Definition at line 204 of file rtl/remlock.c.

References ASSERT, ExFreePool(), FALSE, IO_NO_INCREMENT, KeAcquireSpinLock, KeQueryTickCount(), KeReleaseSpinLock(), KeSetEvent(), MinutesToTicks, NULL, and TRUE.

00211 : 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 }

NTSYSAPI VOID NTAPI RtlReleaseRemoveLockAndWait IN PRTL_REMOVE_LOCK  RemoveLock,
IN PVOID  Tag
 

Definition at line 328 of file rtl/remlock.c.

References ASSERT, Executive, ExFreePool(), FALSE, KernelMode, KeWaitForSingleObject(), NULL, PAGED_CODE, and TRUE.

00335 : 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 }


Generated on Sat May 15 19:45:28 2004 for test by doxygen 1.3.7