diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f84535e6c..a204f9f81 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2002-10-22 Christopher Faylor + + * cygheap.cc (cygheap_fixup_in_child): Use user_heap element in + cygheap. + (init_cheap): Ditto for declaration. + * fork.cc (fork_parent): Use user_heap element in cygheap. + * heap.h (inheap): Ditto. + * heap.cc (sbrk): Ditto. + (heap_init): Ditto. Reorganize to shrink heap chunk as required and + record new value in cygheap. + * dcrt0.cc (dll_crt0_1): More "move the cygthread init" games. + * shared.cc (open_shared): Rework memory protection to properly deal + with relocated shared segment. + (shared_info::heap_chunk_size): Rename element to 'heap_chunk'. + * shared_info.h (shared_info): Ditto for declaration. + * strace.cc (strace::hello): Report on heap chunk size from cygheap + since it may shrink. + 2002-10-20 Christopher Faylor Change _function() to function() throughout. diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index e4ea673d0..0bfb06a7e 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -156,7 +156,7 @@ cygheap_fixup_in_child (bool execed) if (execed) { - cygheap->heapbase = NULL; /* We can allocate the heap anywhere */ + cygheap->user_heap.base = NULL; /* We can allocate the heap anywhere */ /* Walk the allocated memory chain looking for orphaned memory from previous execs */ for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev) diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index fd784ae95..703c1d1dc 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -198,18 +198,21 @@ struct cygheap_debug }; #endif +struct user_heap_info +{ + void *base; + void *ptr; + void *top; + unsigned chunk; +}; + struct init_cygheap { _cmalloc_entry *chain; char *buckets[32]; - struct /* User heap stuff. */ - { - void *heapbase; - void *heapptr; - void *heaptop; - }; cygheap_root root; cygheap_user user; + user_heap_info user_heap; mode_t umask; HANDLE shared_h; HANDLE console_h; diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index febb2004e..89c9a4456 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -585,11 +585,11 @@ dll_crt0_1 () { case _PROC_FORK: alloc_stack (fork_info); - cygthread::init (); cygheap_fixup_in_child (0); - close_ppid_handle = !!child_proc_info->pppid_handle; memory_init (); + cygthread::init (); set_myself (mypid); + close_ppid_handle = !!child_proc_info->pppid_handle; break; case _PROC_SPAWN: /* Have to delay closes until after cygheap is setup */ diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc index 592381cde..76e26fe6e 100644 --- a/winsup/cygwin/dll_init.cc +++ b/winsup/cygwin/dll_init.cc @@ -261,8 +261,10 @@ release_upto (const char *name, DWORD here) { size = mb.RegionSize; if (!(mb.State == MEM_RESERVE && mb.AllocationProtect == PAGE_NOACCESS && - (((void *) start < cygheap->heapbase || (void *) start > cygheap->heaptop) && - ((void *) start < (void *) cygheap || (void *) start > (void *) ((char *) cygheap + CYGHEAPSIZE))))) + (((void *) start < cygheap->user_heap.base + || (void *) start > cygheap->user_heap.top) && + ((void *) start < (void *) cygheap + | (void *) start > (void *) ((char *) cygheap + CYGHEAPSIZE))))) continue; if (!VirtualFree ((void *) start, 0, MEM_RELEASE)) api_fatal ("couldn't release memory %p(%d) for '%s' alignment, %E\n", diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index 485bd17ea..165c794ca 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -551,7 +551,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll, rc = fork_copy (pi, "user/cygwin data", user_data->data_start, user_data->data_end, user_data->bss_start, user_data->bss_end, - cygheap->heapbase, cygheap->heapptr, + cygheap->user_heap.base, cygheap->user_heap.ptr, stack_here, ch.stackbottom, dll_data_start, dll_data_end, dll_bss_start, dll_bss_end, NULL); diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc index c850a796c..19ce3f875 100644 --- a/winsup/cygwin/heap.cc +++ b/winsup/cygwin/heap.cc @@ -20,6 +20,8 @@ details. */ #include "path.h" #include "dtable.h" #include "cygheap.h" +#include "registry.h" +#include "cygwin_version.h" #define assert(x) @@ -27,6 +29,8 @@ static unsigned page_const; extern "C" size_t getpagesize (); +#define MINHEAP_SIZE (4 * 1024 * 1024) + /* Initialize the heap at process start up. */ void @@ -36,19 +40,40 @@ heap_init () as our parent. If not, we don't care where it ends up. */ page_const = system_info.dwPageSize; - if (cygheap->heapbase) + if (!cygheap->user_heap.base) { - DWORD chunk = cygwin_shared->heap_chunk_size (); /* allocation chunk */ + cygheap->user_heap.chunk = cygwin_shared->heap_chunk_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, MEM_RESERVE, 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); + } + else + { + DWORD chunk = cygheap->user_heap.chunk; /* allocation chunk */ /* total size commited in parent */ - DWORD allocsize = (char *) cygheap->heaptop - (char *) cygheap->heapbase; + DWORD allocsize = (char *) cygheap->user_heap.top - + (char *) cygheap->user_heap.base; /* round up by chunk size */ DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk); /* Loop until we've managed to reserve an adequate amount of memory. */ char *p; +MEMORY_BASIC_INFORMATION m; +(void) VirtualQuery (cygheap->user_heap.base, &m, sizeof (m)); for (;;) { - p = (char *) VirtualAlloc (cygheap->heapbase, reserve_size, + p = (char *) VirtualAlloc (cygheap->user_heap.base, reserve_size, MEM_RESERVE, PAGE_READWRITE); if (p) break; @@ -56,27 +81,25 @@ heap_init () break; } if (p == NULL) - api_fatal ("1. unable to allocate heap %p, heap_chunk_size %d, pid %d, %E", - cygheap->heapbase, cygwin_shared->heap_chunk_size (), myself->pid); - if (p != cygheap->heapbase) - api_fatal ("heap allocated but not at %p", cygheap->heapbase); - if (!VirtualAlloc (cygheap->heapbase, allocsize, MEM_COMMIT, PAGE_READWRITE)) +{ +system_printf ("unable to allocate heap %p, chunk %u, reserve %u, alloc %u, %E", +cygheap->user_heap.base, cygheap->user_heap.chunk, +reserve_size, allocsize); +system_printf ("base %p mem alloc base %p, state %p, size %d, %E", +cygheap->user_heap.base, m.AllocationBase, m.State, m.RegionSize); +error_start_init ("h:/gdbtest/gdb.exe < con > con"); try_to_debug (); + api_fatal ("unable to allocate heap %p, chunk %u, reserve %u, alloc %u, %E", + cygheap->user_heap.base, cygheap->user_heap.chunk, + reserve_size, allocsize); +} + if (p != cygheap->user_heap.base) + api_fatal ("heap allocated but not at %p", cygheap->user_heap.base); + if (!VirtualAlloc (cygheap->user_heap.base, allocsize, MEM_COMMIT, PAGE_READWRITE)) api_fatal ("MEM_COMMIT failed, %E"); } - else - { - /* Initialize page mask and default heap size. Preallocate a heap - * to assure contiguous memory. */ - cygheap->heapptr = cygheap->heaptop = cygheap->heapbase = - VirtualAlloc (NULL, cygwin_shared->heap_chunk_size (), MEM_RESERVE, - PAGE_NOACCESS); - if (cygheap->heapbase == NULL) - api_fatal ("2. unable to allocate heap, heap_chunk_size %d, %E", - cygwin_shared->heap_chunk_size ()); - } - debug_printf ("heap base %p, heap top %p", cygheap->heapbase, - cygheap->heaptop); + debug_printf ("heap base %p, heap top %p", cygheap->user_heap.base, + cygheap->user_heap.top); page_const--; malloc_init (); } @@ -93,43 +116,43 @@ sbrk (int n) unsigned commitbytes, newbrksize; if (n == 0) - return cygheap->heapptr; /* Just wanted to find current cygheap->heapptr address */ + return cygheap->user_heap.ptr; /* Just wanted to find current cygheap->user_heap.ptr address */ - newbrk = (char *) cygheap->heapptr + n; /* Where new cygheap->heapptr will be */ + newbrk = (char *) cygheap->user_heap.ptr + n; /* Where new cygheap->user_heap.ptr will be */ newtop = (char *) pround (newbrk); /* Actual top of allocated memory - on page boundary */ - if (newtop == cygheap->heaptop) + if (newtop == cygheap->user_heap.top) goto good; if (n < 0) { /* Freeing memory */ - assert (newtop < cygheap->heaptop); - n = (char *) cygheap->heaptop - newtop; + assert (newtop < cygheap->user_heap.top); + n = (char *) cygheap->user_heap.top - newtop; if (VirtualFree (newtop, n, MEM_DECOMMIT)) /* Give it back to OS */ goto good; /* Didn't take */ else goto err; } - assert (newtop > cygheap->heaptop); + assert (newtop > cygheap->user_heap.top); /* Need to grab more pages from the OS. If this fails it may be because * we have used up previously reserved memory. Or, we're just plumb out * of memory. */ - commitbytes = pround (newtop - (char *) cygheap->heaptop); - if (VirtualAlloc (cygheap->heaptop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL) + commitbytes = pround (newtop - (char *) cygheap->user_heap.top); + if (VirtualAlloc (cygheap->user_heap.top, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL) goto good; /* Couldn't allocate memory. Maybe we can reserve some more. Reserve either the maximum of the standard cygwin_shared->heap_chunk_size () or the requested amount. Then attempt to actually allocate it. */ - if ((newbrksize = cygwin_shared->heap_chunk_size ()) < commitbytes) + if ((newbrksize = cygheap->user_heap.chunk) < commitbytes) newbrksize = commitbytes; - if ((VirtualAlloc (cygheap->heaptop, newbrksize, MEM_RESERVE, PAGE_NOACCESS) != NULL) && - (VirtualAlloc (cygheap->heaptop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)) + if ((VirtualAlloc (cygheap->user_heap.top, newbrksize, MEM_RESERVE, PAGE_NOACCESS) != NULL) && + (VirtualAlloc (cygheap->user_heap.top, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)) goto good; err: @@ -137,8 +160,8 @@ err: return (void *) -1; good: - void *oldbrk = cygheap->heapptr; - cygheap->heapptr = newbrk; - cygheap->heaptop = newtop; + void *oldbrk = cygheap->user_heap.ptr; + cygheap->user_heap.ptr = newbrk; + cygheap->user_heap.top = newtop; return oldbrk; } diff --git a/winsup/cygwin/heap.h b/winsup/cygwin/heap.h index bcea4bae0..b497dd3a4 100644 --- a/winsup/cygwin/heap.h +++ b/winsup/cygwin/heap.h @@ -15,5 +15,6 @@ void heap_init (); void malloc_init (); #define inheap(s) \ - (cygheap->heapptr && s && ((char *) (s) >= (char *) cygheap->heapbase) \ - && ((char *) (s) <= (char *) cygheap->heaptop)) + (cygheap->user_heap.ptr && s \ + && ((char *) (s) >= (char *) cygheap->user_heap.base) \ + && ((char *) (s) <= (char *) cygheap->user_heap.top)) diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index ba370f834..8aaa3c655 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -47,28 +47,29 @@ shared_name (const char *str, int num) #define page_const (65535) #define pround(n) (((size_t) (n) + page_const) & ~page_const) +static char *offsets[] = +{ + (char *) cygwin_shared_address, + (char *) cygwin_shared_address + + pround (sizeof (shared_info)), + (char *) cygwin_shared_address + + pround (sizeof (shared_info)) + + pround (sizeof (mount_info)), + (char *) cygwin_shared_address + + pround (sizeof (shared_info)) + + pround (sizeof (mount_info)) + + pround (sizeof (console_state)), + (char *) cygwin_shared_address + + pround (sizeof (shared_info)) + + pround (sizeof (mount_info)) + + pround (sizeof (console_state)) + + pround (sizeof (_pinfo)) +}; + void * __stdcall open_shared (const char *name, int n, HANDLE &shared_h, DWORD size, shared_locations m) { void *shared; - static char *offsets[] = - { - (char *) cygwin_shared_address, - (char *) cygwin_shared_address - + pround (sizeof (shared_info)), - (char *) cygwin_shared_address - + pround (sizeof (shared_info)) - + pround (sizeof (mount_info)), - (char *) cygwin_shared_address - + pround (sizeof (shared_info)) - + pround (sizeof (mount_info)) - + pround (sizeof (console_state)), - (char *) cygwin_shared_address - + pround (sizeof (shared_info)) - + pround (sizeof (mount_info)) - + pround (sizeof (console_state)) - + pround (sizeof (_pinfo)) - }; void *addr; if (!wincap.needs_memory_protection ()) @@ -117,16 +118,18 @@ open_shared (const char *name, int n, HANDLE &shared_h, DWORD size, shared_locat if (!shared) api_fatal ("MapViewOfFileEx '%s'(%p), %E. Terminating.", name, shared_h); - if (m == SH_CYGWIN_SHARED) + if (m == SH_CYGWIN_SHARED && wincap.needs_memory_protection ()) { + unsigned delta = (char *) shared - offsets[0]; + offsets[0] = (char *) shared; for (int i = SH_CYGWIN_SHARED + 1; i < SH_TOTAL_SIZE; i++) { - offsets[i] += (char *) shared - offsets[0]; - if (!VirtualAlloc (offsets[i], offsets[i + 1] - offsets[i], - MEM_RESERVE, PAGE_NOACCESS)) + unsigned size = offsets[i + 1] - offsets[i]; + offsets[i] += delta; + if (!VirtualAlloc (offsets[i], size, MEM_RESERVE, PAGE_NOACCESS)) continue; /* oh well */ - offsets[0] = (char *) shared; } + offsets[SH_TOTAL_SIZE] += delta; #if 0 if (!child_proc_info && wincap.needs_memory_protection ()) @@ -137,9 +140,6 @@ open_shared (const char *name, int n, HANDLE &shared_h, DWORD size, shared_locat debug_printf ("name %s, shared %p (wanted %p), h %p", name, shared, addr, shared_h); - /* FIXME: I couldn't find anywhere in the documentation a note about - whether the memory is initialized to zero. The code assumes it does - and since this part seems to be working, we'll leave it as is. */ return shared; } @@ -229,7 +229,7 @@ memory_init () unsigned shared_info::heap_chunk_size () { - if (!initial_heap_size) + if (!heap_chunk) { /* Fetch misc. registry entries. */ @@ -240,20 +240,20 @@ shared_info::heap_chunk_size () /* FIXME: We should not be restricted to a fixed size heap no matter what the fixed size is. */ - initial_heap_size = reg.get_int ("heap_chunk_in_mb", 0); - if (!initial_heap_size) { + heap_chunk = reg.get_int ("heap_chunk_in_mb", 0); + if (!heap_chunk) { reg_key r1 (HKEY_LOCAL_MACHINE, KEY_READ, "SOFTWARE", CYGWIN_INFO_CYGNUS_REGISTRY_NAME, CYGWIN_INFO_CYGWIN_REGISTRY_NAME, NULL); - initial_heap_size = reg.get_int ("heap_chunk_in_mb", 384); + heap_chunk = reg.get_int ("heap_chunk_in_mb", 384); } - if (initial_heap_size < 4) - initial_heap_size = 4 * 1024 * 1024; + if (heap_chunk < 4) + heap_chunk = 4 * 1024 * 1024; else - initial_heap_size <<= 20; - debug_printf ("fixed heap size is %u", initial_heap_size); + heap_chunk <<= 20; + debug_printf ("fixed heap size is %u", heap_chunk); } - return initial_heap_size; + return heap_chunk; } diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index c93fd6762..0156763e6 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -138,7 +138,7 @@ public: #define SHARED_INFO_CB 47112 -#define CURR_SHARED_MAGIC 0xd9e0bc22U +#define CURR_SHARED_MAGIC 0x359218a2U /* NOTE: Do not make gratuitous changes to the names or organization of the below class. The layout is checksummed to determine compatibility between @@ -148,7 +148,7 @@ class shared_info DWORD version; DWORD cb; public: - unsigned initial_heap_size; + unsigned heap_chunk; DWORD sys_mount_table_counter; tty_list tty; diff --git a/winsup/cygwin/strace.cc b/winsup/cygwin/strace.cc index cb367afeb..26f155aaa 100644 --- a/winsup/cygwin/strace.cc +++ b/winsup/cygwin/strace.cc @@ -14,12 +14,18 @@ details. */ #include #include #include +#include #include "pinfo.h" #include "perprocess.h" #include "cygwin_version.h" #include "hires.h" +#include "security.h" #include "cygthread.h" -#include "shared_info.h" +#include "fhandler.h" +#include "path.h" +#include "dtable.h" +#include "cygerrno.h" +#include "cygheap.h" #define PROTECT(x) x[sizeof (x)-1] = 0 #define CHECK(x) if (x[sizeof (x)-1] != 0) { small_printf ("array bound exceeded %d\n", __LINE__); ExitProcess (1); } @@ -58,7 +64,7 @@ strace::hello () cygwin_version.api_major, cygwin_version.api_minor); prntf (1, NULL, "DLL build: %s", cygwin_version.dll_build_date); prntf (1, NULL, "OS version: Windows %s", wincap.osname ()); - prntf (1, NULL, "Heap size: %u", cygwin_shared->heap_chunk_size ()); + prntf (1, NULL, "Heap size: %u", cygheap->user_heap.chunk); prntf (1, NULL, "**********************************************"); } }