* child_info.h (child_info::cygheap_h): Delete.

(child_info::dwProcessId): New field.
* cygheap.cc (init_cheap): Delete.
(dup_now): Ditto.
(cygheap_setup_for_child): Ditto.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_fixup_in_child): Simplify.  Use new "child_copy" function to copy heap
from parent.
(_csbrk): Don't attempt allocation if within cygheap section.  Fix so that more
than one allocation will succeed.
(cygheap_init): Reset possibly-nonzero region to zero.
* cygheap.h (cygheap_setup_for_child): Delete declaration.
(cygheap_setup_for_child_cleanup): Ditto.
(cygheap_start): Define as an array.
* cygwin.sc: Modernize.  Remove unneeded sections.  Define cygheap here.
* dcrt0.cc (do_exit): Reflect argument change to close_all_files.
* dtable.cc (dtable::vfork_parent_restore): Ditto.
* dtable.h: Ditto.
* fhandler.h: Ditto.
* fork.cc (fork_copy): Call ReadProcessMemory if there is no thread
(indicating that we're execing).
(fork_child): Don't mess with hParent.
(fork_parent): Remove hParent stuff.  It happens earlier now.  Remove call to
cygheap_setup_for_child* stuff.
(fork): Put child_info_stuff in grouped structure.  Issue error if parent
handle is not set.
(child_copy): New function.
* sigproc.cc (child_info::child_info): Put cygheap settings here.  Set parent
handle.
(child_info::~child_info): Close parent handle if it exists.
* spawn.cc (spawn_guts): Reorganize so that ciresrv is allocated at only the
last minute so that cygheap changes are reflected.  Delete cygheap_setup*
calls.
* syscalls.cc (close_all_files): Add an argument to flag when the fd entry
should be released.
* winsup.h (close_all_files): Add an argument to close_all_files declaration.
Declare child_copy.
This commit is contained in:
Christopher Faylor
2005-06-01 03:46:56 +00:00
parent 302cb8165e
commit ce95c6407e
14 changed files with 202 additions and 280 deletions

View File

@@ -22,12 +22,16 @@
#include "heap.h"
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include <unistd.h>
init_cygheap NO_COPY *cygheap;
void NO_COPY *cygheap_max;
extern "C" char _cygheap_mid[] __attribute__((section(".cygheap")));
extern "C" char _cygheap_end[] __attribute__((section(".cygheap_end")));
static NO_COPY muto cygheap_protect;
static NO_COPY DWORD reserve_sz;
struct cygheap_entry
{
@@ -44,141 +48,20 @@ struct cygheap_entry
#define MVMAP_OPTIONS (FILE_MAP_WRITE)
extern "C" {
static void __stdcall _cfree (void *ptr) __attribute__((regparm(1)));
}
static void
init_cheap ()
{
#ifndef DEBUGGING
reserve_sz = CYGHEAPSIZE;
#else
char buf[80];
DWORD initial_sz = 0;
if (!GetEnvironmentVariable ("CYGWIN_HEAPSIZE", buf, sizeof buf - 1))
initial_sz = reserve_sz = CYGHEAPSIZE;
else
{
initial_sz = reserve_sz = atoi (buf);
small_printf ("using cygheap size %d\n", reserve_sz);
}
#endif
do
if ((cygheap = (init_cygheap *) VirtualAlloc ((void *) &_cygheap_start,
reserve_sz, MEM_RESERVE,
PAGE_NOACCESS)))
break;
while ((reserve_sz -= 2 * (1024 * 1024)) >= CYGHEAPSIZE_MIN);
#ifdef DEBUGGING
if (reserve_sz != initial_sz)
small_printf ("reset initial cygheap size to %u\n", reserve_sz);
#endif
if (!cygheap)
{
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery ((LPCVOID) &_cygheap_start, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
system_printf ("Couldn't reserve %d bytes of space for cygwin's heap, %E",
reserve_sz);
api_fatal ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
}
cygheap_max = cygheap;
}
static void dup_now (void *, child_info *, unsigned) __attribute__ ((regparm(3)));
static void
dup_now (void *newcygheap, child_info *ci, unsigned n)
{
if (!VirtualAlloc (newcygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("couldn't allocate new cygwin heap %p, %d for child, %E",
newcygheap, n);
memcpy (newcygheap, cygheap, n);
}
void *__stdcall
cygheap_setup_for_child (child_info *ci, bool dup_later)
{
void *newcygheap;
cygheap_protect.acquire ();
unsigned n = (char *) cygheap_max - (char *) cygheap;
unsigned size = reserve_sz;
if (size < n)
size = n + (128 * 1024);
ci->cygheap_h = CreateFileMapping (INVALID_HANDLE_VALUE, &sec_none,
CFMAP_OPTIONS, 0, size, NULL);
if (!ci->cygheap_h)
api_fatal ("Couldn't create heap for child, size %d, %E", size);
newcygheap = MapViewOfFileEx (ci->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
if (!newcygheap)
api_fatal ("couldn't map space for new cygheap, %E");
ProtectHandle1INH (ci->cygheap_h, passed_cygheap_h);
if (!dup_later)
dup_now (newcygheap, ci, n);
cygheap_protect.release ();
ci->cygheap = cygheap;
ci->cygheap_max = cygheap_max;
ci->cygheap_reserve_sz = size;
return newcygheap;
}
void __stdcall
cygheap_setup_for_child_cleanup (void *newcygheap, child_info *ci,
bool dup_it_now)
{
if (dup_it_now)
{
/* NOTE: There is an assumption here that cygheap_max has not changed
between the time that cygheap_setup_for_child was called and now.
Make sure that this is a correct assumption. */
cygheap_protect.acquire ();
dup_now (newcygheap, ci, (char *) cygheap_max - (char *) cygheap);
cygheap_protect.release ();
}
UnmapViewOfFile (newcygheap);
ForceCloseHandle1 (ci->cygheap_h, passed_cygheap_h);
static void __stdcall _cfree (void *) __attribute__((regparm(1)));
static void *__stdcall _csbrk (int);
}
/* Called by fork or spawn to reallocate cygwin heap */
void __stdcall
cygheap_fixup_in_child (bool execed)
{
cygheap = child_proc_info->cygheap;
cygheap_max = child_proc_info->cygheap_max;
void *addr = !wincap.map_view_of_file_ex_sucks () ? cygheap : NULL;
void *newaddr;
newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, addr);
reserve_sz = child_proc_info->cygheap_reserve_sz;
if (newaddr != cygheap)
{
if (!newaddr)
newaddr = MapViewOfFileEx (child_proc_info->cygheap_h, MVMAP_OPTIONS, 0, 0, 0, NULL);
DWORD n = (DWORD) cygheap_max - (DWORD) cygheap;
/* Reserve cygwin heap in same spot as parent */
if (!VirtualAlloc (cygheap, reserve_sz, MEM_RESERVE, PAGE_NOACCESS))
{
MEMORY_BASIC_INFORMATION m;
memset (&m, 0, sizeof m);
if (!VirtualQuery ((LPCVOID) cygheap, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
system_printf ("Couldn't reserve %d bytes of space for cygwin's heap (%p <%p>) in child, %E",
reserve_sz, cygheap, newaddr);
api_fatal ("m.AllocationBase %p, m.BaseAddress %p, m.RegionSize %p, m.State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
}
/* Allocate same amount of memory as parent */
if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
cygheap, n);
memcpy (cygheap, newaddr, n);
UnmapViewOfFile (newaddr);
}
ForceCloseHandle1 (child_proc_info->cygheap_h, passed_cygheap_h);
cygheap_max = child_proc_info->cygheap;
cygheap = (init_cygheap *) cygheap_max;
_csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap", cygheap, cygheap_max);
if (execed)
CloseHandle (child_proc_info->parent);
cygheap_init ();
debug_fixup_after_fork_exec ();
@@ -222,30 +105,42 @@ init_cygheap::close_ctty ()
#endif
}
#define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
#define nextpage(x) ((char *) (((DWORD) ((char *) x + granmask)) & ~granmask))
#define allocsize(x) ((DWORD) nextpage (x))
#ifdef DEBUGGING
#define somekinda_printf debug_printf
#else
#define somekinda_printf malloc_printf
#endif
static void *__stdcall
_csbrk (int sbs)
{
void *prebrk = cygheap_max;
void *prebrka = pagetrunc (prebrk);
size_t granmask = getshmlba () - 1;
char *newbase = nextpage (prebrk);
cygheap_max = (char *) cygheap_max + sbs;
if (!sbs || (prebrk != prebrka && prebrka == pagetrunc (cygheap_max)))
if (!sbs || (newbase > cygheap_max) || (cygheap_max < _cygheap_end))
/* nothing to do */;
else if (!VirtualAlloc (prebrk, (DWORD) sbs, MEM_COMMIT, PAGE_READWRITE))
else
{
#ifdef DEBUGGING
system_printf ("couldn't commit memory for cygwin heap, prebrk %p, size %d, heapsize now %d, max heap size %u, %E",
prebrk, sbs, (char *) cygheap_max - (char *) cygheap,
reserve_sz);
#else
malloc_printf ("couldn't commit memory for cygwin heap, prebrk %p, size %d, heapsize now %d, max heap size %u, %E",
prebrk, sbs, (char *) cygheap_max - (char *) cygheap,
reserve_sz);
#endif
__seterrno ();
cygheap_max = (char *) cygheap_max - sbs;
return NULL;
if (prebrk <= _cygheap_end)
newbase = _cygheap_end;
DWORD adjsbs = allocsize ((char *) cygheap_max - newbase);
if (!VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
{
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery (newbase, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
somekinda_printf ("Couldn't reserve/commit %d bytes of space for cygwin's heap, %E",
adjsbs);
somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
__seterrno ();
cygheap_max = (char *) cygheap_max - sbs;
return NULL;
}
}
return prebrk;
@@ -257,7 +152,13 @@ cygheap_init ()
cygheap_protect.init ("cygheap_protect");
if (!cygheap)
{
init_cheap ();
#if 1
cygheap = (init_cygheap *) memset (_cygheap_start, 0, _cygheap_mid - _cygheap_start);
#else
cygheap = (init_cygheap *) _cygheap_start;
#endif
cygheap_max = cygheap;
(void) _csbrk (sizeof (*cygheap));
}
if (!cygheap->fdtab)