Author: tkreuzer Date: Tue Jan 8 08:04:52 2008 New Revision: 31661
URL: http://svn.reactos.org/svn/reactos?rev=31661&view=rev Log: change gdi object deleting mechanism to a windows compatible one.
Modified: trunk/reactos/subsystems/win32/win32k/include/gdiobj.h trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
Modified: trunk/reactos/subsystems/win32/win32k/include/gdiobj.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/gdiobj.h (original) +++ trunk/reactos/subsystems/win32/win32k/include/gdiobj.h Tue Jan 8 08:04:52 2008 @@ -24,9 +24,9 @@ ////////////////////////////////////////////////////////////////////////////// PPAGED_LOOKASIDE_LIST LookasideLists;
- SLIST_HEADER FreeEntriesHead; - SLIST_ENTRY FreeEntries[((GDI_HANDLE_COUNT * sizeof(GDI_TABLE_ENTRY)) << 3) / - (sizeof(SLIST_ENTRY) << 3)]; + ULONG FirstFree; + ULONG FirstUnused; + } GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
extern PGDI_HANDLE_TABLE GdiHandleTable;
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c (original) +++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c Tue Jan 8 08:04:52 2008 @@ -124,9 +124,7 @@ PGDI_HANDLE_TABLE HandleTable = NULL; LARGE_INTEGER htSize; UINT ObjType; - UINT i; ULONG ViewSize = 0; - PGDI_TABLE_ENTRY Entry; NTSTATUS Status;
ASSERT(SectionObject != NULL); @@ -157,16 +155,6 @@
RtlZeroMemory(HandleTable, sizeof(GDI_HANDLE_TABLE));
- /* - * initialize the free entry cache - */ - InitializeSListHead(&HandleTable->FreeEntriesHead); - Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT]; - for(i = GDI_HANDLE_COUNT - 1; i >= RESERVE_ENTRIES_COUNT; i--) - { - InterlockedPushEntrySList(&HandleTable->FreeEntriesHead, &HandleTable->FreeEntries[i]); - } - HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool, BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST), TAG_GDIHNDTBLE); @@ -188,6 +176,9 @@ }
ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */ + + HandleTable->FirstFree = 0; + HandleTable->FirstUnused = RESERVE_ENTRIES_COUNT;
return HandleTable; } @@ -329,6 +320,69 @@ KeRosDumpStackFrames(NULL, 20); }
+ULONG +FASTCALL +InterlockedPopFreeEntry(PGDI_HANDLE_TABLE HandleTable) +{ + ULONG idxFirstFree, idxNextFree, idxPrev; + PGDI_TABLE_ENTRY pFreeEntry; + + DPRINT("Enter InterLockedPopFreeEntry\n"); + + do + { + idxFirstFree = HandleTable->FirstFree; + if (idxFirstFree) + { + pFreeEntry = HandleTable->Entries + idxFirstFree; + ASSERT(((ULONG)pFreeEntry->KernelData & ~GDI_HANDLE_INDEX_MASK) == 0); + idxNextFree = (ULONG)pFreeEntry->KernelData; + idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstFree, idxNextFree, idxFirstFree); + } + else + { + idxFirstFree = HandleTable->FirstUnused; + idxNextFree = idxFirstFree + 1; + if (idxNextFree >= GDI_HANDLE_COUNT) + { + DPRINT1("No more gdi handles left!\n"); + return 0; + } + idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstUnused, idxNextFree, idxFirstFree); + } + } + while (idxPrev != idxFirstFree); + + return idxFirstFree; +} + +/* Pushes an entry of the handle table to the free list, + The entry must be unlocked and the base type field must be 0 */ +VOID +FASTCALL +InterlockedPushFreeEntry(PGDI_HANDLE_TABLE HandleTable, ULONG idxToFree) +{ + ULONG idxFirstFree, idxPrev; + PGDI_TABLE_ENTRY pFreeEntry; + + DPRINT("Enter InterlockedPushFreeEntry\n"); + + pFreeEntry = HandleTable->Entries + idxToFree; + ASSERT((pFreeEntry->Type & GDI_ENTRY_BASETYPE_MASK) == 0); + ASSERT(pFreeEntry->ProcessId == 0); + pFreeEntry->UserData = NULL; + + do + { + idxFirstFree = HandleTable->FirstFree; + pFreeEntry->KernelData = (PVOID)idxFirstFree; + + idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstFree, idxToFree, idxFirstFree); + } + while (idxPrev != idxFirstFree); +} + + /*! * Allocate memory for GDI object and return handle to it. * @@ -380,7 +434,7 @@ } if(newObject != NULL) { - PSLIST_ENTRY FreeEntry; + UINT Index; PGDI_TABLE_ENTRY Entry; PGDIOBJ ObjectBody; LONG TypeInfo; @@ -407,15 +461,11 @@ (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */ TypeInfo = (ObjectType & GDI_HANDLE_BASETYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
- FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead); - if(FreeEntry != NULL) + Index = InterlockedPopFreeEntry(HandleTable); + if (Index != 0) { HANDLE PrevProcId; - UINT Index; - - /* calculate the entry from the address of the entry in the free slot array */ - Index = ((ULONG_PTR)FreeEntry - (ULONG_PTR)&HandleTable->FreeEntries[0]) / - sizeof(HandleTable->FreeEntries[0]); + Entry = &HandleTable->Entries[Index];
LockHandle: @@ -423,8 +473,6 @@ if(PrevProcId == NULL) { HGDIOBJ Handle; - - ASSERT(Entry->KernelData == NULL);
Entry->KernelData = ObjectBody;
@@ -554,7 +602,8 @@ if(PrevProcId == ProcessId) { if( (Entry->KernelData != NULL) && - ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) ) + ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) && + ((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == (HandleUpper & GDI_ENTRY_BASETYPE_MASK)) ) { PGDIOBJHDR GdiHdr;
@@ -565,16 +614,14 @@ BOOL Ret; PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
- /* Clear the type field so when unlocking the handle it gets finally deleted and increment reuse counter */ - Entry->Type = (Entry->Type + GDI_ENTRY_REUSE_INC) & GDI_ENTRY_REUSE_MASK; - Entry->KernelData = NULL; + /* Clear the basetype field so when unlocking the handle it gets finally deleted and increment reuse counter */ + Entry->Type = (Entry->Type + GDI_ENTRY_REUSE_INC) & ~GDI_ENTRY_BASETYPE_MASK;
/* unlock the handle slot */ (void)InterlockedExchangePointer(&Entry->ProcessId, NULL);
/* push this entry to the free list */ - InterlockedPushEntrySList(&HandleTable->FreeEntriesHead, - &HandleTable->FreeEntries[GDI_ENTRY_TO_INDEX(HandleTable, Entry)]); + InterlockedPushFreeEntry(HandleTable, GDI_ENTRY_TO_INDEX(HandleTable, Entry));
if(W32Process != NULL) { @@ -646,7 +693,7 @@ else { DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)ProcessId & ~0x1); - KeRosDumpStackFrames(NULL, 20); + KeRosDumpStackFrames(NULL, 20); } #ifdef GDI_DEBUG DPRINT1("-> called from %s:%i\n", file, line);