[PATCH] Large processes shared.cc fix

Eizenberg Ariel arielez@cs.huji.ac.il
Fri Dec 31 13:58:00 GMT 2004


Hi,

This patch fixes a problem I have with running large fortran programs
(actually most programs with a very large image size in memory). The
problem occurs on Windows 2000, XP and 2003.

The problem occurs when a process is large enough so when open_shared()
tries to map the shared memory section to 0x0A000000, it fails, since
0x0A000000 is occupied by the program. Since the
MapViewOfFileEx(h,...,NULL) is preformed on a region smaller than the full
region required for offsets[SH_TOTAL_SIZE], MapViewOfFileEx might allocate
a region at a location which does not have enough free space after it,
so the VirtualAlloc's at the end of open_shared() silently fail
(in my case MapViewOfFileEx() returns 0x3d0000).

The patch fixed the problem by looking for a region large enough for
offsets[SH_TOTAL_SIZE], and using this region as the base address for
offsets[0] instead.

I would greatly appreciate if you could integrate this patch into
mainstream Cygwin.

The `cvs diff -up` patch is attached as TEXT/PLAIN.

The ChangeLog entry is:

* shared.cc (open_shared): Fix allocation of shared region for large
processes.

Thanks.




-------------- next part --------------
Index: shared.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/shared.cc,v
retrieving revision 1.84
diff -u -p -r1.84 shared.cc
--- shared.cc	3 Dec 2004 02:00:37 -0000	1.84
+++ shared.cc	31 Dec 2004 12:39:00 -0000
@@ -103,6 +103,53 @@ open_shared (const char *name, int n, HA
 	api_fatal ("CreateFileMapping %s, %E.  Terminating.", mapname);
     }
 
+  if (m == SH_CYGWIN_SHARED && wincap.needs_memory_protection ())
+  {
+	 // ariel_e: we need to make sure we have enough space to reserve 
+	 // (with VirtualAlloc(MEM_RESERVE) after 'shared', so we 
+	 // ask for a memory location large enough to hold all
+	 // shared data. After we get a valid location,
+	 // we unmap it and try to map only the actual amount currently 
+	 // required
+	 
+	 DWORD size_needed = offsets[SH_TOTAL_SIZE] - offsets[0];
+	 void* old_addr = addr;
+
+	 HANDLE tmp_map = CreateFileMapping(INVALID_HANDLE_VALUE,
+			 		NULL, // attributes 
+					PAGE_READWRITE | SEC_RESERVE,
+					0, // max size high,
+					size_needed,
+					NULL);
+
+	 if(tmp_map == NULL)
+		api_fatal("Failed to reserve memory: %E\n");
+
+	 addr = MapViewOfFileEx (tmp_map, FILE_MAP_READ | FILE_MAP_WRITE, 
+				 0, 0, 0, addr);
+
+	 if(addr == NULL)
+	 {
+		// try again without a predetermined address
+    		addr = MapViewOfFileEx (tmp_map, 
+					FILE_MAP_READ | FILE_MAP_WRITE, 
+					0, 0, 0, NULL);
+
+		if(addr == NULL)
+		{
+			// failed to reserve memory, to maintain old 
+			// compatibility we use original addr
+			addr = old_addr;
+		}
+	 }
+
+	UnmapViewOfFile(addr);
+	CloseHandle(tmp_map);
+
+	// now we are ready to map the actual required amount of memory
+	// at the address we know has enough free space for everything
+  }
+
   shared = (shared_info *)
     MapViewOfFileEx (shared_h, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, addr);
 


More information about the Cygwin-patches mailing list