Author: fireball Date: Wed Mar 4 23:58:32 2009 New Revision: 39876
URL: http://svn.reactos.org/svn/reactos?rev=39876&view=rev Log: - Make TOKEN pointer in OBJECT_HEADER a fast reference, just like on Windows. - Update SD cache code to treat it as such. - Improves performance by 500% during security checks - noticeable impact during large file or registry transfer operations.
Modified: trunk/reactos/ntoskrnl/ob/obsdcach.c trunk/reactos/ntoskrnl/ob/obsecure.c
Modified: trunk/reactos/ntoskrnl/ob/obsdcach.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsdcach.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obsdcach.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ob/obsdcach.c [iso-8859-1] Wed Mar 4 23:58:32 2009 @@ -181,24 +181,51 @@ { PSECURITY_DESCRIPTOR SecurityDescriptor; PSECURITY_DESCRIPTOR_HEADER SdHeader; - - /* Get the SD */ - SecurityDescriptor = ObjectHeader->SecurityDescriptor; - if (!SecurityDescriptor) - { - /* No SD, nothing to do */ - return NULL; - } - + PEX_FAST_REF FastRef; + EX_FAST_REF OldValue; + ULONG_PTR Count; + + /* Acquire a reference to the security descriptor */ + FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor; + OldValue = ExAcquireFastReference(FastRef); + + /* Get the descriptor and reference count */ + SecurityDescriptor = ExGetObjectFastReference(OldValue); + Count = ExGetCountFastReference(OldValue); + + /* Check if there's no descriptor or if there's still cached references */ + if ((Count >= 1) || !(SecurityDescriptor)) + { + /* Check if this is the last reference */ + if (Count == 1) + { + /* Add the extra references that we'll take */ + SdHeader = ObpGetHeaderForSd(SecurityDescriptor); + InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, MAX_FAST_REFS); + + /* Now insert them */ + if (!ExInsertFastReference(FastRef, SecurityDescriptor)) + { + /* Undo the references since we failed */ + InterlockedExchangeAdd((PLONG)&SdHeader->RefCount, + -MAX_FAST_REFS); + } + } + + /* Return the SD */ + return SecurityDescriptor; + } + /* Lock the object */ ObpAcquireObjectLockShared(ObjectHeader); - + /* Get the object header */ + SecurityDescriptor = ExGetObjectFastReference(*FastRef); SdHeader = ObpGetHeaderForSd(SecurityDescriptor); - + /* Do the reference */ InterlockedIncrement((PLONG)&SdHeader->RefCount); - + /* Release the lock and return */ ObpReleaseObjectLock(ObjectHeader); return SecurityDescriptor;
Modified: trunk/reactos/ntoskrnl/ob/obsecure.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obsecure.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ob/obsecure.c [iso-8859-1] Wed Mar 4 23:58:32 2009 @@ -24,19 +24,23 @@ POBJECT_HEADER ObjectHeader; NTSTATUS Status; PSECURITY_DESCRIPTOR NewSd; + PEX_FAST_REF FastRef; PAGED_CODE();
/* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); + FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor; if (!SecurityDescriptor) { /* Nothing to assign */ - ObjectHeader->SecurityDescriptor = NULL; + ExInitializeFastReference(FastRef, NULL); return STATUS_SUCCESS; }
/* Add it to our internal cache */ - Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, 1); + Status = ObLogSecurityDescriptor(SecurityDescriptor, + &NewSd, + MAX_FAST_REFS + 1); if (NT_SUCCESS(Status)) { /* Free the old copy */ @@ -44,7 +48,7 @@
/* Set the new pointer */ ASSERT(NewSd); - ObjectHeader->SecurityDescriptor = NewSd; + ExInitializeFastReference(FastRef, NewSd); }
/* Return status */ @@ -55,11 +59,22 @@ NTAPI ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor) { - /* Dereference it */ - ObDereferenceSecurityDescriptor(*SecurityDescriptor, 1); - + EX_FAST_REF FastRef; + ULONG_PTR Count; + PSECURITY_DESCRIPTOR OldSecurityDescriptor; + + /* Get the fast reference and capture it */ + FastRef = *(PEX_FAST_REF)SecurityDescriptor; + /* Don't free again later */ *SecurityDescriptor = NULL; + + /* Get the descriptor and reference count */ + OldSecurityDescriptor = ExGetObjectFastReference(FastRef); + Count = ExGetCountFastReference(FastRef); + + /* Dereference the descriptor */ + ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1);
/* All done */ return STATUS_SUCCESS; @@ -109,6 +124,9 @@ NTSTATUS Status; POBJECT_HEADER ObjectHeader; PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor; + PEX_FAST_REF FastRef; + EX_FAST_REF OldValue; + ULONG_PTR Count; PAGED_CODE();
/* Get the object header */ @@ -129,7 +147,9 @@ if (NT_SUCCESS(Status)) { /* Now add this to the cache */ - Status = ObLogSecurityDescriptor(NewDescriptor, &CachedDescriptor, 1); + Status = ObLogSecurityDescriptor(NewDescriptor, + &CachedDescriptor, + MAX_FAST_REFS + 1);
/* Let go of our uncached copy */ ExFreePool(NewDescriptor); @@ -137,15 +157,34 @@ /* Check for success */ if (NT_SUCCESS(Status)) { - /* Dereference the old one */ - ASSERT(OldDescriptor == ObjectHeader->SecurityDescriptor); - - /* Now set this as the new descriptor */ - ObjectHeader->SecurityDescriptor = CachedDescriptor; - - /* And dereference the old one */ - ObDereferenceSecurityDescriptor(OldDescriptor, 1); - break; + /* Do the swap */ + FastRef = (PEX_FAST_REF)OutputSecurityDescriptor; + OldValue = ExCompareSwapFastReference(FastRef, + CachedDescriptor, + OldDescriptor); + + /* Get the security descriptor */ + SecurityDescriptor = ExGetObjectFastReference(OldValue); + Count = ExGetCountFastReference(OldValue); + + /* Make sure the swap worked */ + if (SecurityDescriptor == OldDescriptor) + { + /* Flush waiters */ + ObpAcquireObjectLock(ObjectHeader); + ObpReleaseObjectLock(ObjectHeader); + + /* And dereference the old one */ + ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2); + break; + } + else + { + /* Someone changed it behind our back -- try again */ + ObDereferenceSecurityDescriptor(OldDescriptor, 1); + ObDereferenceSecurityDescriptor(CachedDescriptor, + MAX_FAST_REFS + 1); + } } else {