From db41ecbbff4962a627e56241263d048b23dea403 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Wed, 7 Dec 2005 17:06:48 +0000 Subject: [PATCH] implemented sweeping of handle tables svn path=/trunk/; revision=19951 --- reactos/ntoskrnl/ex/handle.c | 132 +++++++++---------------- reactos/ntoskrnl/include/internal/ex.h | 9 +- reactos/ntoskrnl/ob/handle.c | 17 ++-- reactos/ntoskrnl/rtl/libsupp.c | 16 +-- 4 files changed, 69 insertions(+), 105 deletions(-) diff --git a/reactos/ntoskrnl/ex/handle.c b/reactos/ntoskrnl/ex/handle.c index 21fe5f612ff..71ec9254414 100644 --- a/reactos/ntoskrnl/ex/handle.c +++ b/reactos/ntoskrnl/ex/handle.c @@ -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); } diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index bd9fb1b4473..0e38d139ff4 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -91,7 +91,7 @@ ExpInitializeProfileImplementation(VOID); EX_HANDLE_ENTRY_INHERITABLE | \ EX_HANDLE_ENTRY_AUDITONCLOSE) -typedef VOID (STDCALL PEX_DESTROY_HANDLE_CALLBACK)( +typedef VOID (STDCALL PEX_SWEEP_HANDLE_CALLBACK)( PHANDLE_TABLE HandleTable, PVOID Object, ULONG GrantedAccess, @@ -118,8 +118,13 @@ ExCreateHandleTable(IN PEPROCESS QuotaProcess OPTIONAL); VOID ExDestroyHandleTable( + IN PHANDLE_TABLE HandleTable +); + +VOID +ExSweepHandleTable( IN PHANDLE_TABLE HandleTable, - IN PEX_DESTROY_HANDLE_CALLBACK DestroyHandleCallback OPTIONAL, + IN PEX_SWEEP_HANDLE_CALLBACK SweepHandleCallback OPTIONAL, IN PVOID Context OPTIONAL ); diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index 617676611a9..153ff107802 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -504,10 +504,10 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, } static VOID STDCALL -DeleteHandleCallback(PHANDLE_TABLE HandleTable, - PVOID Object, - ULONG GrantedAccess, - PVOID Context) +SweepHandleCallback(PHANDLE_TABLE HandleTable, + PVOID Object, + ULONG GrantedAccess, + PVOID Context) { POBJECT_HEADER ObjectHeader; PVOID ObjectBody; @@ -580,9 +580,12 @@ ObKillProcess(PEPROCESS Process) { PAGED_CODE(); - ExDestroyHandleTable(Process->ObjectTable, - DeleteHandleCallback, - Process); + /* FIXME - Temporary hack: sweep and destroy here, needs to be fixed!!! */ + ExSweepHandleTable(Process->ObjectTable, + SweepHandleCallback, + Process); + ExDestroyHandleTable(Process->ObjectTable); + Process->ObjectTable = NULL; } diff --git a/reactos/ntoskrnl/rtl/libsupp.c b/reactos/ntoskrnl/rtl/libsupp.c index 34ad4a1a3fc..d966de6298a 100644 --- a/reactos/ntoskrnl/rtl/libsupp.c +++ b/reactos/ntoskrnl/rtl/libsupp.c @@ -225,23 +225,15 @@ RtlpCreateAtomHandleTable(PRTL_ATOM_TABLE AtomTable) return (AtomTable->ExHandleTable != NULL); } -static VOID STDCALL -AtomDeleteHandleCallback(PHANDLE_TABLE HandleTable, - PVOID Object, - ULONG GrantedAccess, - PVOID Context) -{ - return; -} - VOID RtlpDestroyAtomHandleTable(PRTL_ATOM_TABLE AtomTable) { if (AtomTable->ExHandleTable) { - ExDestroyHandleTable(AtomTable->ExHandleTable, - AtomDeleteHandleCallback, - AtomTable); + ExSweepHandleTable(AtomTable->ExHandleTable, + NULL, + NULL); + ExDestroyHandleTable(AtomTable->ExHandleTable); AtomTable->ExHandleTable = NULL; } }