示例#1
0
文件: remlock.c 项目: mingpen/OpenNT
NTSYSAPI
VOID
NTAPI
IoInitializeRemoveLockEx(
    IN  PIO_REMOVE_LOCK PublicLock,
    IN  ULONG   AllocateTag, // Used only on checked kernels
    IN  ULONG   MaxLockedMinutes, // Used only on checked kernels
    IN  ULONG   HighWatermark, // Used only on checked kernels
    IN  ULONG   RemlockSize // are we checked or free
    )
/*++

Routine Description:

    This routine is called to initialize the remove lock for a device object.

--*/
{
    PIO_PRIVATE_REMOVE_LOCK Lock = (PIO_PRIVATE_REMOVE_LOCK) PublicLock;

    PAGED_CODE ();

    if (Lock) {

        switch (RemlockSize) {

        case CHECKEDSIZE:
            Lock->Dbg.Signature = IO_REMOVE_LOCK_SIG;
            Lock->Dbg.HighWatermark = HighWatermark;
            Lock->Dbg.MaxLockedTicks = MinutesToTicks (MaxLockedMinutes);
            Lock->Dbg.AllocateTag = AllocateTag;
            KeInitializeSpinLock (&Lock->Dbg.Spin);
            Lock->Dbg.LowMemoryCount = 0;
            Lock->Dbg.Blocks = NULL;

            //
            // fall through
            //
        case FREESIZE:
            Lock->Common.Removed = FALSE;
            Lock->Common.IoCount = 1;
            KeInitializeEvent(&Lock->Common.RemoveEvent,
                              SynchronizationEvent,
                              FALSE);
            break;

        default:
            break;
        }
    }
}
示例#2
0
NTSYSAPI
VOID
NTAPI
RtlReleaseRemoveLock(
    IN PRTL_REMOVE_LOCK RemoveLock,
    IN PVOID            Tag
    )

/*++

Routine Description:

    This routine is called to release the remove lock on the device object.  It
    must be called when finished using a previously locked reference to the
    device object.  If an Tag was specified when acquiring the lock then the
    same Tag must be specified when releasing the lock.

    When the lock count reduces to zero, this routine will signal the waiting
    event to release the waiting thread deleting the device object protected
    by this lock.

Arguments:

    DeviceObject - the device object to lock

    Tag - The tag (if any) specified when acquiring the lock.  This is used
          for lock tracking purposes

Return Value:

    none

--*/

{
    LONG            lockValue;

#if DBG
    KIRQL           oldIrql;
    LARGE_INTEGER   difference;
    BOOLEAN         found;
    LONGLONG        maxTime;

    PRTL_REMOVE_LOCK_TRACKING_BLOCK last;
    PRTL_REMOVE_LOCK_TRACKING_BLOCK current;

    //
    // Check the tick count and make sure this thing hasn't been locked
    // for more than MaxLockedMinutes.
    //

    found = FALSE;
    KeAcquireSpinLock(&RemoveLock->Spin, &oldIrql);
    last = (&RemoveLock->Blocks);
    current = last->Link;
    //
    // Note the first one is the sentinal
    //

    while (NULL != current) {

        KeQueryTickCount((&difference));
        difference.QuadPart -= current->TimeLocked.QuadPart;
        maxTime = MinutesToTicks (RemoveLock->MaxLockedMinutes);

        if (maxTime && (maxTime < difference.QuadPart)) {

            KdPrint(("RtlReleaseRemoveLock: Lock %#08lx (tag %#08lx) locked "
                     "for %I64d ticks - TOO LONG\n",
                     RemoveLock,
                     current->Tag,
                     difference.QuadPart));

            KdPrint(("RtlReleaseRemoveLock: Lock acquired in file "
                     "%s on line %d\n",
                     current->File,
                     current->Line));
            ASSERT(FALSE);
        }

        if ((!found) && (current->Tag == Tag)) {
            found = TRUE;
            last->Link = current->Link;
            ExFreePool (current);
                          current = last->Link;
            continue;
        }

        last = current;
        current = current->Link;
    }

    KeReleaseSpinLock(&RemoveLock->Spin, oldIrql);

    if (!found) {

        KdPrint (("RtlReleaseRemoveLock: Couldn't find Tag %#08lx "
                  "in the lock tracking list\n",
                  Tag));
        ASSERT(FALSE);
    }
#endif

    lockValue = InterlockedDecrement(&RemoveLock->IoCount);

    ASSERT(0 <= lockValue);

    if (0 == lockValue) {

        ASSERT (RemoveLock->Removed);

        //
        // The device needs to be removed.  Signal the remove event
        // that it's safe to go ahead.
        //

        KeSetEvent(&RemoveLock->RemoveEvent,
                   IO_NO_INCREMENT,
                   FALSE);
    }
    return;
}