This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: (no) GCC pre-compiled headers on Cygwin

[Please keep me Cc'd, I'm not subscribed to the gcc mailing list]

On Tue, Jul 22, 2003 at 04:02:26AM -0300, Alexandre Oliva wrote:
> I've been looking into why GCC pre-compiled headers don't work on
> Cygwin.  There are several reasons:
> - gt_pch_save() mmap()s the file with the expected PCH size before the
>   file is big enough.  Cygwin mmap will fail in this case, because it
>   truncates the requested mmap size on the file-end boundary, and
>   then, when mmap_record::map_map checks that a region big enough for
>   the entire requested size was mapped, it fails.  A simple

This is a Windows limitation which we don't have a workaround for so far.

On POSIX systems, mmapping over EOF is implemented so that the underlying
file does not change when calling mmap.  Bytes after EOF are not written
to the file, the file size doesn't change.

In Windows, mappings longer than the file size are possible but they will
change the file size immediately to match the map size.

The current implementation in Cygwin avoids to change the file in this
scenario, thus allowing mappings only <= file size.

>   work-around for this is to ftruncate() to the expected size first:
>   then mmap() works, and we generate a PCH file with a reasonable
>   base_address.  I think this is a change that would be very
>   reasonable to make in GCC, given that mmap()ing a region beyond the
>   end of a file is not portable.  Unfortunately, ftruncate isn't
>   ftruncate if it's not available, and just do our best.

I agree.  There's also a possible but so far untested workaround in Cygwin. 
The Windows NT API NtMapViewOfSection allows to specify a flag
AT_EXTENDABLE_FILE (which is not exposed to the Win32 API MapViewOfFileEx),
which changes the behaviour to the above described POSIX way (allow mappings
beyond EOF w/o changing the file).  The downside is, it's only available
since Windows 2000.  No way to implement it on 9x/Me or NT <= 4.  So I guess
gcc would have to change as you described or we leave older systems behind.

> - gt_pch_restore() mmap()s the file without MAP_FIXED, passing it the
>   wanted base address, that gt_pch_save() had obtained from mmap() and
>   saved in the file, but Cygwin's fhandler_disk_file::mmap() simply
>   disregards the address when mapping without MAP_FIXED.  I don't
>   understand why it does this.  Why doesn't it pass the requested
>   address to MapViewOfFileEx always?  It doesn't seem that it would

It did so until Cygwin 1.3.22, having a good right to do it according
to SUSv3: "When MAP_FIXED is not set, the implementation uses addr in
an implementation-defined manner to arrive at pa."  The implementation-
defined manner was not to use it.

>   fail if the exact address wasn't available but, even if it did,
>   although mmap is not required to use the given address, except for
>   MAP_FIXED, mmap should at least favor the given address over other
>   alternatives, even if this means issuing two calls, one with the
>   address and one without.  Is there a reason for this behavior in
>   Cygwin?

The current test version of "next generation" ;-) Cygwin, 1.5.0, implements
exactly that.  Basically it tries the address first.  This will fail
if Windows cannot fulfill the request.  If so, Cygwin tries with NULL
address again unless MAP_FIXED is specified.

> - Another problem is the way Cygwin copes with granularity of mmaps.
>   When GCC calls mmap() in gt_pch_save() to choose the base address of
>   the PCH, it maps the file starting at offset 0.  When
>   gt_pch_restore() calls it, it uses a non-zero offset, that, in spite
>   of being aligned to a page boundary, is not necessarily aligned to
>   the allocation granularity.  Unfortunately, because of the way
>   Cygwin (or Windows?) handles granularity, its mmap() cannot *ever*

Windows.  The page size is 4K, the allocation granularity is 64K.

>   returned by mmap was off by 0x5000.  I don't know whether Cygwin's
>   handling of gran_off and gran_len is based on requirements from
>   Windows or on its own design decisions, but it seems clear to me

It was a design decision.  Honestly, I wasn't aware in how many sick
ways the call is used.  Keep in mind that Cygwin has all hands full
to hold off applications from Windows specific limitations.  It's
not easy, sometimes nearly impossible, to emulate e.g. Linux behaviour.
The non-standard expectations of some applications doesn't make it
exactly easier...

>   Anyway, ideally Cygwin should, if possible, not align file mappings
>   to the mmap granularity, especially for MAP_FIXED, and it should
>   definitely fail if it can't satisfy the request to MAP_FIXED to the
>   given address with a non-granularity- (bug still page-)aligned
>   offset.

The new Cygwin 1.5.0 does handle that situation as you describe.  It
realignes the given address and length parameters to fit into the Windows
granularity requirements, allowing to return the given address with a
high probability.

Again, there's another possible way to implement that in Cygwin.  The
above mentioned NT API call NtMapViewOfSection allows a flag AT_ROUND_TO_PAGE,
also not exposed to the corresponding Win32 call MapViewOfFileEx.  This
flag enables the ability to return maps at page boundaries instead of
only at granularity boundaries.  But as above, this is untested and
the downside is again, it will not work on 9x/Me for obvious reasons.

> - GCC, on its end, should probably not expect the address returned by
>   mmap() for offset 0 of the file to be valid for other offsets.

Good idea.

> - It would be nice if Cygwin could expose the mmap granularity
>   information somehow (maybe it already does?), as well as some means
>   to tell whether a collection of pages is available for mmapping,
>   somewhat like mincore(), that gt_pch_restore() uses if available in
>   case mmap doesn't take the base address hint, to check whether the
>   memory region is available before trying to MAP_FIXED it.  We don't
>   need mincore()s functionality.  It's not even clear that such
>   functionality is available on Windows; I for one know it's not

For the allocation granularity, Windows already has a call GetSystemInfo.
For the mincore functionality it has the call VirtualQuery.

Since getting these information is highly non-portable anyway, I don't
think it makes sense to create an additional Cygwin call.  The same
way as the allocation granularity has no use for most other systems,
the mincore call is not backed by the standards.  It's use is non-portable
by definition.  However, regardless of my own opinion on that, it would
be possible to implement mincore in Cygwin, AFAICS.

>   entirely available on GNU/Linux, but GCC attempts to use it anyhow,
>   and such use is actually unsafe.  However, if we could come up with
>   another interface that could be used to tell whether a certain page
>   is mapped or not, we could use it for the same purpose that we
>   currently use mincore.  As long as Cygwin's MAP_FIXED is fixed
>   and/or we pre-compute the offset and pass it to the save-time mmap
>   and/or we align the offset to the allocation granularity.

As long as we left 9x/Me behind again, there might be a chance to get
an even better implementation in Cygwin:  The NT API call NtCreateSection
allows a flag SEC_BASED (again, not exposed to the normal Win32 API, but
you guessed that), which defines that this mapping will be based at the
very same address in all processes.

> Anyway, we seem to still be a long way from getting PCH on Cygwin :-(

Which is pretty weird.  Cygwin's mmap implementation tries to be as
portable as possible given the underlying Windows implementation of
file mappings.

I really don't understand why gcc expects non-standard behaviour from
a standard call as mmap.  We would have very few problems (granted, not
"no problems") if gcc would use the mmap call only portable as defined
in SUSv3.

Unfortunately, your posting hits me the last day before I'm on vacation
and offline for two weeks.  I'd love to discuss this further and to change
Cygwin's mmap implementation even to get the more non-portable behaviour
as gcc expects, as far as it's possible on Windows. 

Some changes to the gcc implementation, especially removing as much
non-portable stuff as possible, would be required, though.


Corinna Vinschen
Cygwin Developer
Red Hat, Inc.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]