Non-working patch for 3GB of memory allocation

Shachar Shemesh wine-devel at shemesh.biz
Mon Jul 26 10:04:37 CDT 2004


Ok, this patch would probably not be appropriate even if it did work. 
The surprising thing, however, is that it doesn't.

The idea was simple. We use mmap as usual until mmap starts to fail with 
no memory. When that happens, we switch to allocating memory with 
malloc, which allegably knows how to use "brk" in order to allocate 
memory from the lower 1GB area.

The patch is against 20040716.

The attached program tries to repeatedly allocate ~100MB, until it 
fails. It is compiled for advanced server (i.e. - it has 3GB of address 
space, but that's besides the point).

When actually run (through strace), one can see the mmaps being carried 
out and successful, and then the mmap that fails (no memory). Then 
malloc is attempted, which tries mmap, then brk, and then mmap again. 
All fail. This is the point where I stop understanding.

Does anyone have any explanation as to why malloc fails? Does wine 
prevent large scale use of the lower area due to some reason?

Any ideas would be appreciated.

                Shachar
-------------- next part --------------
? runconfig
? dlls/ntdll/.virtual.c.swp
Index: dlls/ntdll/virtual.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/virtual.c,v
retrieving revision 1.37
diff -u -r1.37 virtual.c
--- dlls/ntdll/virtual.c	22 Jun 2004 03:02:35 -0000	1.37
+++ dlls/ntdll/virtual.c	26 Jul 2004 13:53:41 -0000
@@ -78,6 +78,7 @@
 /* Per-view flags */
 #define VFLAG_SYSTEM     0x01  /* system view (underlying mmap not under our control) */
 #define VFLAG_VALLOC     0x02  /* allocated by VirtualAlloc */
+#define VFLAG_MALLOC     0x04  /* allocated using malloc */
 
 /* Conversion from VPROT_* to Win32 flags */
 static const BYTE VIRTUAL_Win32Flags[16] =
@@ -168,9 +169,13 @@
     DPRINTF( "View: %p - %p", addr, addr + view->size - 1 );
     if (view->flags & VFLAG_SYSTEM)
         DPRINTF( " (system)\n" );
-    else if (view->flags & VFLAG_VALLOC)
-        DPRINTF( " (valloc)\n" );
-    else if (view->mapping)
+    else if (view->flags & VFLAG_VALLOC) {
+        DPRINTF( " (valloc" );
+	if (view->flags & VFLAG_MALLOC)
+	    DPRINTF( " using malloc)\n" );
+	else
+	    DPRINTF( ")\n" );
+    } else if (view->mapping)
         DPRINTF( " %p\n", view->mapping );
     else
         DPRINTF( " (anonymous)\n");
@@ -348,7 +353,12 @@
  */
 static void delete_view( struct file_view *view ) /* [in] View */
 {
-    if (!(view->flags & VFLAG_SYSTEM)) unmap_area( view->base, view->size );
+    if (!(view->flags & VFLAG_SYSTEM)) {
+	if( !(view->flags & VFLAG_MALLOC) )
+	    unmap_area( view->base, view->size );
+	else
+	    free( view->base );
+    }
     list_remove( &view->entry );
     if (view->mapping) NtClose( view->mapping );
     free( view );
@@ -559,6 +569,7 @@
 {
     void *ptr;
     NTSTATUS status;
+    int used_malloc=0;
 
     if (base)
     {
@@ -602,7 +613,19 @@
         {
             if ((ptr = wine_anon_mmap( NULL, view_size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
             {
-                if (errno == ENOMEM) return STATUS_NO_MEMORY;
+                if (errno == ENOMEM)
+		{
+		    /* mmap allocation failed. Let's see if we can try malloc, and whether it is going to be more lucky */
+		    FIXME("About to try malloc\n");
+		    if( /* Unix protection is not malloc compatible, or */ (ptr = malloc( size ))!=NULL )
+		    {
+			used_malloc=1;
+			goto memory_allocated;
+		    } else {
+			FIXME("malloc failed\n");
+			return STATUS_NO_MEMORY;
+		    }
+		}
                 return STATUS_INVALID_PARAMETER;
             }
             /* if we got something beyond the user limit, unmap it and retry */
@@ -623,8 +646,17 @@
             munmap( (char *)ptr + size, view_size - size );
     }
 
+memory_allocated:
     status = create_view( view_ret, ptr, size, vprot );
-    if (status != STATUS_SUCCESS) unmap_area( ptr, size );
+    if( used_malloc && status==STATUS_SUCCESS )
+	(*view_ret)->flags|=VFLAG_MALLOC;
+    else if (status != STATUS_SUCCESS)
+    {
+	if( !used_malloc )
+	    unmap_area( ptr, size );
+	else
+	    free( ptr );
+    }
     return status;
 }
 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: MemoryAllocation.zip
Type: application/zip
Size: 24461 bytes
Desc: not available
Url : http://www.winehq.org/pipermail/wine-devel/attachments/20040726/d387e1be/MemoryAllocation.zip


More information about the wine-devel mailing list