Corinna Vinschen
2011-06-18 20:17:24 UTC
Hi gang,
I just read something interesting on MSDN which only affects 64 bit systems:
"If the application has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag set in the
image header, each 32-bit application receives 4 GB of virtual address
space in the WOW64 environment. If the IMAGE_FILE_LARGE_ADDRESS_AWARE
flag is not set, each 32-bit application receives 2 GB of virtual address
space in the WOW64 environment."
So, with this flag set, a WOW64 process has the full 4 Gigs address
space and none of that is taken by the OS? That sounds cool.
That means, if we make all Cygwin binaries large address aware, somebody
using a 64 bit system could rebase all Cygwin DLLs, except for the
Cygwin DLL itself into the virtual memory area beyond 0x80000000. Given
that this memory area is not at all used by Windows itself, it's free
for usage by Cygwin alone. This would affect the memory allocation not
only for Cygwin DLLs, but also for mmaps and for thread stacks, which
both use the MEM_TOP_DOWN flag.
If I get this right, this should ease the fork pain due to memory collisions
on 64 bit systems quite a lot.
So I made an experiment, using the Cygwin DLL from CVS to get the new
extended /proc/$PID/maps output. I converted all .exe files in /bin to
have the large-address awareness flag on, then I rebased all DLLs into
the high memory area, kind of like this:
C:\> cd \cygwin\bin
C:\cygwin\bin> copy dash.exe ..
C:\cygwin\bin> copy peflags.exe ..
C:\cygwin\bin> path C:\cygwin\bin;%path%
C:\cygwin\bin> ..\dash
$ ../peflags --bigaddr=1 *.exe
$ rebaseall -b 0xe0000000
This really works. If you check the /proc/$PID/maps file, you see how
the Cygwin DLLs, the PEB and TEBs, (non-fixed) mmaps and thread stacks
are placed into the large address area.
The downside is that moving the DLLs into the large address area potentially
breaks executables which are not large-address aware. They will run fine
as long as they don't try to fork. I tried that with bash. It's not fun:
[~]$ peflags --bigaddr=0 /bin/bash
[~]$ bash
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
bash-4.1$ exit
[~]$ peflags --bigaddr=1 /bin/bash
[~]$ bash
***@vmw2k8r2 ~/tests
$
This obviously also affects all non-distro executables, such as self-
compiled stuff. All of them need the --bigaddr flag set, too.
Therefore it might be quite tricky to maintain a sane system, given that
gcc creates executables with the large address awareness flag switched
off, and given the fact that the flag is reset for a distro executable
every time it gets updated via setup.
However, if anybody feels confident to test this on the own machine,
I'd be curious if that has the desired effect of letting fork work
more reliable. I'm not sure I have the required use cases to test
this sufficiently.
Corinna
I just read something interesting on MSDN which only affects 64 bit systems:
"If the application has the IMAGE_FILE_LARGE_ADDRESS_AWARE flag set in the
image header, each 32-bit application receives 4 GB of virtual address
space in the WOW64 environment. If the IMAGE_FILE_LARGE_ADDRESS_AWARE
flag is not set, each 32-bit application receives 2 GB of virtual address
space in the WOW64 environment."
So, with this flag set, a WOW64 process has the full 4 Gigs address
space and none of that is taken by the OS? That sounds cool.
That means, if we make all Cygwin binaries large address aware, somebody
using a 64 bit system could rebase all Cygwin DLLs, except for the
Cygwin DLL itself into the virtual memory area beyond 0x80000000. Given
that this memory area is not at all used by Windows itself, it's free
for usage by Cygwin alone. This would affect the memory allocation not
only for Cygwin DLLs, but also for mmaps and for thread stacks, which
both use the MEM_TOP_DOWN flag.
If I get this right, this should ease the fork pain due to memory collisions
on 64 bit systems quite a lot.
So I made an experiment, using the Cygwin DLL from CVS to get the new
extended /proc/$PID/maps output. I converted all .exe files in /bin to
have the large-address awareness flag on, then I rebased all DLLs into
the high memory area, kind of like this:
C:\> cd \cygwin\bin
C:\cygwin\bin> copy dash.exe ..
C:\cygwin\bin> copy peflags.exe ..
C:\cygwin\bin> path C:\cygwin\bin;%path%
C:\cygwin\bin> ..\dash
$ ../peflags --bigaddr=1 *.exe
$ rebaseall -b 0xe0000000
This really works. If you check the /proc/$PID/maps file, you see how
the Cygwin DLLs, the PEB and TEBs, (non-fixed) mmaps and thread stacks
are placed into the large address area.
The downside is that moving the DLLs into the large address area potentially
breaks executables which are not large-address aware. They will run fine
as long as they don't try to fork. I tried that with bash. It's not fun:
[~]$ peflags --bigaddr=0 /bin/bash
[~]$ bash
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: retry: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
bash-4.1$ exit
[~]$ peflags --bigaddr=1 /bin/bash
[~]$ bash
***@vmw2k8r2 ~/tests
$
This obviously also affects all non-distro executables, such as self-
compiled stuff. All of them need the --bigaddr flag set, too.
Therefore it might be quite tricky to maintain a sane system, given that
gcc creates executables with the large address awareness flag switched
off, and given the fact that the flag is reset for a distro executable
every time it gets updated via setup.
However, if anybody feels confident to test this on the own machine,
I'd be curious if that has the desired effect of letting fork work
more reliable. I'm not sure I have the required use cases to test
this sufficiently.
Corinna
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat