delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2011/03/18/10:41:23

X-Recipient: archive-cygwin AT delorie DOT com
X-Spam-Check-By: sourceware.org
Date: Fri, 18 Mar 2011 15:40:48 +0100
From: Corinna Vinschen <corinna-cygwin AT cygwin DOT com>
To: cygwin AT cygwin DOT com
Subject: Re: ld: fatal error - cmalloc would have returned NULL
Message-ID: <20110318144048.GF20048@calimero.vinschen.de>
Reply-To: cygwin AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
References: <4D7A2951 DOT 1030002 AT emrich-ebersheim DOT de> <4D82F1D8 DOT 1020608 AT gmail DOT com> <20110318060821 DOT GB15594 AT ednor DOT casa DOT cgf DOT cx> <20110318102355 DOT GA20048 AT calimero DOT vinschen DOT de>
MIME-Version: 1.0
In-Reply-To: <20110318102355.GA20048@calimero.vinschen.de>
User-Agent: Mutt/1.5.21 (2010-09-15)
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Unsubscribe: <mailto:cygwin-unsubscribe-archive-cygwin=delorie DOT com AT cygwin DOT com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com

On Mar 18 11:23, Corinna Vinschen wrote:
> On Mar 18 02:08, Christopher Faylor wrote:
> > On Fri, Mar 18, 2011 at 05:47:04AM +0000, Dave Korn wrote:
> > >On 11/03/2011 13:53, Rainer Emrich wrote:
> > >
> > >> I have to be more clear. I increased the heap_chunk_in_mb to 1792 using:
> > >> regtool -i set /HKLM/Software/Cygwin/heap_chunk_in_mb 1792
> > >
> > >  I run with this setting all the time, I guess that's why I haven't seen this
> > >problem.  Before I did that (couple of years back) I also used to get crashes
> > >building libjava.
> > 
> > That setting should have nothing to do with cmalloc().  cmalloc is for
> > Cygwin's internal heap which has nothing to do with that setting.
> > 
> > Didn't Corinna already mention this?
> 
> In this case the bigger heap seems to avoid the aggressive use of small
> mmap chunks which in turn disallows to raise the cygheap size.  Without
> analyzing the whole situation there's not much else to say or do.  This
> is YA case which screams loudly for a testcase...

I created an extensive testcase(*) and it turned out that the current
algorithm to allocate memory on the cygheap is wasting a lot of memory.
Actually it organizes the memory in buckets, each of which cares for a
specific size as a power of 2.  So memory on the cygheap is always
allocated in chunks of 4 byte, 8 byte, 16 byte, 32 byte, etc.  Plus,
every chunk needs extra 8 byte for bookkeeping.

Now, mmap has to keep a per-mmap record on the cygheap to maintain mmaps
across munmap and fork.  The problem is that the size of the mmap record
so far is 64 bytes plus a 4 byte page bitmap per 128K of allocated memory.

So each mmap(64K) requires a 68 byte record.  Due to the way the cygheap
allocation works, this takes actually 128 bytes on the cygheap.  In my
testcase, after about 8500 mmaps, the required size of the mmap records
on the cygheap is 128*8500 = 1088000 bytes.  Now we're out of space on
the cygheap, but it's not possible to raise the size of the cygheap
since the space beyond is taken by the mmaped regions.  Consequentially
mmap fails, even though there's still space left in the processes
address space.

I applied a patch (actually three patches) to Cygwin now, which are
supposed to drop the cygheap usage of mmap.  The size of a mmap record
is now only 48 bytes.  A 64K mmap requires another 4 bytes for the page
bitmap.  Plus 8 bytes bookkeeping for the allocation algorithm.  Total
of 60 bytes.  This happens to fit in a 64 bit chunk on the cygheap.
64*8500 = 544000 bytes, so there's still a lot of space left on the
cygheap.

The result in the below testcase(*) is now that cygheap is exhausted
only after 14826 calls to mmap(64K).

I've create a new snapshot with this change.  Please test the latest
snapshot from http://cygwin.com/snapshots/

If this doesn't fix your issue with ld, then you would have to raise the
size of the cygheap before running ld.  This requires a change to the
Cygwin DLL, but you can do this without rebuilding the DLL.  Just using
objcopy should help to do it.  A cygheap size of 2 Megs should be
sufficient to exhaust the application's address space faster than the
cygheap.


Corinna


(*) #include <stdio.h>
    #include <sys/mman.h>

    int
    main ()
    {
      unsigned long i = 0;
      void *m2 = NULL, *m1;
      while ((m1 = mmap (NULL, 65536, PROT_READ | PROT_WRITE,
		   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED)
	{
	  m2 = m1;
	  ++i;
	}
      if (m2)
	munmap (m2, 65536);	/* Otherwise printf fails. */
      printf ("%d\n", i);
      return 0;
    }

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019