- Lock only the object header for an object instead of the entire object type, for better contention. Implement exclusive/shared lock and release routines around the existing lock slots in the object type (this allows up to 4 different objects to be locked in the same time, instead of locking the entire type).

- Thanks to Alex for reporting this.

svn path=/trunk/; revision=32812
This commit is contained in:
Aleksey Bragin 2008-04-01 20:07:36 +00:00
parent 24e07f0eac
commit 1417fd5fa6
5 changed files with 86 additions and 26 deletions

View file

@ -15,6 +15,68 @@
#define OBP_LOCK_STATE_RELEASED 0xEEEE1234 #define OBP_LOCK_STATE_RELEASED 0xEEEE1234
#define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234 #define OBP_LOCK_STATE_INITIALIZED 0xFFFF1234
ULONG
FORCEINLINE
ObpSelectObjectLockSlot(IN POBJECT_HEADER ObjectHeader)
{
/* We have 4 locks total, this will return a 0-index slot */
return (((ULONG_PTR)ObjectHeader) >> 8) & 3;
}
VOID
FORCEINLINE
ObpAcquireObjectLock(IN POBJECT_HEADER ObjectHeader)
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
/* Enter a critical region and acquire the resource */
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&ObjectType->ObjectLocks[Slot], TRUE);
}
VOID
FORCEINLINE
ObpAcquireObjectLockShared(IN POBJECT_HEADER ObjectHeader)
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
/* Enter a critical region and acquire the resource */
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&ObjectType->ObjectLocks[Slot], TRUE);
}
VOID
FORCEINLINE
ObpReleaseObjectLock(IN POBJECT_HEADER ObjectHeader)
{
ULONG Slot;
POBJECT_TYPE ObjectType = ObjectHeader->Type;
/* Pick a slot */
Slot = ObpSelectObjectLockSlot(ObjectHeader);
/* Enter a critical region and acquire the resource */
ExReleaseResourceLite(&ObjectType->ObjectLocks[Slot]);
KeLeaveCriticalRegion();
/* Sanity check */
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
}
POBJECT_HEADER_NAME_INFO POBJECT_HEADER_NAME_INFO
FORCEINLINE FORCEINLINE
ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader) ObpAcquireNameInformation(IN POBJECT_HEADER ObjectHeader)

View file

@ -495,8 +495,8 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
ObjectHeader->HandleCount, ObjectHeader->HandleCount,
ObjectHeader->PointerCount); ObjectHeader->PointerCount);
/* Lock the object type */ /* Lock the object */
ObpEnterObjectTypeMutex(ObjectType); ObpAcquireObjectLock(ObjectHeader);
/* Set default counts */ /* Set default counts */
SystemHandleCount = ObjectHeader->HandleCount; SystemHandleCount = ObjectHeader->HandleCount;
@ -571,7 +571,7 @@ ObpDecrementHandleCount(IN PVOID ObjectBody,
} }
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
/* Check if we have a close procedure */ /* Check if we have a close procedure */
if (ObjectType->TypeInfo.CloseProcedure) if (ObjectType->TypeInfo.CloseProcedure)
@ -796,8 +796,8 @@ ObpIncrementHandleCount(IN PVOID Object,
ProbeMode = AccessMode; ProbeMode = AccessMode;
} }
/* Lock the object type */ /* Lock the object */
ObpEnterObjectTypeMutex(ObjectType); ObpAcquireObjectLock(ObjectHeader);
/* Charge quota and remove the creator info flag */ /* Charge quota and remove the creator info flag */
Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject);
@ -922,7 +922,7 @@ ObpIncrementHandleCount(IN PVOID Object,
} }
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
/* Check if we have an open procedure */ /* Check if we have an open procedure */
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
@ -988,7 +988,7 @@ ObpIncrementHandleCount(IN PVOID Object,
Quickie: Quickie:
/* Release lock and return */ /* Release lock and return */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
return Status; return Status;
} }
@ -1049,7 +1049,7 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
ObjectHeader->PointerCount); ObjectHeader->PointerCount);
/* Lock the object type */ /* Lock the object type */
ObpEnterObjectTypeMutex(ObjectType); ObpAcquireObjectLock(ObjectHeader);
/* Charge quota and remove the creator info flag */ /* Charge quota and remove the creator info flag */
Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject); Status = ObpChargeQuotaForObject(ObjectHeader, ObjectType, &NewObject);
@ -1149,7 +1149,7 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
} }
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
/* Check if we have an open procedure */ /* Check if we have an open procedure */
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
@ -1207,7 +1207,7 @@ ObpIncrementUnnamedHandleCount(IN PVOID Object,
Quickie: Quickie:
/* Release lock and return */ /* Release lock and return */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
return Status; return Status;
} }
@ -3093,8 +3093,8 @@ ObInsertObject(IN PVOID Object,
} }
else else
{ {
/* Otherwise, lock the object type */ /* Otherwise, lock the object */
ObpEnterObjectTypeMutex(ObjectType); ObpAcquireObjectLock(ObjectHeader);
/* And charge quota for the process to make it appear as used */ /* And charge quota for the process to make it appear as used */
RealStatus = ObpChargeQuotaForObject(ObjectHeader, RealStatus = ObpChargeQuotaForObject(ObjectHeader,
@ -3102,7 +3102,7 @@ ObInsertObject(IN PVOID Object,
&IsNewObject); &IsNewObject);
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
/* Check if we failed and dereference the object if so */ /* Check if we failed and dereference the object if so */
if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object); if (!NT_SUCCESS(RealStatus)) ObDereferenceObject(Object);

View file

@ -262,8 +262,8 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
/* Get the header */ /* Get the header */
ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody); ObjectHeader = OBJECT_TO_OBJECT_HEADER(ObjectBody);
/* Acquire object type lock */ /* Acquire object lock */
ObpEnterObjectTypeMutex(ObjectHeader->Type); ObpAcquireObjectLock(ObjectHeader);
/* Check what we're doing to it */ /* Check what we're doing to it */
if (Permanent) if (Permanent)
@ -272,7 +272,7 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
ObjectHeader->Flags |= OB_FLAG_PERMANENT; ObjectHeader->Flags |= OB_FLAG_PERMANENT;
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectHeader->Type); ObpReleaseObjectLock(ObjectHeader);
} }
else else
{ {
@ -280,7 +280,7 @@ ObpSetPermanentObject(IN PVOID ObjectBody,
ObjectHeader->Flags &= ~OB_FLAG_PERMANENT; ObjectHeader->Flags &= ~OB_FLAG_PERMANENT;
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectHeader->Type); ObpReleaseObjectLock(ObjectHeader);
/* Check if we should delete the object now */ /* Check if we should delete the object now */
ObpDeleteNameCheck(ObjectBody); ObpDeleteNameCheck(ObjectBody);

View file

@ -503,9 +503,8 @@ NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
NULL); NULL);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Lock the object type */ /* Lock the object */
KeEnterCriticalRegion(); ObpAcquireObjectLock(OBJECT_TO_OBJECT_HEADER(SymlinkObject));
ExAcquireResourceExclusiveLite(&ObSymbolicLinkType->Mutex, TRUE);
/* /*
* So here's the thing: If you specify a return length, then the * So here's the thing: If you specify a return length, then the
@ -549,9 +548,8 @@ NtQuerySymbolicLinkObject(IN HANDLE LinkHandle,
} }
_SEH_END; _SEH_END;
/* Unlock the object type and reference the object */ /* Unlock the object and reference the object */
ExReleaseResourceLite(&ObSymbolicLinkType->Mutex); ObpReleaseObjectLock(OBJECT_TO_OBJECT_HEADER(SymlinkObject));
KeLeaveCriticalRegion();
ObDereferenceObject(SymlinkObject); ObDereferenceObject(SymlinkObject);
} }

View file

@ -206,8 +206,8 @@ ObpDeleteNameCheck(IN PVOID Object)
&Context); &Context);
if (Object) if (Object)
{ {
/* Lock the object type */ /* Lock the object */
ObpEnterObjectTypeMutex(ObjectType); ObpAcquireObjectLock(ObjectHeader);
/* Make sure we can still delete the object */ /* Make sure we can still delete the object */
if (!(ObjectHeader->HandleCount) && if (!(ObjectHeader->HandleCount) &&
@ -238,7 +238,7 @@ ObpDeleteNameCheck(IN PVOID Object)
} }
/* Release the lock */ /* Release the lock */
ObpLeaveObjectTypeMutex(ObjectType); ObpReleaseObjectLock(ObjectHeader);
} }
/* Cleanup after lookup */ /* Cleanup after lookup */