implemented reuse counters for gdi objects
Modified: trunk/reactos/include/win32k/gdiobj.h
Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c
Modified: trunk/reactos/subsys/win32k/objects/region.c
_____
Modified: trunk/reactos/include/win32k/gdiobj.h
--- trunk/reactos/include/win32k/gdiobj.h 2005-02-18 09:17:56 UTC
(rev 13627)
+++ trunk/reactos/include/win32k/gdiobj.h 2005-02-18 12:54:17 UTC
(rev 13628)
@@ -19,13 +19,16 @@
#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
#define GDI_HANDLE_TYPE_MASK 0x007f0000
#define GDI_HANDLE_STOCK_MASK 0x00800000
+#define GDI_HANDLE_REUSE_MASK 0xff000000
+#define GDI_HANDLE_REUSECNT_SHIFT 24
+
#define GDI_HANDLE_CREATE(i, t) ((HANDLE)(((i) &
GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK)))
-#define GDI_HANDLE_GET_INDEX(h) (((DWORD)(h)) &
GDI_HANDLE_INDEX_MASK)
-#define GDI_HANDLE_GET_TYPE(h) (((DWORD)(h)) &
GDI_HANDLE_TYPE_MASK)
-#define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((DWORD)(h)) &
GDI_HANDLE_TYPE_MASK))
-#define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((DWORD)(h)) &
GDI_HANDLE_STOCK_MASK))
-#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) |
GDI_HANDLE_STOCK_MASK))
+#define GDI_HANDLE_GET_INDEX(h) (((ULONG_PTR)(h)) &
GDI_HANDLE_INDEX_MASK)
+#define GDI_HANDLE_GET_TYPE(h) (((ULONG_PTR)(h)) &
GDI_HANDLE_TYPE_MASK)
+#define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((ULONG_PTR)(h)) &
GDI_HANDLE_TYPE_MASK))
+#define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((ULONG_PTR)(h)) &
GDI_HANDLE_STOCK_MASK))
+#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((ULONG_PTR)(h)) |
GDI_HANDLE_STOCK_MASK))
/*! \defgroup GDI object types
@@ -74,20 +77,10 @@
#endif
} GDIOBJHDR, *PGDIOBJHDR;
-typedef struct _GDIMULTILOCK
-{
- HGDIOBJ hObj;
- PGDIOBJ pObj;
- DWORD ObjectType;
-} GDIMULTILOCK, *PGDIMULTILOCK;
-
-BOOL INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT
nObj);
-BOOL INTERNAL_CALL GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT
nObj);
BOOL INTERNAL_CALL GDIOBJ_OwnedByCurrentProcess(HGDIOBJ
ObjectHandle);
void INTERNAL_CALL GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle,
PEPROCESS Owner);
void INTERNAL_CALL GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ
CopyTo);
BOOL INTERNAL_CALL GDIOBJ_ConvertToStockObj(HGDIOBJ *hObj);
-BOOL INTERNAL_CALL GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT
nObj);
#define GDIOBJ_GetObjectType(Handle) \
GDI_HANDLE_GET_TYPE(Handle)
_____
Modified: trunk/reactos/subsys/win32k/objects/gdiobj.c
--- trunk/reactos/subsys/win32k/objects/gdiobj.c 2005-02-18
09:17:56 UTC (rev 13627)
+++ trunk/reactos/subsys/win32k/objects/gdiobj.c 2005-02-18
12:54:17 UTC (rev 13628)
@@ -377,28 +377,31 @@
RtlZeroMemory(ObjectBody, GetObjectSize(ObjectType));
- TypeInfo = (ObjectType & 0xFFFF0000) | (ObjectType >> 16);
+ TypeInfo = (ObjectType & GDI_HANDLE_TYPE_MASK) | (ObjectType >>
16);
FreeEntry =
InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
if(FreeEntry != NULL)
{
HANDLE PrevProcId;
UINT Index;
- HGDIOBJ Handle;
/* 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];
- Handle = (HGDIOBJ)((Index & 0xFFFF) | (ObjectType &
0xFFFF0000));
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_HANDLE_REUSE_MASK;
/* we found a free entry, no need to exchange this field
atomically
since we're holding the lock */
@@ -416,6 +419,7 @@
{
InterlockedIncrement(&W32Process->GDIObjects);
}
+ Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo &
(GDI_HANDLE_TYPE_MASK | GDI_HANDLE_REUSE_MASK)));
DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle,
ObjectBody);
return Handle;
@@ -425,7 +429,7 @@
#ifdef GDI_DEBUG
if(++Attempts > 20)
{
- DPRINT1("[%d]Waiting on 0x%x\n", Attempts, Handle);
+ 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
@@ -508,7 +512,8 @@
PrevProcId = InterlockedCompareExchangePointer(&Entry->ProcessId,
LockedProcessId, ProcessId);
if(PrevProcId == ProcessId)
{
- if(Entry->Type != 0 && Entry->KernelData != NULL &&
(ExpectedType
== 0 || ((Entry->Type << 16) == ExpectedType)))
+ if(Entry->Type != 0 && Entry->KernelData != NULL &&
+ (ExpectedType == 0 || ((Entry->Type << 16) == ExpectedType)))
{
PGDIOBJHDR GdiHdr;
@@ -520,8 +525,8 @@
PW32PROCESS W32Process = PsGetWin32Process();
ULONG Type = Entry->Type << 16;
- /* Clear the type field so when unlocking the handle it gets
finally deleted */
- Entry->Type = 0;
+ /* Clear the type field so when unlocking the handle it gets
finally deleted and increment reuse counter */
+ Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1)
<< GDI_HANDLE_REUSECNT_SHIFT;
Entry->KernelData = NULL;
/* unlock the handle slot */
@@ -551,8 +556,9 @@
else
{
/* the object is currently locked. just clear the type field so
when the
- object gets unlocked it will be finally deleted from the
table. */
- Entry->Type = 0;
+ object gets unlocked it will be finally deleted from the
table. Also
+ incrment the reuse counter! */
+ Entry->Type = ((Entry->Type >> GDI_HANDLE_REUSECNT_SHIFT) + 1)
<< GDI_HANDLE_REUSECNT_SHIFT;
/* unlock the handle slot */
InterlockedExchangePointer(&Entry->ProcessId, NULL);
@@ -563,7 +569,7 @@
}
else
{
- if(Entry->Type != 0)
+ if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0)
{
DPRINT1("Attempted to delete object 0x%x, type mismatch (0x%x :
0x%x)\n", hObj, ObjectType, ExpectedType);
}
@@ -610,85 +616,6 @@
}
/*!
- * Lock multiple objects. Use this function when you need to lock
multiple objects and some of them may be
- * duplicates. You should use this function to avoid trying to lock the
same object twice!
- *
- * \param pList pointer to the list that contains handles to the
objects. You should set hObj and ObjectType fields.
- * \param nObj number of objects to lock
- * \return for each entry in pList this function sets pObj field to
point to the object.
- *
- * \note this function uses an O(n^2) algoritm because we shouldn't
need to call it with more than 3 or 4 objects.
-*/
-BOOL INTERNAL_CALL
-GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj)
-{
- INT i, j;
- ASSERT( pList );
- /* FIXME - check for "invalid" handles */
- /* go through the list checking for duplicate objects */
- for (i = 0; i < nObj; i++)
- {
- pList[i].pObj = NULL;
- for (j = 0; j < i; j++)
- {
- if (pList[i].hObj == pList[j].hObj)
- {
- /* already locked, so just copy the pointer to the object
*/
- pList[i].pObj = pList[j].pObj;
- break;
- }
- }
-
- if (NULL == pList[i].pObj)
- {
- /* object hasn't been locked, so lock it. */
- if (NULL != pList[i].hObj)
- {
- pList[i].pObj = GDIOBJ_LockObj(pList[i].hObj,
pList[i].ObjectType);
- }
- }
- }
-
- return TRUE;
-}
-
-/*!
- * Unlock multiple objects. Use this function when you need to unlock
multiple objects and some of them may be
- * duplicates.
- *
- * \param pList pointer to the list that contains handles to the
objects. You should set hObj and ObjectType fields.
- * \param nObj number of objects to lock
- *
- * \note this function uses O(n^2) algoritm because we shouldn't need
to call it with more than 3 or 4 objects.
-*/
-BOOL INTERNAL_CALL
-GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj)
-{
- INT i, j;
- ASSERT(pList);
-
- /* go through the list checking for duplicate objects */
- for (i = 0; i < nObj; i++)
- {
- if (NULL != pList[i].pObj)
- {
- for (j = i + 1; j < nObj; j++)
- {
- if ((pList[i].pObj == pList[j].pObj))
- {
- /* set the pointer to zero for all duplicates */
- pList[j].pObj = NULL;
- }
- }
- GDIOBJ_UnlockObj(pList[i].hObj);
- pList[i].pObj = NULL;
- }
- }
-
- return TRUE;
-}
-
-/*!
* Initialization of the GDI object engine.
*/
VOID INTERNAL_CALL
@@ -744,11 +671,11 @@
End = &HandleTable->Entries[GDI_HANDLE_COUNT];
for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT];
- Entry < End;
+ Entry != End;
Entry++, Index++)
{
/* ignore the lock bit */
- if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId &&
Entry->Type != 0)
+ if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId &&
(Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0)
{
HGDIOBJ ObjectHandle;
@@ -824,7 +751,8 @@
/* we're locking an object that belongs to our process or it's a
global
object if ProcessId == 0 here. ProcessId can only be 0 here if
it previously
failed to lock the object and it turned out to be a global
object. */
- if(EntryType != 0 && Entry->KernelData != NULL && (ExpectedType
==
0 || (EntryType == ExpectedType)))
+ if(EntryType != 0 && Entry->KernelData != NULL &&
+ (ExpectedType == 0 || (EntryType == ExpectedType)))
{
PETHREAD PrevThread;
PGDIOBJHDR GdiHdr;
@@ -870,14 +798,15 @@
{
InterlockedExchangePointer(&Entry->ProcessId, PrevProcId);
- if(EntryType == 0)
+ if((EntryType & ~GDI_HANDLE_REUSE_MASK) == 0)
{
DPRINT1("Attempted to lock object 0x%x that is deleted!\n",
hObj);
KeRosDumpStackFrames ( NULL, 20 );
}
else
{
- DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x :
0x%x)\n", hObj, EntryType, ExpectedType);
+ DPRINT1("Attempted to lock object 0x%x, type mismatch (0x%x :
0x%x)\n",
+ hObj, EntryType & ~GDI_HANDLE_REUSE_MASK, ExpectedType
& ~GDI_HANDLE_REUSE_MASK);
KeRosDumpStackFrames ( NULL, 20 );
}
#ifdef GDI_DEBUG
@@ -981,7 +910,7 @@
#endif
}
- if(Entry->Type == 0 && GdiHdr->Locks == 0)
+ if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) == 0 &&
GdiHdr->Locks
== 0)
{
PPAGED_LOOKASIDE_LIST LookasideList;
PW32PROCESS W32Process = PsGetWin32Process();
@@ -1095,7 +1024,7 @@
Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle);
Ret = Entry->KernelData != NULL &&
- Entry->Type != 0 &&
+ (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 &&
(HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
return Ret;
@@ -1143,6 +1072,8 @@
exchange it.*/
NewType = GDI_HANDLE_GET_TYPE(*hObj);
NewType |= NewType >> 16;
+ NewType |= (ULONG_PTR)(*hObj) & GDI_HANDLE_REUSE_MASK;
+
/* This is the type that the object should have right now, save
it */
OldType = NewType;
/* As the object should be a stock object, set it's flag, but
only in the upper 16 bits */
@@ -1268,7 +1199,7 @@
{
PETHREAD PrevThread;
- if(Entry->Type != 0 && Entry->KernelData != NULL)
+ if((Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 &&
Entry->KernelData != NULL)
{
PGDIOBJHDR GdiHdr = GDIBdyToHdr(Entry->KernelData);
@@ -1401,7 +1332,7 @@
PETHREAD PrevThread;
PGDIOBJHDR GdiHdr;
- if(FromEntry->Type != 0 && FromEntry->KernelData != NULL)
+ if((FromEntry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 &&
FromEntry->KernelData != NULL)
{
GdiHdr = GDIBdyToHdr(FromEntry->KernelData);
_____
Modified: trunk/reactos/subsys/win32k/objects/region.c
--- trunk/reactos/subsys/win32k/objects/region.c 2005-02-18
09:17:56 UTC (rev 13627)
+++ trunk/reactos/subsys/win32k/objects/region.c 2005-02-18
12:54:17 UTC (rev 13628)
@@ -707,45 +707,43 @@
HRGN FASTCALL REGION_CropRgn(HRGN hDst, HRGN hSrc, const PRECT lpRect,
PPOINT lpPt)
{
PROSRGNDATA objSrc, rgnDst;
- HRGN hNewDst, hRet = NULL;
- GDIMULTILOCK Lock[2] = {{hDst, 0, GDI_OBJECT_TYPE_REGION}, {hSrc, 0,
GDI_OBJECT_TYPE_REGION}};
+ HRGN hRet = NULL;
+ POINT pt = { 0, 0 };
if( !hDst )
{
- if( !( hNewDst = RGNDATA_AllocRgn(1) ) )
+ if( !( hDst = RGNDATA_AllocRgn(1) ) )
{
return 0;
}
- Lock[0].hObj = hNewDst;
}
- if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) )
- {
- DPRINT1("GDIOBJ_LockMultipleObj() failed\n" );
- return 0;
- }
- rgnDst = Lock[0].pObj;
- objSrc = Lock[1].pObj;
-
- if( objSrc && rgnDst )
+ rgnDst = RGNDATA_LockRgn(hDst);
+ if(rgnDst == NULL)
{
- if(rgnDst)
- {
- POINT pt = { 0, 0 };
+ return NULL;
+ }
+
+ objSrc = RGNDATA_LockRgn(hSrc);
+ if(objSrc == NULL)
+ {
+ RGNDATA_UnlockRgn(hDst);
+ return NULL;
+ }
+ if(!lpPt)
+ lpPt = &pt;
- if(!lpPt)
- lpPt = &pt;
-
- if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) ==
FALSE)
- { // ve failed cleanup and return
- hRet = NULL;
- }
- else{ // ve are fine. unlock the correct pointer and return
correct handle
- hRet = Lock[0].hObj;
- }
+ if(REGION_CropAndOffsetRegion(lpPt, lpRect, objSrc, rgnDst) ==
FALSE)
+ { // ve failed cleanup and return
+ hRet = NULL;
}
+ else{ // ve are fine. unlock the correct pointer and return correct
handle
+ hRet = hDst;
}
- GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0]));
+
+ RGNDATA_UnlockRgn(hSrc);
+ RGNDATA_UnlockRgn(hDst);
+
return hRet;
}
@@ -1957,21 +1955,12 @@
INT CombineMode)
{
INT result = ERROR;
- GDIMULTILOCK Lock[3] = {{hDest, 0, GDI_OBJECT_TYPE_REGION}, {hSrc1,
0, GDI_OBJECT_TYPE_REGION}, {hSrc2, 0, GDI_OBJECT_TYPE_REGION}};
PROSRGNDATA destRgn, src1Rgn, src2Rgn;
-
- if ( !GDIOBJ_LockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0])) )
- {
- DPRINT1("GDIOBJ_LockMultipleObj() failed\n" );
- return ERROR;
- }
-
- destRgn = (PROSRGNDATA) Lock[0].pObj;
- src1Rgn = (PROSRGNDATA) Lock[1].pObj;
- src2Rgn = (PROSRGNDATA) Lock[2].pObj;
-
+
+ destRgn = RGNDATA_LockRgn(hDest);
if( destRgn )
{
+ src1Rgn = RGNDATA_LockRgn(hSrc1);
if( src1Rgn )
{
if (CombineMode == RGN_COPY)
@@ -1982,7 +1971,8 @@
}
else
{
- if( src2Rgn )
+ src2Rgn = RGNDATA_LockRgn(hSrc2);
+ if( src2Rgn )
{
switch (CombineMode)
{
@@ -1999,17 +1989,26 @@
REGION_SubtractRegion(destRgn, src1Rgn,
src2Rgn);
break;
}
+ RGNDATA_UnlockRgn(hSrc2);
result = destRgn->rdh.iType;
}
+ else
+ {
+ DPRINT1("NtGdiCombineRgn requires hSrc2 != NULL for
combine mode %d!\n", CombineMode);
+ }
}
+
+ RGNDATA_UnlockRgn(hSrc1);
}
+
+ RGNDATA_UnlockRgn(hDest);
}
else
{
DPRINT("NtGdiCombineRgn: hDest unavailable\n");
result = ERROR;
}
- GDIOBJ_UnlockMultipleObj(Lock, sizeof(Lock)/sizeof(Lock[0]));
+
return result;
}