mirror of
https://github.com/reactos/reactos.git
synced 2025-05-18 16:51:18 +00:00
- use the new ObjectType list with fixed indices
svn path=/trunk/; revision=28892
This commit is contained in:
parent
2aaf1f0e51
commit
ad90579751
1 changed files with 145 additions and 186 deletions
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue