[ros-diffs] [fireball] 39876: - 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.

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Mar 4 21:58:33 CET 2009


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=39876&r1=39875&r2=39876&view=diff
==============================================================================
--- 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=39876&r1=39875&r2=39876&view=diff
==============================================================================
--- 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
             {



More information about the Ros-diffs mailing list