[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