implemented sweeping of handle tables

svn path=/trunk/; revision=19951
This commit is contained in:
Thomas Bluemel 2005-12-07 17:06:48 +00:00
parent e6894eb9f9
commit db41ecbbff
4 changed files with 69 additions and 105 deletions

View 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);
}

View file

@ -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
);

View file

@ -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;
}

View file

@ -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;
}
}