- use the new ObjectType list with fixed indices

svn path=/trunk/; revision=28892
This commit is contained in:
Timo Kreuzer 2007-09-06 02:54:17 +00:00
parent 2aaf1f0e51
commit ad90579751

View file

@ -48,13 +48,6 @@ KeRosDumpStackFrames(
/* apparently the first 10 entries are never used in windows as they are empty */
#define RESERVE_ENTRIES_COUNT 10
typedef struct
{
ULONG Type;
ULONG Size;
GDICLEANUPPROC CleanupProc;
} GDI_OBJ_INFO, *PGDI_OBJ_INFO;
/*
* Dummy GDI Cleanup Callback
*/
@ -64,31 +57,6 @@ GDI_CleanupDummy(PVOID ObjectBody)
return TRUE;
}
/* Testing shows that regions are the most used GDIObj type,
so put that one first for performance */
static const
GDI_OBJ_INFO ObjInfo[] =
{
/* Type */ /* Size */ /* CleanupProc */
{GDI_OBJECT_TYPE_REGION, sizeof(ROSRGNDATA), RGNDATA_Cleanup},
{GDI_OBJECT_TYPE_BITMAP, sizeof(BITMAPOBJ), BITMAP_Cleanup},
{GDI_OBJECT_TYPE_DC, sizeof(DC), DC_Cleanup},
{GDI_OBJECT_TYPE_PALETTE, sizeof(PALGDI), PALETTE_Cleanup},
{GDI_OBJECT_TYPE_BRUSH, sizeof(GDIBRUSHOBJ), BRUSH_Cleanup},
{GDI_OBJECT_TYPE_PEN, sizeof(GDIBRUSHOBJ), BRUSH_Cleanup},
{GDI_OBJECT_TYPE_FONT, sizeof(TEXTOBJ), GDI_CleanupDummy},
{GDI_OBJECT_TYPE_DIRECTDRAW, sizeof(DD_DIRECTDRAW), DD_Cleanup},
{GDI_OBJECT_TYPE_DD_SURFACE, sizeof(DD_SURFACE), DDSURF_Cleanup},
{GDI_OBJECT_TYPE_EXTPEN, sizeof(GDIBRUSHOBJ), BRUSH_Cleanup},
/* FIXME do not use normal DC struct for this */
{GDI_OBJECT_TYPE_METADC, sizeof(DC), GDI_CleanupDummy},
{GDI_OBJECT_TYPE_METAFILE, sizeof(DC), GDI_CleanupDummy},
{GDI_OBJECT_TYPE_ENHMETAFILE, 0, GDI_CleanupDummy},
{GDI_OBJECT_TYPE_EMF, 0, GDI_CleanupDummy}
};
#define OBJTYPE_COUNT (sizeof(ObjInfo) / sizeof(ObjInfo[0]))
typedef struct
{
BOOL bUseLookaside;
@ -200,7 +168,7 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
}
HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool,
OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
TAG_GDIHNDTBLE);
if(HandleTable->LookasideLists == NULL)
{
@ -210,10 +178,13 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
return NULL;
}
for(ObjType = 0; ObjType < OBJTYPE_COUNT; ObjType++)
for(ObjType = 0; ObjType < BASE_OBJTYPE_COUNT; ObjType++)
{
ExInitializePagedLookasideList(HandleTable->LookasideLists + ObjType, NULL, NULL, 0,
ObjInfo[ObjType].Size + sizeof(GDIOBJHDR), TAG_GDIOBJ, 0);
if (ObjTypeInfo[ObjType].bUseLookaside)
{
ExInitializePagedLookasideList(HandleTable->LookasideLists + ObjType, NULL, NULL, 0,
ObjTypeInfo[ObjType].ulBodySize + sizeof(GDIOBJHDR), ObjTypeInfo[ObjType].Tag, 0);
}
}
ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */
@ -223,55 +194,21 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
static __inline PPAGED_LOOKASIDE_LIST
FindLookasideList(PGDI_HANDLE_TABLE HandleTable,
DWORD ObjectType)
ULONG TypeIndex)
{
int Index;
for (Index = 0; Index < OBJTYPE_COUNT; Index++)
{
if (ObjInfo[Index].Type == ObjectType)
{
return HandleTable->LookasideLists + Index;
}
}
DPRINT1("Can't find lookaside list for object type 0x%08x\n", ObjectType);
return NULL;
return HandleTable->LookasideLists + TypeIndex;
}
static __inline BOOL
RunCleanupCallback(PGDIOBJ pObj, DWORD ObjectType)
RunCleanupCallback(PGDIOBJ pObj, ULONG TypeIndex)
{
int Index;
for (Index = 0; Index < OBJTYPE_COUNT; Index++)
{
if (ObjInfo[Index].Type == ObjectType)
{
return ((GDICLEANUPPROC)ObjInfo[Index].CleanupProc)(pObj);
}
}
DPRINT1("Can't find cleanup callback for object type 0x%08x\n", ObjectType);
return TRUE;
return ((GDICLEANUPPROC)ObjTypeInfo[TypeIndex].CleanupProc)(pObj);
}
static __inline ULONG
GetObjectSize(DWORD ObjectType)
GetObjectSize(ULONG TypeIndex)
{
int Index;
for (Index = 0; Index < OBJTYPE_COUNT; Index++)
{
if (ObjInfo[Index].Type == ObjectType)
{
return ObjInfo[Index].Size;
}
}
DPRINT1("Can't find size for object type 0x%08x\n", ObjectType);
return 0;
return ObjTypeInfo[TypeIndex].ulBodySize;
}
#ifdef GDI_DEBUG
@ -411,9 +348,10 @@ GDIOBJ_AllocObj(PGDI_HANDLE_TABLE HandleTable, ULONG ObjectType)
#endif /* GDI_DEBUG */
{
PW32PROCESS W32Process;
PGDIOBJHDR newObject;
PPAGED_LOOKASIDE_LIST LookasideList;
PGDIOBJHDR newObject = NULL;
PPAGED_LOOKASIDE_LIST LookasideList = NULL;
HANDLE CurrentProcessId, LockedProcessId;
ULONG TypeIndex;
#ifdef GDI_DEBUG
ULONG Attempts = 0;
#endif
@ -426,115 +364,128 @@ GDIOBJ_AllocObj(PGDI_HANDLE_TABLE HandleTable, ULONG ObjectType)
ASSERT(ObjectType != GDI_OBJECT_TYPE_DONTCARE);
LookasideList = FindLookasideList(HandleTable, ObjectType);
if(LookasideList != NULL)
TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(ObjectType);
if (ObjTypeInfo[TypeIndex].bUseLookaside)
{
newObject = ExAllocateFromPagedLookasideList(LookasideList);
if(newObject != NULL)
LookasideList = FindLookasideList(HandleTable, TypeIndex);
if(LookasideList != NULL)
{
PSLIST_ENTRY FreeEntry;
PGDI_TABLE_ENTRY Entry;
PGDIOBJ ObjectBody;
LONG TypeInfo;
CurrentProcessId = PsGetCurrentProcessId();
LockedProcessId = (HANDLE)((ULONG_PTR)CurrentProcessId | 0x1);
newObject->LockingThread = NULL;
newObject->Locks = 0;
#ifdef GDI_DEBUG
newObject->createdfile = file;
newObject->createdline = line;
newObject->lockfile = NULL;
newObject->lockline = 0;
#endif
ObjectBody = GDIHdrToBdy(newObject);
RtlZeroMemory(ObjectBody, GetObjectSize(ObjectType));
/* FIXME: On Windows the higher 16 bit of the type field don't always match
the type from the handle, it is probably a storage type
(type = pen, storage = brush) */
TypeInfo = (ObjectType & GDI_HANDLE_TYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
if(FreeEntry != NULL)
{
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:
PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0);
if(PrevProcId == NULL)
{
HGDIOBJ Handle;
ASSERT(Entry->KernelData == NULL);
Entry->KernelData = ObjectBody;
/* copy the reuse-counter */
TypeInfo |= Entry->Type & GDI_ENTRY_REUSE_MASK;
/* we found a free entry, no need to exchange this field atomically
since we're holding the lock */
Entry->Type = TypeInfo;
/* unlock the entry */
(void)InterlockedExchangePointer(&Entry->ProcessId, CurrentProcessId);
#ifdef GDI_DEBUG
memset ( GDIHandleAllocator[Index], 0xcd, GDI_STACK_LEVELS * sizeof(ULONG) );
KeRosGetStackFrames ( GDIHandleAllocator[Index], GDI_STACK_LEVELS );
#endif /* GDI_DEBUG */
if(W32Process != NULL)
{
InterlockedIncrement(&W32Process->GDIObjects);
}
Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo << GDI_ENTRY_UPPER_SHIFT));
DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody);
return Handle;
}
else
{
#ifdef GDI_DEBUG
if(++Attempts > 20)
{
DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index);
}
#endif
/* damn, someone is trying to lock the object even though it doesn't
eve nexist anymore, wait a little and try again!
FIXME - we shouldn't loop forever! Give up after some time! */
DelayExecution();
/* try again */
goto LockHandle;
}
}
ExFreeToPagedLookasideList(LookasideList, newObject);
DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n");
#ifdef GDI_DEBUG
IntDumpHandleTable(HandleTable);
#endif /* GDI_DEBUG */
}
else
{
DPRINT1("Not enough memory to allocate gdi object!\n");
newObject = ExAllocateFromPagedLookasideList(LookasideList);
}
}
else
{
DPRINT1("Failed to find lookaside list for object type 0x%x\n", ObjectType);
newObject = ExAllocatePoolWithTag(PagedPool,
ObjTypeInfo[TypeIndex].ulBodySize + sizeof(GDIOBJHDR),
ObjTypeInfo[TypeIndex].Tag);
}
if(newObject != NULL)
{
PSLIST_ENTRY FreeEntry;
PGDI_TABLE_ENTRY Entry;
PGDIOBJ ObjectBody;
LONG TypeInfo;
CurrentProcessId = PsGetCurrentProcessId();
LockedProcessId = (HANDLE)((ULONG_PTR)CurrentProcessId | 0x1);
newObject->LockingThread = NULL;
newObject->Locks = 0;
#ifdef GDI_DEBUG
newObject->createdfile = file;
newObject->createdline = line;
newObject->lockfile = NULL;
newObject->lockline = 0;
#endif
ObjectBody = GDIHdrToBdy(newObject);
RtlZeroMemory(ObjectBody, GetObjectSize(TypeIndex));
/* FIXME: On Windows the higher 16 bit of the type field don't always match
the type from the handle, it is probably a storage type
(type = pen, storage = brush) */
TypeInfo = (ObjectType & GDI_HANDLE_TYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
if(FreeEntry != NULL)
{
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:
PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId, LockedProcessId, 0);
if(PrevProcId == NULL)
{
HGDIOBJ Handle;
ASSERT(Entry->KernelData == NULL);
Entry->KernelData = ObjectBody;
/* copy the reuse-counter */
TypeInfo |= Entry->Type & GDI_ENTRY_REUSE_MASK;
/* we found a free entry, no need to exchange this field atomically
since we're holding the lock */
Entry->Type = TypeInfo;
/* unlock the entry */
(void)InterlockedExchangePointer(&Entry->ProcessId, CurrentProcessId);
#ifdef GDI_DEBUG
memset ( GDIHandleAllocator[Index], 0xcd, GDI_STACK_LEVELS * sizeof(ULONG) );
KeRosGetStackFrames ( GDIHandleAllocator[Index], GDI_STACK_LEVELS );
#endif /* GDI_DEBUG */
if(W32Process != NULL)
{
InterlockedIncrement(&W32Process->GDIObjects);
}
Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo << GDI_ENTRY_UPPER_SHIFT));
DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody);
return Handle;
}
else
{
#ifdef GDI_DEBUG
if(++Attempts > 20)
{
DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index);
}
#endif
/* damn, someone is trying to lock the object even though it doesn't
eve nexist anymore, wait a little and try again!
FIXME - we shouldn't loop forever! Give up after some time! */
DelayExecution();
/* try again */
goto LockHandle;
}
}
if (ObjTypeInfo[TypeIndex].bUseLookaside)
{
ExFreeToPagedLookasideList(LookasideList, newObject);
}
else
{
ExFreePool(newObject);
}
DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n");
#ifdef GDI_DEBUG
IntDumpHandleTable(HandleTable);
#endif /* GDI_DEBUG */
}
else
{
DPRINT1("Not enough memory to allocate gdi object!\n");
}
return NULL;
}
@ -559,7 +510,7 @@ GDIOBJ_FreeObj(PGDI_HANDLE_TABLE HandleTable, HGDIOBJ hObj, DWORD ExpectedType)
PGDI_TABLE_ENTRY Entry;
PPAGED_LOOKASIDE_LIST LookasideList;
HANDLE ProcessId, LockedProcessId, PrevProcId;
ULONG HandleType, HandleUpper;
ULONG HandleType, HandleUpper, TypeIndex;
BOOL Silent;
#ifdef GDI_DEBUG
ULONG Attempts = 0;
@ -632,13 +583,21 @@ LockHandle:
}
/* call the cleanup routine. */
Ret = RunCleanupCallback(GDIHdrToBdy(GdiHdr), HandleType);
TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(HandleType);
Ret = RunCleanupCallback(GDIHdrToBdy(GdiHdr), TypeIndex);
/* Now it's time to free the memory */
LookasideList = FindLookasideList(HandleTable, HandleType);
if(LookasideList != NULL)
if (ObjTypeInfo[TypeIndex].bUseLookaside)
{
ExFreeToPagedLookasideList(LookasideList, GdiHdr);
LookasideList = FindLookasideList(HandleTable, TypeIndex);
if(LookasideList != NULL)
{
ExFreeToPagedLookasideList(LookasideList, GdiHdr);
}
}
else
{
ExFreePool(GdiHdr);
}
return Ret;