Commit in reactos on MAIN
include/win32k/gdiobj.h+5-11.27 -> 1.28
subsys/win32k/objects/gdiobj.c+84-431.76 -> 1.77
+89-44
2 modified files
cache free gdi handles

reactos/include/win32k
gdiobj.h 1.27 -> 1.28
diff -u -r1.27 -r1.28
--- gdiobj.h	12 Dec 2004 01:40:36 -0000	1.27
+++ gdiobj.h	13 Dec 2004 21:59:27 -0000	1.28
@@ -65,6 +65,8 @@
   PETHREAD LockingThread; /* only assigned if a thread is holding the lock! */
   ULONG Locks;
 #ifdef GDI_DEBUG
+  const char* createdfile;
+  int createdline;
   const char* lockfile;
   int lockline;
 #endif
@@ -77,7 +79,6 @@
   DWORD	ObjectType;
 } GDIMULTILOCK, *PGDIMULTILOCK;
 
-HGDIOBJ INTERNAL_CALL GDIOBJ_AllocObj(ULONG ObjectType);
 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);
@@ -92,16 +93,19 @@
 #ifdef GDI_DEBUG
 
 /* a couple macros for debugging GDIOBJ locking */
+#define GDIOBJ_AllocObj(ty) GDIOBJ_AllocObjDbg(__FILE__,__LINE__,ty)
 #define GDIOBJ_FreeObj(obj,ty) GDIOBJ_FreeObjDbg(__FILE__,__LINE__,obj,ty)
 #define GDIOBJ_LockObj(obj,ty) GDIOBJ_LockObjDbg(__FILE__,__LINE__,obj,ty)
 #define GDIOBJ_UnlockObj(obj) GDIOBJ_UnlockObjDbg(__FILE__,__LINE__,obj)
 
+HGDIOBJ INTERNAL_CALL GDIOBJ_AllocObjDbg(const char* file, int line, ULONG ObjectType);
 BOOL    INTERNAL_CALL GDIOBJ_FreeObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType);
 PGDIOBJ INTERNAL_CALL GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType);
 BOOL    INTERNAL_CALL GDIOBJ_UnlockObjDbg (const char* file, int line, HGDIOBJ hObj);
 
 #else /* !GDI_DEBUG */
 
+HGDIOBJ INTERNAL_CALL GDIOBJ_AllocObj(ULONG ObjectType);
 BOOL    INTERNAL_CALL GDIOBJ_FreeObj (HGDIOBJ hObj, DWORD ObjectType);
 PGDIOBJ INTERNAL_CALL GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType);
 BOOL    INTERNAL_CALL GDIOBJ_UnlockObj (HGDIOBJ hObj);

reactos/subsys/win32k/objects
gdiobj.c 1.76 -> 1.77
diff -u -r1.76 -r1.77
--- gdiobj.c	13 Dec 2004 12:51:51 -0000	1.76
+++ gdiobj.c	13 Dec 2004 21:59:28 -0000	1.77
@@ -19,7 +19,7 @@
 /*
  * GDIOBJ.C - GDI object manipulation routines
  *
- * $Id: gdiobj.c,v 1.76 2004/12/13 12:51:51 weiden Exp $
+ * $Id: gdiobj.c,v 1.77 2004/12/13 21:59:28 weiden Exp $
  */
 #include <w32k.h>
 
@@ -52,13 +52,13 @@
 
 typedef struct _GDI_HANDLE_TABLE
 {
-  LONG HandlesCount;
-  LONG nEntries;
   PPAGED_LOOKASIDE_LIST LookasideLists;
+  
+  SLIST_HEADER FreeEntriesHead;
+  SLIST_ENTRY FreeEntries[((GDI_HANDLE_COUNT * sizeof(GDI_TABLE_ENTRY)) << 3) /
+                          (sizeof(SLIST_ENTRY) << 3)];
 
-  PGDI_TABLE_ENTRY EntriesEnd;
-
-  GDI_TABLE_ENTRY Entries[1];
+  GDI_TABLE_ENTRY Entries[GDI_HANDLE_COUNT];
 } GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
 
 typedef struct
@@ -116,20 +116,26 @@
  * \param	Size - number of entries in the object table.
 */
 static PGDI_HANDLE_TABLE INTERNAL_CALL
-GDIOBJ_iAllocHandleTable(ULONG Entries)
+GDIOBJ_iAllocHandleTable(VOID)
 {
   PGDI_HANDLE_TABLE handleTable;
   UINT ObjType;
-  ULONG MemSize = sizeof(GDI_HANDLE_TABLE) + (sizeof(GDI_TABLE_ENTRY) * (Entries - 1));
+  UINT i;
+  PGDI_TABLE_ENTRY Entry;
 
-  handleTable = ExAllocatePoolWithTag(NonPagedPool, MemSize, TAG_GDIHNDTBLE);
+  handleTable = ExAllocatePoolWithTag(NonPagedPool, sizeof(GDI_HANDLE_TABLE), TAG_GDIHNDTBLE);
   ASSERT( handleTable );
-  RtlZeroMemory(handleTable, MemSize);
-
-  handleTable->HandlesCount = 0;
-  handleTable->nEntries = Entries;
-
-  handleTable->EntriesEnd = &handleTable->Entries[Entries];
+  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,
                                                       OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
@@ -214,12 +220,19 @@
  * \todo return the object pointer and lock it by default.
 */
 HGDIOBJ INTERNAL_CALL
+#ifdef GDI_DEBUG
+GDIOBJ_AllocObjDbg(const char* file, int line, ULONG ObjectType)
+#else /* !GDI_DEBUG */
 GDIOBJ_AllocObj(ULONG ObjectType)
+#endif /* GDI_DEBUG */
 {
   PW32PROCESS W32Process;
   PGDIOBJHDR  newObject;
   PPAGED_LOOKASIDE_LIST LookasideList;
   LONG CurrentProcessId, LockedProcessId;
+#ifdef GDI_DEBUG
+  ULONG Attempts = 0;
+#endif
 
   ASSERT(ObjectType != GDI_OBJECT_TYPE_DONTCARE);
 
@@ -229,6 +242,7 @@
     newObject = ExAllocateFromPagedLookasideList(LookasideList);
     if(newObject != NULL)
     {
+      PSLIST_ENTRY FreeEntry;
       PGDI_TABLE_ENTRY Entry;
       PGDIOBJ ObjectBody;
       LONG TypeInfo;
@@ -244,6 +258,8 @@
       newObject->Locks = 0;
 
 #ifdef GDI_DEBUG
+      newObject->createdfile = file;
+      newObject->createdline = line;
       newObject->lockfile = NULL;
       newObject->lockline = 0;
 #endif
@@ -253,40 +269,57 @@
       RtlZeroMemory(ObjectBody, GetObjectSize(ObjectType));
 
       TypeInfo = (ObjectType & 0xFFFF0000) | (ObjectType >> 16);
-
-      /* Search for a free handle entry */
-      for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT];
-          Entry < HandleTable->EntriesEnd;
-          Entry++)
+      
+      FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
+      if(FreeEntry != NULL)
       {
-        LONG PrevProcId = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, 0);
+        LONG 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 = InterlockedCompareExchange(&Entry->ProcessId, LockedProcessId, 0);
         if(PrevProcId == 0)
         {
-          if(InterlockedCompareExchangePointer(&Entry->KernelData, ObjectBody, NULL) == NULL)
-          {
-            HGDIOBJ Handle;
-            UINT Index = GDI_ENTRY_TO_INDEX(HandleTable, Entry);
-            
-            Handle = (HGDIOBJ)((Index & 0xFFFF) | (ObjectType & 0xFFFF0000));
-
-            /* we found a free entry, no need to exchange this field atomically
-               since we're holding the lock */
-            Entry->Type = TypeInfo;
+          ASSERT(Entry->KernelData == NULL);
+          
+          Entry->KernelData = ObjectBody;
 
-            InterlockedExchange(&Entry->ProcessId, CurrentProcessId);
+          /* we found a free entry, no need to exchange this field atomically
+             since we're holding the lock */
+          Entry->Type = TypeInfo;
 
-            if(W32Process != NULL)
-            {
-              InterlockedIncrement(&W32Process->GDIObjects);
-            }
+          /* unlock the entry */
+          InterlockedExchange(&Entry->ProcessId, CurrentProcessId);
 
-            DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody);
-            return Handle;
+          if(W32Process != NULL)
+          {
+            InterlockedIncrement(&W32Process->GDIObjects);
           }
-          else
+
+          DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, ObjectBody);
+          return Handle;
+        }
+        else
+        {
+#ifdef GDI_DEBUG
+          if(++Attempts > 20)
           {
-            InterlockedExchange(&Entry->ProcessId, PrevProcId);
+            DPRINT1("[%d]Waiting on 0x%x\n", Attempts, Handle);
           }
+#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;
         }
       }
 
@@ -374,6 +407,10 @@
         /* unlock the handle slot */
         InterlockedExchange(&Entry->ProcessId, 0);
         
+        /* push this entry to the free list */
+        InterlockedPushEntrySList(&HandleTable->FreeEntriesHead,
+                                  &HandleTable->FreeEntries[GDI_ENTRY_TO_INDEX(HandleTable, Entry)]);
+        
         if(W32Process != NULL)
         {
           InterlockedDecrement(&W32Process->GDIObjects);
@@ -536,7 +573,7 @@
 {
   DPRINT("InitGdiObjectHandleTable\n");
 
-  HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
+  HandleTable = GDIOBJ_iAllocHandleTable();
   DPRINT("HandleTable: %x\n", HandleTable);
 }
 
@@ -561,7 +598,7 @@
 BOOL INTERNAL_CALL
 GDI_CleanupForProcess (struct _EPROCESS *Process)
 {
-  PGDI_TABLE_ENTRY Entry;
+  PGDI_TABLE_ENTRY Entry, End;
   PEPROCESS CurrentProcess;
   PW32PROCESS W32Process;
   LONG ProcId;
@@ -582,8 +619,9 @@
                we should delete it directly here! */
     ProcId = ((LONG)Process->UniqueProcessId << 1);
 
+    End = &HandleTable->Entries[GDI_HANDLE_COUNT];
     for(Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT];
-        Entry < HandleTable->EntriesEnd;
+        Entry < End;
         Entry++, Index++)
     {
       /* ignore the lock bit */
@@ -832,6 +870,9 @@
           Entry->KernelData = NULL;
           InterlockedExchange(&Entry->ProcessId, 0);
           
+          InterlockedPushEntrySList(&HandleTable->FreeEntriesHead,
+                                    &HandleTable->FreeEntries[GDI_ENTRY_TO_INDEX(HandleTable, Entry)]);
+          
           if(W32Process != NULL)
           {
             InterlockedDecrement(&W32Process->GDIObjects);
CVSspam 0.2.8