ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

lock.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.