implemented sweeping of handle tables
[reactos.git] / reactos / ntoskrnl / ex / handle.c
index 21fe5f6..71ec925 100644 (file)
@@ -11,7 +11,6 @@
  *
  *  - the last entry of a subhandle list should be reserved for auditing
  *
- *  ExSweepHandleTable (???)
  *  ExReferenceHandleDebugInfo
  *  ExSnapShotHandleTables
  *  ExpMoveFreeHandles (???)
@@ -163,63 +162,12 @@ ExCreateHandleTable(IN PEPROCESS QuotaProcess  OPTIONAL)
   return HandleTable;
 }
 
-static BOOLEAN
-ExLockHandleTableEntryNoDestructionCheck(IN PHANDLE_TABLE HandleTable,
-                                         IN PHANDLE_TABLE_ENTRY Entry)
-{
-  ULONG_PTR Current, New;
-
-  PAGED_CODE();
-
-  DPRINT("Entering handle table entry 0x%p lock...\n", Entry);
-
-  ASSERT(HandleTable);
-  ASSERT(Entry);
-
-  for(;;)
-  {
-    Current = (volatile ULONG_PTR)Entry->u1.Object;
-
-    if(!Current)
-    {
-      DPRINT("Attempted to lock empty handle table entry 0x%p or handle table shut down\n", Entry);
-      break;
-    }
-
-    if(!(Current & EX_HANDLE_ENTRY_LOCKED))
-    {
-      New = Current | EX_HANDLE_ENTRY_LOCKED;
-      if(InterlockedCompareExchangePointer(&Entry->u1.Object,
-                                           (PVOID)New,
-                                           (PVOID)Current) == (PVOID)Current)
-      {
-        DPRINT("SUCCESS handle table 0x%p entry 0x%p lock\n", HandleTable, Entry);
-        /* we acquired the lock */
-        return TRUE;
-      }
-    }
-
-    /* wait about 5ms at maximum so we don't wait forever in unfortunate
-       co-incidences where releasing the lock in another thread happens right
-       before we're waiting on the contention event to get pulsed, which might
-       never happen again... */
-    KeWaitForSingleObject(&HandleTable->HandleContentionEvent,
-                          Executive,
-                          KernelMode,
-                          FALSE,
-                          &ExpHandleShortWait);
-  }
-
-  return FALSE;
-}
-
 VOID
-ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
-                     IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback  OPTIONAL,
-                     IN PVOID Context  OPTIONAL)
+ExSweepHandleTable(IN PHANDLE_TABLE HandleTable,
+                   IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback  OPTIONAL,
+                   IN PVOID Context  OPTIONAL)
 {
   PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
-  PEPROCESS QuotaProcess;
 
   PAGED_CODE();
 
@@ -238,38 +186,30 @@ ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
                EVENT_INCREMENT,
                FALSE);
 
-  /* remove the handle table from the global handle table list */
-  ExAcquireHandleTableListLock();
-  RemoveEntryList(&HandleTable->HandleTableList);
-  ExReleaseHandleTableListLock();
-
   /* call the callback function to cleanup the objects associated with the
      handle table */
-  if(DestroyHandleCallback != NULL)
+  for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
+      tlp != lasttlp;
+      tlp++)
   {
-    for(tlp = HandleTable->Table, lasttlp = HandleTable->Table + N_TOPLEVEL_POINTERS;
-        tlp != lasttlp;
-        tlp++)
+    if((*tlp) != NULL)
     {
-      if((*tlp) != NULL)
+      for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
+          mlp != lastmlp;
+          mlp++)
       {
-        for(mlp = *tlp, lastmlp = (*tlp) + N_MIDDLELEVEL_POINTERS;
-            mlp != lastmlp;
-            mlp++)
+        if((*mlp) != NULL)
         {
-          if((*mlp) != NULL)
-          {
-            PHANDLE_TABLE_ENTRY curee, laste;
+          PHANDLE_TABLE_ENTRY curee, laste;
 
-            for(curee = *mlp, laste = *mlp + N_SUBHANDLE_ENTRIES;
-                curee != laste;
-                curee++)
+          for(curee = *mlp, laste = *mlp + N_SUBHANDLE_ENTRIES;
+              curee != laste;
+              curee++)
+          {
+            if(curee->u1.Object != NULL && SweepHandleCallback != NULL)
             {
-              if(curee->u1.Object != NULL && ExLockHandleTableEntryNoDestructionCheck(HandleTable, curee))
-              {
-                DestroyHandleCallback(HandleTable, curee->u1.Object, curee->u2.GrantedAccess, Context);
-                ExUnlockHandleTableEntry(HandleTable, curee);
-              }
+              curee->u1.ObAttributes |= EX_HANDLE_ENTRY_LOCKED;
+              SweepHandleCallback(HandleTable, curee->u1.Object, curee->u2.GrantedAccess, Context);
             }
           }
         }
@@ -277,6 +217,34 @@ ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
     }
   }
 
+  ExReleaseHandleTableLock(HandleTable);
+
+  KeLeaveCriticalRegion();
+}
+
+VOID
+ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable)
+{
+  PHANDLE_TABLE_ENTRY **tlp, **lasttlp, *mlp, *lastmlp;
+  PEPROCESS QuotaProcess;
+
+  PAGED_CODE();
+
+  ASSERT(HandleTable);
+  ASSERT(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING);
+
+  KeEnterCriticalRegion();
+
+  /* at this point the table should not be queried or altered anymore,
+     no locks should be necessary */
+
+  ASSERT(HandleTable->Flags & EX_HANDLE_TABLE_CLOSING);
+
+  /* remove the handle table from the global handle table list */
+  ExAcquireHandleTableListLock();
+  RemoveEntryList(&HandleTable->HandleTableList);
+  ExReleaseHandleTableListLock();
+
   QuotaProcess = HandleTable->QuotaProcess;
 
   /* free the tables */
@@ -310,8 +278,6 @@ ExDestroyHandleTable(IN PHANDLE_TABLE HandleTable,
     }
   }
 
-  ExReleaseHandleTableLock(HandleTable);
-
   KeLeaveCriticalRegion();
 
   /* free the handle table */
@@ -408,9 +374,7 @@ freehandletable:
 
           ExReleaseHandleTableLock(SourceHandleTable);
 
-          ExDestroyHandleTable(HandleTable,
-                               NULL,
-                               NULL);
+          ExDestroyHandleTable(HandleTable);
           /* allocate an empty handle table */
           return ExCreateHandleTable(QuotaProcess);
         }