From: Corinna Vinschen Date: Tue, 31 Oct 2006 18:41:16 +0000 (+0000) Subject: * cygheap.h (struct user_heap_info): Add slop member. X-Git-Tag: gdb_6_6-2006-11-15-branchpoint~27 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=c2b10dc4d83b4bfba357eb6cfc4b7698dc8fef1c;p=newlib-cygwin.git * cygheap.h (struct user_heap_info): Add slop member. * heap.cc (heap_init): Add slop factor to heap allocation. Add comment. * mmap.cc (MapViewNT): Allocate memory maps top down. (fhandler_dev_zero::mmap): Ditto. * shared.cc (shared_info::heap_slop_size): New method. (shared_info::heap_chunk_size): Don't use debug_printf at early stage. * shared_info.h (SHARED_INFO_CB): Accomodate change to shared_info. (CURR_SHARED_MAGIC): Ditto. (class shared_info): Add heap_slop member. Declare heap_slop_size. * wincap.h: Define heapslop throughout. * wincap.cc: Ditto. --- diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fddfd6bf7..212bbabdb 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2006-10-31 Corinna Vinschen + + * cygheap.h (struct user_heap_info): Add slop member. + * heap.cc (heap_init): Add slop factor to heap allocation. Add + comment. + * mmap.cc (MapViewNT): Allocate memory maps top down. + (fhandler_dev_zero::mmap): Ditto. + * shared.cc (shared_info::heap_slop_size): New method. + (shared_info::heap_chunk_size): Don't use debug_printf at early stage. + * shared_info.h (SHARED_INFO_CB): Accomodate change to shared_info. + (CURR_SHARED_MAGIC): Ditto. + (class shared_info): Add heap_slop member. Declare heap_slop_size. + * wincap.h: Define heapslop throughout. + * wincap.cc: Ditto. + 2006-10-31 Corinna Vinschen * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 35db5cad8..85da8f6ed 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -262,6 +262,7 @@ struct user_heap_info void *top; void *max; unsigned chunk; + unsigned slop; }; struct hook_chain diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index 63fc93520..5278febfc 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -41,21 +41,38 @@ heap_init () if (!cygheap->user_heap.base) { cygheap->user_heap.chunk = cygwin_shared->heap_chunk_size (); + /* For some obscure reason Vista and 2003 sometimes reserve space after + calls to CreateProcess overlapping the spot where the heap has been + allocated. This apparently spoils fork. The behaviour looks quite + arbitrary. Experiments on Vista show a memory size of 0x37e000 or + 0x1fd000 overlapping the usual heap by at most 0x1ed000. So what + we do here is to allocate the heap with an extra slop of (by default) + 0x200000 and set the appropriate pointers to the start of the heap + area + slop. A forking child then creates its heap at the new start + address and without the slop factor. Since this is not entirely + foolproof we add a registry setting "heap_slop_in_mb" so the slop + factor can be influenced by the user if the need arises. */ + cygheap->user_heap.slop = cygwin_shared->heap_slop_size (); while (cygheap->user_heap.chunk >= MINHEAP_SIZE) { /* Initialize page mask and default heap size. Preallocate a heap * to assure contiguous memory. */ - cygheap->user_heap.ptr = cygheap->user_heap.top = cygheap->user_heap.base = - VirtualAlloc (NULL, cygheap->user_heap.chunk, alloctype, PAGE_NOACCESS); + VirtualAlloc (NULL, cygheap->user_heap.chunk + + cygheap->user_heap.slop, + alloctype, PAGE_NOACCESS); if (cygheap->user_heap.base) break; cygheap->user_heap.chunk -= 1 * 1024 * 1024; } if (cygheap->user_heap.base == NULL) - api_fatal ("unable to allocate heap, heap_chunk_size %d, %E", - cygheap->user_heap.chunk); - cygheap->user_heap.max = (char *) cygheap->user_heap.base + cygheap->user_heap.chunk; + api_fatal ("unable to allocate heap, heap_chunk_size %p, slop %p, %E", + cygheap->user_heap.chunk, cygheap->user_heap.slop); + cygheap->user_heap.base = (void *) ((char *) cygheap->user_heap.base + + cygheap->user_heap.slop); + cygheap->user_heap.ptr = cygheap->user_heap.top = cygheap->user_heap.base; + cygheap->user_heap.max = (char *) cygheap->user_heap.base + + cygheap->user_heap.chunk; } else { diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 1c1afba57..31bac5869 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -350,7 +350,8 @@ MapViewNT (HANDLE h, void *addr, size_t len, DWORD openflags, void *base = addr; ULONG commitsize = attached (prot) ? 0 : len; ULONG viewsize = len; - ULONG alloc_type = base && !wincap.is_wow64 () ? AT_ROUND_TO_PAGE : 0; + ULONG alloc_type = (base && !wincap.is_wow64 () ? AT_ROUND_TO_PAGE : 0) + | MEM_TOP_DOWN; /* Try mapping using the given address first, even if it's NULL. If it failed, and addr was not NULL and flags is not MAP_FIXED, @@ -1669,7 +1670,8 @@ fhandler_dev_zero::mmap (caddr_t *addr, size_t len, int prot, when using the (non-POSIX, yay-Linux) MAP_NORESERVE flag. */ DWORD protect = gen_protect (prot, flags); - DWORD alloc_type = MEM_RESERVE | (noreserve (flags) ? 0 : MEM_COMMIT); + DWORD alloc_type = MEM_TOP_DOWN | MEM_RESERVE + | (noreserve (flags) ? 0 : MEM_COMMIT); base = VirtualAlloc (*addr, len, alloc_type, protect); if (!base && addr && !fixed (flags)) base = VirtualAlloc (NULL, len, alloc_type, protect); diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index 65965b58b..4c4b7bc72 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -234,6 +234,33 @@ memory_init () mtinfo_init (); } +unsigned +shared_info::heap_slop_size () +{ + if (!heap_slop) + { + /* Fetch from registry, first user then local machine. */ + for (int i = 0; i < 2; i++) + { + reg_key reg (i, KEY_READ, NULL); + + if ((heap_slop = reg.get_int ("heap_slop_in_mb", 0))) + break; + heap_slop = wincap.heapslop (); + } + + if (heap_slop < 0) + heap_slop = 0; + else + heap_slop <<= 20; +#ifdef DEBUGGING + system_printf ("fixed heap slop is %p", heap_slop); +#endif + } + + return heap_slop; +} + unsigned shared_info::heap_chunk_size () { @@ -260,7 +287,9 @@ shared_info::heap_chunk_size () heap_chunk <<= 20; if (!heap_chunk) heap_chunk = 384 * 1024 * 1024; - debug_printf ("fixed heap size is %u", heap_chunk); +#ifdef DEBUGGING + system_printf ("fixed heap size is %u", heap_chunk); +#endif } return heap_chunk; diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index ff9361605..a1a4be0db 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -143,9 +143,9 @@ public: cygwin_version.api_minor) #define SHARED_VERSION_MAGIC CYGWIN_VERSION_MAGIC (SHARED_MAGIC, SHARED_VERSION) -#define SHARED_INFO_CB 19984 +#define SHARED_INFO_CB 19988 -#define CURR_SHARED_MAGIC 0x818f75beU +#define CURR_SHARED_MAGIC 0xb632a4cU /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between @@ -156,11 +156,13 @@ class shared_info DWORD cb; public: unsigned heap_chunk; + unsigned heap_slop; DWORD sys_mount_table_counter; tty_list tty; void initialize (); unsigned heap_chunk_size (); + unsigned heap_slop_size (); }; extern shared_info *cygwin_shared; diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 9c82e45a7..df6765b7b 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -14,6 +14,7 @@ details. */ static NO_COPY wincaps wincap_unknown = { lock_file_highword:0x0, chunksize:0x0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -72,6 +73,7 @@ static NO_COPY wincaps wincap_unknown = { static NO_COPY wincaps wincap_95 = { lock_file_highword:0x0, chunksize:32 * 1024 * 1024, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -130,6 +132,7 @@ static NO_COPY wincaps wincap_95 = { static NO_COPY wincaps wincap_95osr2 = { lock_file_highword:0x0, chunksize:32 * 1024 * 1024, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -188,6 +191,7 @@ static NO_COPY wincaps wincap_95osr2 = { static NO_COPY wincaps wincap_98 = { lock_file_highword:0x0, chunksize:32 * 1024 * 1024, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -246,6 +250,7 @@ static NO_COPY wincaps wincap_98 = { static NO_COPY wincaps wincap_98se = { lock_file_highword:0x0, chunksize:32 * 1024 * 1024, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -304,6 +309,7 @@ static NO_COPY wincaps wincap_98se = { static NO_COPY wincaps wincap_me = { lock_file_highword:0x0, chunksize:32 * 1024 * 1024, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE, is_winnt:false, is_server:false, @@ -362,6 +368,7 @@ static NO_COPY wincaps wincap_me = { static NO_COPY wincaps wincap_nt3 = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:false, @@ -420,6 +427,7 @@ static NO_COPY wincaps wincap_nt3 = { static NO_COPY wincaps wincap_nt4 = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:false, @@ -478,6 +486,7 @@ static NO_COPY wincaps wincap_nt4 = { static NO_COPY wincaps wincap_nt4sp4 = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:false, @@ -536,6 +545,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { static NO_COPY wincaps wincap_2000 = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:false, @@ -594,6 +604,7 @@ static NO_COPY wincaps wincap_2000 = { static NO_COPY wincaps wincap_xp = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x0, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:false, @@ -652,6 +663,7 @@ static NO_COPY wincaps wincap_xp = { static NO_COPY wincaps wincap_2003 = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x4, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:true, @@ -710,6 +722,7 @@ static NO_COPY wincaps wincap_2003 = { static NO_COPY wincaps wincap_vista = { lock_file_highword:UINT32_MAX, chunksize:0, + heapslop:0x4, shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, is_winnt:true, is_server:true, diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 0f1b95a15..bbd58a60b 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -15,6 +15,7 @@ struct wincaps { DWORD lock_file_highword; DWORD chunksize; + DWORD heapslop; int shared; unsigned is_winnt : 1; unsigned is_server : 1; @@ -89,6 +90,7 @@ public: DWORD IMPLEMENT (lock_file_highword) DWORD IMPLEMENT (chunksize) + DWORD IMPLEMENT (heapslop) int IMPLEMENT (shared) bool IMPLEMENT (is_winnt) bool IMPLEMENT (is_server)