Jacek Caban : gdi32: Use NtAllocateVirtualMemory to alloc DC_ATTR.

Alexandre Julliard julliard at winehq.org
Fri Oct 1 18:02:22 CDT 2021


Module: wine
Branch: master
Commit: 01b6ba88d615125d2244a28a0adfda07dca79d0e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=01b6ba88d615125d2244a28a0adfda07dca79d0e

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Oct  1 01:57:54 2021 +0200

gdi32: Use NtAllocateVirtualMemory to alloc DC_ATTR.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/dc.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 81 insertions(+), 3 deletions(-)

diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index c00e5128ced..c21993a8ca5 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -26,6 +26,8 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <pthread.h>
+
 #include "windef.h"
 #include "winbase.h"
 #include "wingdi.h"
@@ -39,6 +41,18 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dc);
 
+static pthread_mutex_t dc_attr_lock = PTHREAD_MUTEX_INITIALIZER;
+
+struct dc_attr_bucket
+{
+    struct list entry;
+    DC_ATTR *entries;
+    DC_ATTR *next_free;
+    DC_ATTR *next_unused;
+};
+
+static struct list dc_attr_buckets = LIST_INIT( dc_attr_buckets );
+
 static inline const char *debugstr_us( const UNICODE_STRING *us )
 {
     if (!us) return "<null>";
@@ -74,6 +88,70 @@ static inline DC *get_dc_obj( HDC hdc )
     }
 }
 
+/* alloc DC_ATTR from a pool of memory accessible from client */
+static DC_ATTR *alloc_dc_attr(void)
+{
+    struct dc_attr_bucket *bucket;
+    DC_ATTR *dc_attr = NULL;
+
+    pthread_mutex_lock( &dc_attr_lock );
+
+    LIST_FOR_EACH_ENTRY( bucket, &dc_attr_buckets, struct dc_attr_bucket, entry )
+    {
+        if (bucket->next_free)
+        {
+            dc_attr = bucket->next_free;
+            bucket->next_free = *(void **)bucket->next_free;
+            break;
+        }
+        if ((char *)bucket->next_unused - (char *)bucket->entries + sizeof(*dc_attr) <=
+            system_info.AllocationGranularity)
+        {
+            dc_attr = bucket->next_unused++;
+            break;
+        }
+    }
+
+    if (!dc_attr && (bucket = malloc( sizeof(*bucket) )))
+    {
+        SIZE_T size = system_info.AllocationGranularity;
+        bucket->entries = NULL;
+        if (!NtAllocateVirtualMemory( GetCurrentProcess(), (void **)&bucket->entries, 0, &size,
+                                      MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ))
+        {
+            bucket->next_free = NULL;
+            bucket->next_unused = bucket->entries + 1;
+            dc_attr = bucket->entries;
+            list_add_head( &dc_attr_buckets, &bucket->entry );
+        }
+        else free( bucket );
+    }
+
+    if (dc_attr) memset( dc_attr, 0, sizeof( *dc_attr ));
+
+    pthread_mutex_unlock( &dc_attr_lock );
+
+    return dc_attr;
+}
+
+
+static void free_dc_attr( DC_ATTR *dc_attr )
+{
+    struct dc_attr_bucket *bucket;
+
+    pthread_mutex_lock( &dc_attr_lock );
+
+    LIST_FOR_EACH_ENTRY( bucket, &dc_attr_buckets, struct dc_attr_bucket, entry )
+    {
+        if (bucket->entries > dc_attr || dc_attr >= bucket->next_unused) continue;
+        *(void **)dc_attr = bucket->next_free;
+        bucket->next_free = dc_attr;
+        break;
+    }
+
+    pthread_mutex_unlock( &dc_attr_lock );
+}
+
 
 /***********************************************************************
  *           set_initial_dc_state
@@ -133,7 +211,7 @@ DC *alloc_dc_ptr( DWORD magic )
     DC *dc;
 
     if (!(dc = calloc( 1, sizeof(*dc) ))) return NULL;
-    if (!(dc->attr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dc->attr) )))
+    if (!(dc->attr = alloc_dc_attr()))
     {
         free( dc );
         return NULL;
@@ -152,7 +230,7 @@ DC *alloc_dc_ptr( DWORD magic )
 
     if (!(dc->hSelf = alloc_gdi_handle( &dc->obj, magic, &dc_funcs )))
     {
-        RtlFreeHeap( GetProcessHeap(), 0, dc->attr );
+        free_dc_attr( dc->attr );
         free( dc );
         return NULL;
     }
@@ -179,7 +257,7 @@ static void free_dc_state( DC *dc )
     if (dc->hVisRgn) NtGdiDeleteObjectApp( dc->hVisRgn );
     if (dc->region) NtGdiDeleteObjectApp( dc->region );
     if (dc->path) free_gdi_path( dc->path );
-    RtlFreeHeap( GetProcessHeap(), 0, dc->attr );
+    free_dc_attr( dc->attr );
     free( dc );
 }
 




More information about the wine-cvs mailing list