mmap() on 64K aligned address fails

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

mmap() on 64K aligned address fails

René Berber-2
Hi,

I was trying to figure out the often reported failure of mmap seen by running
configure on some packages and, after looking at the answers on the list, I
tried a test on a 64k aligned (malloced) address, mmap(... MAP_FIXED ...) fails.

Attached is the small test file that was compiled with the command at the end of
the same file.

Any ideas what's wrong?

Thanks.
--
René Berber

/* confdefs.h.  */

#define PACKAGE_NAME "package-unused"
#define PACKAGE_TARNAME "libstdc++"
#define PACKAGE_VERSION "version-unused"
#define PACKAGE_STRING "package-unused version-unused"
#define PACKAGE_BUGREPORT ""
#ifdef __cplusplus
extern "C" void exit (int);
#endif
#define _GLIBCXX_HOSTED 1
#define _GLIBCXX_SJLJ_EXCEPTIONS 1
#define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STRINGS_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_STDINT_H 1
#define HAVE_UNISTD_H 1
#define _GLIBCXX_USE_C99_MATH 1
#define _GLIBCXX_USE_LONG_LONG 1
#define HAVE_GTHR_DEFAULT 1
#define HAVE_IEEEFP_H 1
#define HAVE_ENDIAN_H 1
#define HAVE_MACHINE_ENDIAN_H 1
#define HAVE_MACHINE_PARAM_H 1
#define HAVE_LOCALE_H 1
#define HAVE_FLOAT_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_IPC_H 1
#define HAVE_SYS_SEM_H 1
#define HAVE_ISINF 1
#define HAVE_ISNAN 1
#define HAVE_FINITE 1
#define HAVE_COPYSIGN 1
#define HAVE_SINCOS 1
#define HAVE_HYPOT 1
#define HAVE_ACOSF 1
#define HAVE_ASINF 1
#define HAVE_ATANF 1
#define HAVE_COSF 1
#define HAVE_SINF 1
#define HAVE_TANF 1
#define HAVE_COSHF 1
#define HAVE_SINHF 1
#define HAVE_TANHF 1
#define HAVE_CEILF 1
#define HAVE_FLOORF 1
#define HAVE_EXPF 1
#define HAVE_ATAN2F 1
#define HAVE_FABSF 1
#define HAVE_FMODF 1
#define HAVE_FREXPF 1
#define HAVE_HYPOTF 1
#define HAVE_LDEXPF 1
#define HAVE_LOGF 1
#define HAVE_LOG10F 1
#define HAVE_MODFF 1
#define HAVE_POWF 1
#define HAVE_SQRTF 1
#define HAVE_SINCOSF 1
#define HAVE___BUILTIN_ABS 1
#define HAVE___BUILTIN_FABSF 1
#define HAVE___BUILTIN_FABS 1
#define HAVE___BUILTIN_FABSL 1
#define HAVE___BUILTIN_LABS 1
#define HAVE___BUILTIN_SQRTF 1
#define HAVE___BUILTIN_SQRT 1
#define HAVE___BUILTIN_SQRTL 1
#define HAVE___BUILTIN_SINF 1
#define HAVE___BUILTIN_SIN 1
#define HAVE___BUILTIN_SINL 1
#define HAVE___BUILTIN_COSF 1
#define HAVE___BUILTIN_COS 1
#define HAVE___BUILTIN_COSL 1
#define HAVE_LIBM 1
#define HAVE_COPYSIGNF 1
#define HAVE___SIGNBITF 1
#define HAVE_MBSTATE_T 1
#define HAVE_WCHAR_H 1
#define HAVE_WCTYPE_H 1
#define HAVE_WCSLEN 1
#define HAVE_WMEMCHR 1
#define HAVE_WMEMCMP 1
#define HAVE_WMEMCPY 1
#define HAVE_WMEMMOVE 1
#define HAVE_WMEMSET 1
#define HAVE_BTOWC 1
#define HAVE_WCTOB 1
#define HAVE_WPRINTF 1
#define HAVE_MBSINIT 1
#define HAVE_MBRLEN 1
#define HAVE_MBRTOWC 1
#define HAVE_MBSRTOWCS 1
#define HAVE_WCSRTOMBS 1
#define HAVE_WCRTOMB 1
#define HAVE_WCSCPY 1
#define HAVE_WCSNCPY 1
#define HAVE_WCSCAT 1
#define HAVE_WCSNCAT 1
#define HAVE_WCSCMP 1
#define HAVE_WCSCOLL 1
#define HAVE_WCSNCMP 1
#define HAVE_WCSCSPN 1
#define HAVE_WCSSPN 1
#define HAVE_WCSCHR 1
#define HAVE_WCSPBRK 1
#define HAVE_WCSRCHR 1
#define HAVE_WCSSTR 1
#define HAVE_ISWBLANK 1
#define HAVE_NL_LANGINFO 1
#define HAVE_STRTOF 1
#define HAVE_SYS_IOCTL_H 1
#define HAVE_POLL 1
#define HAVE_S_ISREG 1
#define HAVE_SYS_UIO_H 1
#define HAVE_WRITEV 1
#define HAVE_INT64_T 1
#define HAVE_LC_MESSAGES 1
#define HAVE_SIGSETJMP 1
#define HAVE_STDLIB_H 1
#define HAVE_UNISTD_H 1
#define HAVE_GETPAGESIZE 1
/* end confdefs.h.  */
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#if STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# if HAVE_STDLIB_H
#  include <stdlib.h>
# endif
#endif
#if HAVE_STRING_H
# if !STDC_HEADERS && HAVE_MEMORY_H
#  include <memory.h>
# endif
# include <string.h>
#endif
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if HAVE_STDINT_H
#  include <stdint.h>
# endif
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
/* malloc might have been renamed as rpl_malloc. */
#undef malloc

/* Thanks to Mike Haertel and Jim Avera for this test.
   Here is a matrix of mmap possibilities:
        mmap private not fixed
        mmap private fixed at somewhere currently unmapped
        mmap private fixed at somewhere already mapped
        mmap shared not fixed
        mmap shared fixed at somewhere currently unmapped
        mmap shared fixed at somewhere already mapped
   For private mappings, we should verify that changes cannot be read()
   back from the file, nor mmap's back from the file at a different
   address.  (There have been systems where private was not correctly
   implemented like the infamous i386 svr4.0, and systems where the
   VM page cache was not coherent with the file system buffer cache
   like early versions of FreeBSD and possibly contemporary NetBSD.)
   For shared mappings, we should conversely verify that changes get
   propagated back to all the places they're supposed to be.

   Grep wants private fixed already mapped.
   The main things grep needs to know about mmap are:
   * does it exist and is it safe to write into the mmap'd area
   * how to use it (BSD variants)  */

#include <fcntl.h>
#include <sys/mman.h>

#if !STDC_HEADERS && !HAVE_STDLIB_H
char *malloc ();
#endif

/* This mess was copied from the GNU getpagesize.h.  */
#if !HAVE_GETPAGESIZE
/* Assume that all systems that can run configure have sys/param.h.  */
# if !HAVE_SYS_PARAM_H
#  define HAVE_SYS_PARAM_H 1
# endif

# ifdef _SC_PAGESIZE
#  define getpagesize() sysconf(_SC_PAGESIZE)
# else /* no _SC_PAGESIZE */
#  if HAVE_SYS_PARAM_H
#   include <sys/param.h>
#   ifdef EXEC_PAGESIZE
#    define getpagesize() EXEC_PAGESIZE
#   else /* no EXEC_PAGESIZE */
#    ifdef NBPG
#     define getpagesize() NBPG * CLSIZE
#     ifndef CLSIZE
#      define CLSIZE 1
#     endif /* no CLSIZE */
#    else /* no NBPG */
#     ifdef NBPC
#      define getpagesize() NBPC
#     else /* no NBPC */
#      ifdef PAGESIZE
#       define getpagesize() PAGESIZE
#      endif /* PAGESIZE */
#     endif /* no NBPC */
#    endif /* no NBPG */
#   endif /* no EXEC_PAGESIZE */
#  else /* no HAVE_SYS_PARAM_H */
#   define getpagesize() 8192 /* punt totally */
#  endif /* no HAVE_SYS_PARAM_H */
# endif /* no _SC_PAGESIZE */

#endif /* no HAVE_GETPAGESIZE */

int
main ()
{
  char *data, *data2, *data3;
  int i, pagesize;
  int fd;

  pagesize = getpagesize ();

  printf("pagesize is %d\n", pagesize);
  /* First, make a file with some known garbage in it. */
  data = (char *) malloc (pagesize);
  if (!data) {
    printf("malloc failed\n");
    exit (1);
  }
  for (i = 0; i < pagesize; ++i)
    *(data + i) = rand ();
  umask (0);
  fd = creat ("conftest.mmap", 0600);
  if (fd < 0) {
    printf("creat failed\n");
    exit (1);
  }
  if (write (fd, data, pagesize) != pagesize) {
    printf("write failed\n");
    exit (1);
  }
  close (fd);

  /* Next, try to mmap the file at a fixed address which already has
     something else allocated at it.  If we can, also make sure that
     we see the same garbage.  */
  fd = open ("conftest.mmap", O_RDWR);
  if (fd < 0) {
    printf("open failed\n");
    exit (1);
  }
#if !defined(__CYGWIN32__)
  data2 = (char *) malloc (2 * pagesize);
  if (!data2) {
    printf("second malloc failed\n");
    exit (1);
  }
  data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
#else
  data2 = (char *) malloc (16 * pagesize);
  if (!data2) {
    printf("second malloc failed\n");
    exit (1);
  }
  printf("data2 before is %p\n", data2);
  data2 += (16*pagesize - ((long) data2 & (16*pagesize - 1))) & (16*pagesize - 1);
  printf("data2 after  is %p\n", data2);
#endif
  if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_FIXED, fd, 0L)) {
    printf("mmap failed\n");
    exit (1);
  }
  for (i = 0; i < pagesize; ++i)
    if (*(data + i) != *(data2 + i)) {
      printf("pages are not equal\n");
      exit (1);
    }

  /* Finally, make sure that changes to the mapped area do not
     percolate back to the file as seen by read().  (This is a bug on
     some variants of i386 svr4.0.)  */
  for (i = 0; i < pagesize; ++i)
    *(data2 + i) = *(data2 + i) + 1;
  data3 = (char *) malloc (pagesize);
  if (!data3) {
    printf("third malloc failed\n");
    exit (1);
  }
  if (read (fd, data3, pagesize) != pagesize) {
    printf("read failed\n");
    exit (1);
  }
  for (i = 0; i < pagesize; ++i)
    if (*(data + i) != *(data3 + i)) {
      printf("file changed\n");
      exit (1);
    }
  close (fd);
  printf("OK\n");
  exit (0);
}

/*
 * Local variables:
 * compile: gcc -o mmap_test -O2 mmap_test.c -lm
 * end:
 */


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/
Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Samuel Thibault
Hi,

Ren? Berber, le Fri 25 Nov 2005 22:34:26 -0600, a ?crit :

> #if !defined(__CYGWIN32__)
>   data2 = (char *) malloc (2 * pagesize);
>   if (!data2) {
>     printf("second malloc failed\n");
>     exit (1);
>   }
>   data2 += (pagesize - ((long) data2 & (pagesize - 1))) & (pagesize - 1);
> #else
>   data2 = (char *) malloc (16 * pagesize);
>   if (!data2) {
>     printf("second malloc failed\n");
>     exit (1);
>   }
>   printf("data2 before is %p\n", data2);
>   data2 += (16*pagesize - ((long) data2 & (16*pagesize - 1))) & (16*pagesize - 1);
>   printf("data2 after  is %p\n", data2);
> #endif

This seems odd. In the cygwin case, pagesize() would not be sufficient ??
And anyway, it should rather be
   data2 = (char *) malloc (2 * 16 * pagesize);
Not only 16 (since it is further 16*pagesize -aligned).

Regards,
Samuel


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
Samuel Thibault wrote:
[snip]
> This seems odd. In the cygwin case, pagesize() would not be sufficient ??

No, in windows there is a requirement that mmap uses memory aligned to 64k (the
infamous granularity).

> And anyway, it should rather be
>    data2 = (char *) malloc (2 * 16 * pagesize);
> Not only 16 (since it is further 16*pagesize -aligned).

It's enough to allocate 16 x pagesize to use one page for mmap-ing (like Corinna
said in one message 15/16 pages will not be aligned -- but one will).  If you
see the intermediate results I printed, data2 is re-aligned to 64k correctly.

Anyway, I still don't know why mmap() failded.
--
René Berber


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Samuel Thibault
Ren? Berber, le Sat 26 Nov 2005 15:19:06 -0600, a ?crit :
> Samuel Thibault wrote:
> [snip]
> > This seems odd. In the cygwin case, pagesize() would not be sufficient ??
>
> No, in windows there is a requirement that mmap uses memory aligned to 64k (the
> infamous granularity).

Then the result of pagesize() is not sufficiently big: POSIX says that
mmap() can return EINVAL if ??the address [...]?is not a multiple of
the page size, or is considered invalid by the implementation??. Well,
we could consider non-16-pages-alignment as `considered invalid', but I
guess this expression was meant as `not in a mmap()-able area'.

> > And anyway, it should rather be
> >    data2 = (char *) malloc (2 * 16 * pagesize);
> > Not only 16 (since it is further 16*pagesize -aligned).
>
> It's enough to allocate 16 x pagesize to use one page for mmap-ing (like Corinna
> said in one message 15/16 pages will not be aligned -- but one will).  If you
> see the intermediate results I printed, data2 is re-aligned to 64k correctly.

Ah oops, didn't pay attention that the mmap was page-sized.  16 pages
are still not enough: if malloc() returns 0x0001 for instance, you'll
round up that to 16*pagesize, which is out the allocated area. 17 pages
are necessary.

BTW, I don't understand why using so complicated code:
p += (align - ((long) p & (align-1))) & (align-1)
Isn't
p = ((long) p + (align-1)) & (align-1)
both faster (tested) and more readable ?

Regards,
Samuel

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
Samuel Thibault wrote:
[snip]
>>No, in windows there is a requirement that mmap uses memory aligned to 64k (the
>>infamous granularity).
>
> Then the result of pagesize() is not sufficiently big: POSIX says that
> mmap() can return EINVAL if « the address [...] is not a multiple of
> the page size, or is considered invalid by the implementation ». Well,
> we could consider non-16-pages-alignment as `considered invalid', but I
> guess this expression was meant as `not in a mmap()-able area'.

mmap() is returning an error code, probably EINVAL I just ddisn't care to look
what was it because there shouldn't be an error.

[snip]
> 16 pages
> are still not enough: if malloc() returns 0x0001 for instance, you'll
> round up that to 16*pagesize, which is out the allocated area. 17 pages
> are necessary.

Yes, that would produce an error... not the one you are saying but the "aligned"
result will fall at the end with less than a pagesize available for mmap.

> BTW, I don't understand why using so complicated code:
> p += (align - ((long) p & (align-1))) & (align-1)
> Isn't
> p = ((long) p + (align-1)) & (align-1)
> both faster (tested) and more readable ?

I didn't write the original code, it is from gcc-4.0.2 and it's used all over
the place to make libraries (libstdc, libgcj, perhaps others) and tools.  There
are other mmap() tests that fail (mmap from /dev/zero, mmap with MAP_ANON) I'm
just starting to look around to see what is the problem, and perhaps send a
patch to the gcc maintainers so we can have a fully functional set of libraries.

Regards.
--
René Berber


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
René Berber wrote:
[snip]
> mmap() is returning an error code, probably EINVAL I just ddisn't care to look
                                                            didn't
> what was it because there shouldn't be an error.

Yes, using perror I get "Invalid argument", so the implementation considers
mmap(0x470000, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)
somehow an invalid invocation.
--
René Berber


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Corinna Vinschen-2
On Nov 26 18:41, Ren? Berber wrote:
> Ren? Berber wrote:
> [snip]
> > mmap() is returning an error code, probably EINVAL I just ddisn't care to look
>                                                             didn't
> > what was it because there shouldn't be an error.
>
> Yes, using perror I get "Invalid argument", so the implementation considers
> mmap(0x470000, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)
> somehow an invalid invocation.

I didn't inspect the testcase all too closely since it's annoyingly long
for such a simple test.  But what exactly do you expect when trying to
mmap an arbitrary memory address in the virtual address space which you
know nothing about?  The code is making invalid assumptions about the
usage of the underlying memory layout.

Don't use MAP_FIXED unless you know what you're doing.


Corinna

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

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
Corinna Vinschen wrote:
[snip]
>>mmap(0x470000, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)
>>somehow an invalid invocation.
>
>
> I didn't inspect the testcase all too closely since it's annoyingly long
> for such a simple test.  But what exactly do you expect when trying to
> mmap an arbitrary memory address in the virtual address space which you
> know nothing about?

It's not an arbitrary memory address, the 0x470000 is the result of aligning a
pagesize space into 17xpagesize malloced memory.

> The code is making invalid assumptions about the
> usage of the underlying memory layout.
>
> Don't use MAP_FIXED unless you know what you're doing.

I'm not an expert but I think the example did comply with all the Windows
"granularity" requirements and unless I'm really missing something else it
should have worked without the invalid argument error.

Thanks for your reply.
--
René Berber


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Samuel Thibault
Ren? Berber, le Sun 27 Nov 2005 16:17:45 -0600, a ?crit :

> Corinna Vinschen wrote:
> [snip]
> >>mmap(0x470000, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0L)
> >>somehow an invalid invocation.
> >
> >
> > I didn't inspect the testcase all too closely since it's annoyingly long
> > for such a simple test.  But what exactly do you expect when trying to
> > mmap an arbitrary memory address in the virtual address space which you
> > know nothing about?
>
> It's not an arbitrary memory address, the 0x470000 is the result of aligning a
> pagesize space into 17xpagesize malloced memory.

Memmapping to malloced memory could very well be forbidden. Why would
one want to do this?

Regards,
Samul

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
Samuel Thibault wrote:
[snip]
> Memmapping to malloced memory could very well be forbidden. Why would
> one want to do this?

As I said before, the test is one that comes with gcc-4.0.2, it fails only on
Windows as far as I know.  To answer your question: is just a test, it should
work with some Windows related tweaking but it's just a test.

Besides, what other memory is there available that a process has under its
control?  Yes, I know, mmap() should be used w/o MAP_FIXED and let the OS choose
where to map, but the interesting part of this test is to use MAP_FIXED.
--
René Berber


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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Corinna Vinschen-2
On Nov 27 16:47, Ren? Berber wrote:

> Samuel Thibault wrote:
> [snip]
> > Memmapping to malloced memory could very well be forbidden. Why would
> > one want to do this?
>
> As I said before, the test is one that comes with gcc-4.0.2, it fails only on
> Windows as far as I know.  To answer your question: is just a test, it should
> work with some Windows related tweaking but it's just a test.
>
> Besides, what other memory is there available that a process has under its
> control?  Yes, I know, mmap() should be used w/o MAP_FIXED and let the OS choose
> where to map, but the interesting part of this test is to use MAP_FIXED.

The problem is that the application using MAP_FIXED has no idea if the
address it's using is *allowed*.  There might be already a mapping
active, maybe just the application's code is mapped at that point, or
the address is generally invalid for shared memory usage.

Many mmap tests make such invalid assumptions about the memory.  Just
because they are part of gcc doesn't make them right.  The only blessed
usage of MAP_FIXED is if the application knows that the memory address
is valid.  One way to do this is to establish a non-FIXED mmap first,
like this:

  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <sys/mman.h>

  int
  main ()
  {
    int pages = 10;
    void *addr, *addr2;

    addr = mmap (NULL, 2 * pages * getpagesize(), PROT_READ|PROT_WRITE,
                 MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    if (addr == MAP_FAILED)
      fprintf (stderr, "Gargl\n");
    else
      {
        munmap (addr, pages * getpagesize());
        addr2 = mmap (addr, pages * getpagesize(), PROT_READ|PROT_WRITE,
                      MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
        if (addr2 == MAP_FAILED)
          fprintf (stderr, "Frtzl\n");
        else if (addr2 != addr)
          fprintf (stderr, "Urgl\n");
        else
          fprintf (stderr, "Haha\n");
      }
    return 0;
  }


Corinna

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

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Corinna Vinschen-2
On Nov 28 12:51, Corinna Vinschen wrote:

> On Nov 27 16:47, Ren? Berber wrote:
> > Samuel Thibault wrote:
> > [snip]
> > > Memmapping to malloced memory could very well be forbidden. Why would
> > > one want to do this?
> >
> > As I said before, the test is one that comes with gcc-4.0.2, it fails only on
> > Windows as far as I know.  To answer your question: is just a test, it should
> > work with some Windows related tweaking but it's just a test.
> >
> > Besides, what other memory is there available that a process has under its
> > control?  Yes, I know, mmap() should be used w/o MAP_FIXED and let the OS choose
> > where to map, but the interesting part of this test is to use MAP_FIXED.
>
> The problem is that the application using MAP_FIXED has no idea if the
> address it's using is *allowed*.  There might be already a mapping
> active, maybe just the application's code is mapped at that point, or
> the address is generally invalid for shared memory usage.
>
> Many mmap tests make such invalid assumptions about the memory.  Just
> because they are part of gcc doesn't make them right.  The only blessed
> usage of MAP_FIXED is if the application knows that the memory address
> is valid.  One way to do this is to establish a non-FIXED mmap first,
> like this:
>
>   #include <stdio.h>
>   #include <stdlib.h>
>   #include <errno.h>
>   #include <sys/mman.h>
>
>   int
>   main ()
>   {
>     int pages = 10;
>     void *addr, *addr2;
>
>     addr = mmap (NULL, 2 * pages * getpagesize(), PROT_READ|PROT_WRITE,
> MAP_SHARED|MAP_ANONYMOUS, -1, 0);
>     if (addr == MAP_FAILED)
>       fprintf (stderr, "Gargl\n");
>     else
>       {
> munmap (addr, pages * getpagesize());
> addr2 = mmap (addr, pages * getpagesize(), PROT_READ|PROT_WRITE,
>      MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
> if (addr2 == MAP_FAILED)
>  fprintf (stderr, "Frtzl\n");
> else if (addr2 != addr)
>  fprintf (stderr, "Urgl\n");
> else
>  fprintf (stderr, "Haha\n");
>       }
>     return 0;
>   }

Btw., the above test won't work on Cygwin 1.5.18 due to a incorrect
test in Cygwin's mmap implementation.  This will be fixed in 1.5.19.
For a start, mmap/munmap the whole page area instead just the half of
it.  That should work.


Corinna

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

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Sam Steingold
In reply to this post by Corinna Vinschen-2
> * Corinna Vinschen <[hidden email]> [2005-11-28 12:51:09 +0100]:
>
> Many mmap tests make such invalid assumptions about the memory.

This is not just "tests" and the assumptions are not necessarily
"invalid".  The appended test fails on cygwin but passes on just about
every unix (linux, *bsd &c).
This means that the cygwin version of CLISP lacks generational GC (while
the win32 native version as well as linux, *bsd, solaris &c have it!)
which is a major feature for memory-intensive computations.


--
Sam Steingold (http://www.podval.org/~sds) running w2k
http://www.openvotingconsortium.org/ http://www.camera.org
http://www.dhimmi.com/ http://www.savegushkatif.org http://www.iris.org.il
The early worm gets caught by the bird.


configure:22543: checking for working mmap
configure:22709: gcc -o conftest.exe -g -O2 -I/usr/local/libsigsegv-cygwin/include  conftest.c  >&5
configure:22712: $? = 0
configure:22714: ./conftest.exe
configure:22717: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h.  */
|
| #define PACKAGE_NAME "GNU CLISP"
| #define PACKAGE_TARNAME "clisp"
| #define PACKAGE_VERSION "2.35 (2005-08-29)"
| #define PACKAGE_STRING "GNU CLISP 2.35 (2005-08-29)"
| #define PACKAGE_BUGREPORT "http://clisp.cons.org/"
| #define _GNU_SOURCE 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define ASM_UNDERSCORE
| #ifndef __i386__
| #define __i386__ 1
| #endif
| #define HAVE_ICONV 1
| #define ICONV_CONST const
| #define HAVE_ICONV 1
| #define ENABLE_NLS 1
| #define HAVE_GETTEXT 1
| #define HAVE_DCGETTEXT 1
| #define HAVE_SIGSEGV 1
| #define return_void return
| #define HAVE_LONG_LONG 1
| #define HAVE_LONGLONG
| #define STDC_HEADERS 1
| #define HAVE_UNISTD_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_STATVFS_H 1
| #define HAVE_SYS_STATFS_H 1
| #define HAVE_OFFSETOF
| #define HAVE_STDBOOL_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_FILE_H 1
| #define DIRENT
| #define HAVE_SYS_UTSNAME_H
| #define HAVE_NETDB_H 1
| #define HAVE_SYS_SHM_H 1
| #define HAVE_SYS_IPC_H 1
| #define HAVE_TERMIOS_H 1
| #define HAVE_TERMIO_H 1
| #define HAVE_SYS_TERMIO_H 1
| #define HAVE_TCGETATTR
| #define HAVE_TCSAFLUSH
| #define HAVE_X11
| #define CADDR_T caddr_t
| #define SOCKLEN_T int
| #define SIZEOF_OFF_T 8
| #define SIZEOF_INO_T 8
| #define SIZEOF_STRUCT_TIMEVAL 8
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
| #define HAVE__JMP
| #define RETSIGTYPE void
| #define SIGNALBLOCK_SYSV
| #define SIGNALBLOCK_POSIX
| #define SIGNAL_NEED_REINSTALL
| #define SIGNAL_NEED_UNBLOCK
| #define SIGNAL_NEED_UNBLOCK_OTHERS
| #define HAVE_SIGACTION 1
| #define HAVE_SIGINTERRUPT 1
| #define HAVE_RAISE
| #define RETABORTTYPE void
| #define ABORT_VOLATILE
| #define HAVE_PERROR_DECL
| #define HAVE_STRERROR 1
| #define HAVE_SYSCONF 1
| #define HAVE_GETDTABLESIZE 1
| #define HAVE_MEMSET 1
| #define HAVE_SETSID 1
| #define HAVE_SETPGID 1
| #define HAVE_FSYNC 1
| #define HAVE_FLOCK 1
| #define HAVE_SHUTDOWN 1
| #define HAVE_USLEEP 1
| #define HAVE_UALARM 1
| #define HAVE_SETITIMER 1
| #define HAVE_NICE 1
| #define HAVE_FTIME 1
| #define HAVE_REALPATH 1
| #define HAVE_PUTENV 1
| #define HAVE_SETENV 1
| #define HAVE_DECL_ENVIRON 1
| #define HAVE_LC_MESSAGES 1
| #define HAVE_GETRLIMIT 1
| #define HAVE_SETRLIMIT 1
| #define SIZEOF_RLIM_T 4
| #define RLIMIT_RESOURCE_T int
| #define SETRLIMIT_CONST const
| #define HAVE_UNISTD_H 1
| #define HAVE_FORK 1
| #define HAVE_VFORK 1
| #define HAVE_WORKING_VFORK 1
| #define HAVE_WORKING_FORK 1
| #define PID_T pid_t
| #define HAVE_SYS_RESOURCE_H 1
| #define HAVE_SYS_TIMES_H 1
| #define HAVE_GETRUSAGE
| #define RUSAGE_WHO_T int
| #define HAVE_GETCWD
| #define GETCWD_SIZE_T size_t
| #define TIME_WITH_SYS_TIME 1
| #define HAVE_LSTAT
| #define HAVE_READLINK 1
| #define ELOOP_VALUE ELOOP
| #define RETCLOSEDIRTYPE int
| #define HAVE_IOCTL 1
| #define IOCTL_REQUEST_T int
| #define IOCTL_DOTS
| #define HAVE_POLL 1
| #define HAVE_RELIABLE_POLL
| #define HAVE_SELECT 1
| #define HAVE_SYS_SELECT_H
| #define SELECT_WIDTH_T int
| #define SELECT_SET_T fd_set
| #define SELECT_CONST
| #define HAVE_RELIABLE_SELECT
| #define HAVE_GETTIMEOFDAY 1
| #define GETTIMEOFDAY_TZP_T struct timezone *
| #define HAVE_GETHOSTNAME 1
| #define HAVE_GETHOSTBYNAME
| #define HAVE_CONNECT 1
| #define CONNECT_CONST const
| #define CONNECT_NAME_T struct sockaddr *
| #define CONNECT_ADDRLEN_T int
| #define HAVE_SYS_UN_H 1
| #define HAVE_IPV4
| #define HAVE_INET_PTON 1
| #define HAVE_INET_NTOP 1
| #define HAVE_INET_ADDR 1
| #define HAVE_SETSOCKOPT 1
| #define HAVE_GETSOCKOPT 1
| #define HAVE_NETINET_IN_H 1
| #define HAVE_ARPA_INET_H 1
| #define RET_INET_ADDR_TYPE unsigned long
| #define INET_ADDR_CONST const
| #define INET_ADDR_SUFFIX
| #define SETSOCKOPT_CONST const
| #define SETSOCKOPT_ARG_T void*
| #define SETSOCKOPT_OPTLEN_T int
| #define CODE_ADDRESS_RANGE 0x00000000UL
| #define MALLOC_ADDRESS_RANGE 0x00000000UL
| #define SHLIB_ADDRESS_RANGE 0x00000000UL
| #define STACK_ADDRESS_RANGE 0x00000000UL
| #define HAVE_GETPAGESIZE
| #define RETGETPAGESIZETYPE size_t
| #define HAVE_MMAP
| /* end confdefs.h.  */
|
| #include <stdlib.h>
| #if defined __MACH__ && defined __APPLE__
| /* Avoid a crash on MacOS X.  */
| #include <mach/mach.h>
| #include <mach/mach_error.h>
| #include <mach/thread_status.h>
| #include <mach/exception.h>
| #include <mach/task.h>
| #include <pthread.h>
| /* The exception port on which our thread listens.  */
| static mach_port_t our_exception_port;
| /* The main function of the thread listening for exceptions of type
|    EXC_BAD_ACCESS.  */
| static void *
| mach_exception_thread (void *arg)
| {
|   /* Buffer for a message to be received.  */
|   struct {
|     mach_msg_header_t head;
|     mach_msg_body_t msgh_body;
|     char data[1024];
|   } msg;
|   mach_msg_return_t retval;
|   /* Wait for a message on the exception port.  */
|   retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
|                      our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|   if (retval != MACH_MSG_SUCCESS)
|     abort ();
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
|   mach_port_t self = mach_task_self ();
|   /* Allocate a port on which the thread shall listen for exceptions.  */
|   if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
|       == KERN_SUCCESS) {
|     /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
|     if (mach_port_insert_right (self, our_exception_port, our_exception_port,
|                                 MACH_MSG_TYPE_MAKE_SEND)
|         == KERN_SUCCESS) {
|       /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
|          for us.  */
|       exception_mask_t mask = EXC_MASK_BAD_ACCESS;
|       /* Create the thread listening on the exception port.  */
|       pthread_attr_t attr;
|       pthread_t thread;
|       if (pthread_attr_init (&attr) == 0
|           && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
|           && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
|         pthread_attr_destroy (&attr);
|         /* Replace the exception port info for these exceptions with our own.
|            Note that we replace the exception port for the entire task, not only
|            for a particular thread.  This has the effect that when our exception
|            port gets the message, the thread specific exception port has already
|            been asked, and we don't need to bother about it.
|            See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
|         task_set_exception_ports (self, mask, our_exception_port,
|                                   EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
|       }
|     }
|   }
| }
| #else
| /* Avoid a crash on POSIX systems.  */
| #include <signal.h>
| /* A POSIX signal handler.  */
| static void
| exception_handler (int sig)
| {
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
| #ifdef SIGSEGV
|   signal (SIGSEGV, exception_handler);
| #endif
| #ifdef SIGBUS
|   signal (SIGBUS, exception_handler);
| #endif
| }
| #endif
|
| #include <stdlib.h>
| #ifdef HAVE_UNISTD_H
| #include <unistd.h>
| #endif
| #include <fcntl.h>
| #ifdef OPEN_NEEDS_SYS_FILE_H
| #include <sys/file.h>
| #endif
| #include <sys/types.h>
| #include <sys/mman.h>
| int main () {
|
|   int flags = MAP_ANON | MAP_PRIVATE;
|   int fd = -1;
|   nocrash_init();
| #define bits_to_avoid 0
| #define my_shift 24
| #define my_low   1
| #ifdef FOR_SUN4_29
| #define my_high  31
| #define my_size  32768 /* hope that 32768 is a multiple of the page size */
| /* i*32 KB for i=1..31 gives a total of 15.5 MB, which is close to what we need */
| #else
| #define my_high  64
| #define my_size  8192 /* hope that 8192 is a multiple of the page size */
| /* i*8 KB for i=1..64 gives a total of 16.25 MB, which is close to what we need */
| #endif
|  {long i;
| #define i_ok(i)  ((i) & (bits_to_avoid >> my_shift) == 0)
|   for (i=my_low; i<=my_high; i++)
|     if (i_ok(i))
|       { caddr_t addr = (caddr_t)(i << my_shift);
| /* Check for 8 MB, not 16 MB. This is more likely to work on Solaris 2. */
| #if bits_to_avoid
|         long size = i*my_size;
| #else
|         long size = ((i+1)/2)*my_size;
| #endif
|         if (mmap(addr,size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) == (void*)-1) exit(1);
|     }
| #define x(i)  *(unsigned char *) ((i<<my_shift) + (i*i))
| #define y(i)  (unsigned char)((3*i-4)*(7*i+3))
|   for (i=my_low; i<=my_high; i++) if (i_ok(i)) { x(i) = y(i); }
|   for (i=my_high; i>=my_low; i--) if (i_ok(i)) { if (x(i) != y(i)) exit(1); }
|   exit(0);
| }}
|
|
configure:22831: gcc -o conftest.exe -g -O2 -I/usr/local/libsigsegv-cygwin/include  conftest.c  >&5
configure:22834: $? = 0
configure:22836: ./conftest.exe
configure:22839: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h.  */
|
| #define PACKAGE_NAME "GNU CLISP"
| #define PACKAGE_TARNAME "clisp"
| #define PACKAGE_VERSION "2.35 (2005-08-29)"
| #define PACKAGE_STRING "GNU CLISP 2.35 (2005-08-29)"
| #define PACKAGE_BUGREPORT "http://clisp.cons.org/"
| #define _GNU_SOURCE 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define ASM_UNDERSCORE
| #ifndef __i386__
| #define __i386__ 1
| #endif
| #define HAVE_ICONV 1
| #define ICONV_CONST const
| #define HAVE_ICONV 1
| #define ENABLE_NLS 1
| #define HAVE_GETTEXT 1
| #define HAVE_DCGETTEXT 1
| #define HAVE_SIGSEGV 1
| #define return_void return
| #define HAVE_LONG_LONG 1
| #define HAVE_LONGLONG
| #define STDC_HEADERS 1
| #define HAVE_UNISTD_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_STATVFS_H 1
| #define HAVE_SYS_STATFS_H 1
| #define HAVE_OFFSETOF
| #define HAVE_STDBOOL_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_FILE_H 1
| #define DIRENT
| #define HAVE_SYS_UTSNAME_H
| #define HAVE_NETDB_H 1
| #define HAVE_SYS_SHM_H 1
| #define HAVE_SYS_IPC_H 1
| #define HAVE_TERMIOS_H 1
| #define HAVE_TERMIO_H 1
| #define HAVE_SYS_TERMIO_H 1
| #define HAVE_TCGETATTR
| #define HAVE_TCSAFLUSH
| #define HAVE_X11
| #define CADDR_T caddr_t
| #define SOCKLEN_T int
| #define SIZEOF_OFF_T 8
| #define SIZEOF_INO_T 8
| #define SIZEOF_STRUCT_TIMEVAL 8
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
| #define HAVE__JMP
| #define RETSIGTYPE void
| #define SIGNALBLOCK_SYSV
| #define SIGNALBLOCK_POSIX
| #define SIGNAL_NEED_REINSTALL
| #define SIGNAL_NEED_UNBLOCK
| #define SIGNAL_NEED_UNBLOCK_OTHERS
| #define HAVE_SIGACTION 1
| #define HAVE_SIGINTERRUPT 1
| #define HAVE_RAISE
| #define RETABORTTYPE void
| #define ABORT_VOLATILE
| #define HAVE_PERROR_DECL
| #define HAVE_STRERROR 1
| #define HAVE_SYSCONF 1
| #define HAVE_GETDTABLESIZE 1
| #define HAVE_MEMSET 1
| #define HAVE_SETSID 1
| #define HAVE_SETPGID 1
| #define HAVE_FSYNC 1
| #define HAVE_FLOCK 1
| #define HAVE_SHUTDOWN 1
| #define HAVE_USLEEP 1
| #define HAVE_UALARM 1
| #define HAVE_SETITIMER 1
| #define HAVE_NICE 1
| #define HAVE_FTIME 1
| #define HAVE_REALPATH 1
| #define HAVE_PUTENV 1
| #define HAVE_SETENV 1
| #define HAVE_DECL_ENVIRON 1
| #define HAVE_LC_MESSAGES 1
| #define HAVE_GETRLIMIT 1
| #define HAVE_SETRLIMIT 1
| #define SIZEOF_RLIM_T 4
| #define RLIMIT_RESOURCE_T int
| #define SETRLIMIT_CONST const
| #define HAVE_UNISTD_H 1
| #define HAVE_FORK 1
| #define HAVE_VFORK 1
| #define HAVE_WORKING_VFORK 1
| #define HAVE_WORKING_FORK 1
| #define PID_T pid_t
| #define HAVE_SYS_RESOURCE_H 1
| #define HAVE_SYS_TIMES_H 1
| #define HAVE_GETRUSAGE
| #define RUSAGE_WHO_T int
| #define HAVE_GETCWD
| #define GETCWD_SIZE_T size_t
| #define TIME_WITH_SYS_TIME 1
| #define HAVE_LSTAT
| #define HAVE_READLINK 1
| #define ELOOP_VALUE ELOOP
| #define RETCLOSEDIRTYPE int
| #define HAVE_IOCTL 1
| #define IOCTL_REQUEST_T int
| #define IOCTL_DOTS
| #define HAVE_POLL 1
| #define HAVE_RELIABLE_POLL
| #define HAVE_SELECT 1
| #define HAVE_SYS_SELECT_H
| #define SELECT_WIDTH_T int
| #define SELECT_SET_T fd_set
| #define SELECT_CONST
| #define HAVE_RELIABLE_SELECT
| #define HAVE_GETTIMEOFDAY 1
| #define GETTIMEOFDAY_TZP_T struct timezone *
| #define HAVE_GETHOSTNAME 1
| #define HAVE_GETHOSTBYNAME
| #define HAVE_CONNECT 1
| #define CONNECT_CONST const
| #define CONNECT_NAME_T struct sockaddr *
| #define CONNECT_ADDRLEN_T int
| #define HAVE_SYS_UN_H 1
| #define HAVE_IPV4
| #define HAVE_INET_PTON 1
| #define HAVE_INET_NTOP 1
| #define HAVE_INET_ADDR 1
| #define HAVE_SETSOCKOPT 1
| #define HAVE_GETSOCKOPT 1
| #define HAVE_NETINET_IN_H 1
| #define HAVE_ARPA_INET_H 1
| #define RET_INET_ADDR_TYPE unsigned long
| #define INET_ADDR_CONST const
| #define INET_ADDR_SUFFIX
| #define SETSOCKOPT_CONST const
| #define SETSOCKOPT_ARG_T void*
| #define SETSOCKOPT_OPTLEN_T int
| #define CODE_ADDRESS_RANGE 0x00000000UL
| #define MALLOC_ADDRESS_RANGE 0x00000000UL
| #define SHLIB_ADDRESS_RANGE 0x00000000UL
| #define STACK_ADDRESS_RANGE 0x00000000UL
| #define HAVE_GETPAGESIZE
| #define RETGETPAGESIZETYPE size_t
| #define HAVE_MMAP
| /* end confdefs.h.  */
|
| #include <stdlib.h>
| #if defined __MACH__ && defined __APPLE__
| /* Avoid a crash on MacOS X.  */
| #include <mach/mach.h>
| #include <mach/mach_error.h>
| #include <mach/thread_status.h>
| #include <mach/exception.h>
| #include <mach/task.h>
| #include <pthread.h>
| /* The exception port on which our thread listens.  */
| static mach_port_t our_exception_port;
| /* The main function of the thread listening for exceptions of type
|    EXC_BAD_ACCESS.  */
| static void *
| mach_exception_thread (void *arg)
| {
|   /* Buffer for a message to be received.  */
|   struct {
|     mach_msg_header_t head;
|     mach_msg_body_t msgh_body;
|     char data[1024];
|   } msg;
|   mach_msg_return_t retval;
|   /* Wait for a message on the exception port.  */
|   retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
|                      our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|   if (retval != MACH_MSG_SUCCESS)
|     abort ();
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
|   mach_port_t self = mach_task_self ();
|   /* Allocate a port on which the thread shall listen for exceptions.  */
|   if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
|       == KERN_SUCCESS) {
|     /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
|     if (mach_port_insert_right (self, our_exception_port, our_exception_port,
|                                 MACH_MSG_TYPE_MAKE_SEND)
|         == KERN_SUCCESS) {
|       /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
|          for us.  */
|       exception_mask_t mask = EXC_MASK_BAD_ACCESS;
|       /* Create the thread listening on the exception port.  */
|       pthread_attr_t attr;
|       pthread_t thread;
|       if (pthread_attr_init (&attr) == 0
|           && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
|           && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
|         pthread_attr_destroy (&attr);
|         /* Replace the exception port info for these exceptions with our own.
|            Note that we replace the exception port for the entire task, not only
|            for a particular thread.  This has the effect that when our exception
|            port gets the message, the thread specific exception port has already
|            been asked, and we don't need to bother about it.
|            See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
|         task_set_exception_ports (self, mask, our_exception_port,
|                                   EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
|       }
|     }
|   }
| }
| #else
| /* Avoid a crash on POSIX systems.  */
| #include <signal.h>
| /* A POSIX signal handler.  */
| static void
| exception_handler (int sig)
| {
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
| #ifdef SIGSEGV
|   signal (SIGSEGV, exception_handler);
| #endif
| #ifdef SIGBUS
|   signal (SIGBUS, exception_handler);
| #endif
| }
| #endif
|
| #include <stdlib.h>
| #ifdef HAVE_UNISTD_H
| #include <unistd.h>
| #endif
| #include <fcntl.h>
| #ifdef OPEN_NEEDS_SYS_FILE_H
| #include <sys/file.h>
| #endif
| #include <sys/types.h>
| #include <sys/mman.h>
| int main () {
|
|   int flags = MAP_ANONYMOUS | MAP_PRIVATE;
|   int fd = -1;
|   nocrash_init();
| #define bits_to_avoid 0
| #define my_shift 24
| #define my_low   1
| #ifdef FOR_SUN4_29
| #define my_high  31
| #define my_size  32768 /* hope that 32768 is a multiple of the page size */
| /* i*32 KB for i=1..31 gives a total of 15.5 MB, which is close to what we need */
| #else
| #define my_high  64
| #define my_size  8192 /* hope that 8192 is a multiple of the page size */
| /* i*8 KB for i=1..64 gives a total of 16.25 MB, which is close to what we need */
| #endif
|  {long i;
| #define i_ok(i)  ((i) & (bits_to_avoid >> my_shift) == 0)
|   for (i=my_low; i<=my_high; i++)
|     if (i_ok(i))
|       { caddr_t addr = (caddr_t)(i << my_shift);
| /* Check for 8 MB, not 16 MB. This is more likely to work on Solaris 2. */
| #if bits_to_avoid
|         long size = i*my_size;
| #else
|         long size = ((i+1)/2)*my_size;
| #endif
|         if (mmap(addr,size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) == (void*)-1) exit(1);
|     }
| #define x(i)  *(unsigned char *) ((i<<my_shift) + (i*i))
| #define y(i)  (unsigned char)((3*i-4)*(7*i+3))
|   for (i=my_low; i<=my_high; i++) if (i_ok(i)) { x(i) = y(i); }
|   for (i=my_high; i>=my_low; i--) if (i_ok(i)) { if (x(i) != y(i)) exit(1); }
|   exit(0);
| }}
|
|
configure:22957: gcc -o conftest.exe -g -O2 -I/usr/local/libsigsegv-cygwin/include  conftest.c  >&5
configure:22960: $? = 0
configure:22962: ./conftest.exe
configure:22965: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h.  */
|
| #define PACKAGE_NAME "GNU CLISP"
| #define PACKAGE_TARNAME "clisp"
| #define PACKAGE_VERSION "2.35 (2005-08-29)"
| #define PACKAGE_STRING "GNU CLISP 2.35 (2005-08-29)"
| #define PACKAGE_BUGREPORT "http://clisp.cons.org/"
| #define _GNU_SOURCE 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define ASM_UNDERSCORE
| #ifndef __i386__
| #define __i386__ 1
| #endif
| #define HAVE_ICONV 1
| #define ICONV_CONST const
| #define HAVE_ICONV 1
| #define ENABLE_NLS 1
| #define HAVE_GETTEXT 1
| #define HAVE_DCGETTEXT 1
| #define HAVE_SIGSEGV 1
| #define return_void return
| #define HAVE_LONG_LONG 1
| #define HAVE_LONGLONG
| #define STDC_HEADERS 1
| #define HAVE_UNISTD_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_STATVFS_H 1
| #define HAVE_SYS_STATFS_H 1
| #define HAVE_OFFSETOF
| #define HAVE_STDBOOL_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_FILE_H 1
| #define DIRENT
| #define HAVE_SYS_UTSNAME_H
| #define HAVE_NETDB_H 1
| #define HAVE_SYS_SHM_H 1
| #define HAVE_SYS_IPC_H 1
| #define HAVE_TERMIOS_H 1
| #define HAVE_TERMIO_H 1
| #define HAVE_SYS_TERMIO_H 1
| #define HAVE_TCGETATTR
| #define HAVE_TCSAFLUSH
| #define HAVE_X11
| #define CADDR_T caddr_t
| #define SOCKLEN_T int
| #define SIZEOF_OFF_T 8
| #define SIZEOF_INO_T 8
| #define SIZEOF_STRUCT_TIMEVAL 8
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
| #define HAVE__JMP
| #define RETSIGTYPE void
| #define SIGNALBLOCK_SYSV
| #define SIGNALBLOCK_POSIX
| #define SIGNAL_NEED_REINSTALL
| #define SIGNAL_NEED_UNBLOCK
| #define SIGNAL_NEED_UNBLOCK_OTHERS
| #define HAVE_SIGACTION 1
| #define HAVE_SIGINTERRUPT 1
| #define HAVE_RAISE
| #define RETABORTTYPE void
| #define ABORT_VOLATILE
| #define HAVE_PERROR_DECL
| #define HAVE_STRERROR 1
| #define HAVE_SYSCONF 1
| #define HAVE_GETDTABLESIZE 1
| #define HAVE_MEMSET 1
| #define HAVE_SETSID 1
| #define HAVE_SETPGID 1
| #define HAVE_FSYNC 1
| #define HAVE_FLOCK 1
| #define HAVE_SHUTDOWN 1
| #define HAVE_USLEEP 1
| #define HAVE_UALARM 1
| #define HAVE_SETITIMER 1
| #define HAVE_NICE 1
| #define HAVE_FTIME 1
| #define HAVE_REALPATH 1
| #define HAVE_PUTENV 1
| #define HAVE_SETENV 1
| #define HAVE_DECL_ENVIRON 1
| #define HAVE_LC_MESSAGES 1
| #define HAVE_GETRLIMIT 1
| #define HAVE_SETRLIMIT 1
| #define SIZEOF_RLIM_T 4
| #define RLIMIT_RESOURCE_T int
| #define SETRLIMIT_CONST const
| #define HAVE_UNISTD_H 1
| #define HAVE_FORK 1
| #define HAVE_VFORK 1
| #define HAVE_WORKING_VFORK 1
| #define HAVE_WORKING_FORK 1
| #define PID_T pid_t
| #define HAVE_SYS_RESOURCE_H 1
| #define HAVE_SYS_TIMES_H 1
| #define HAVE_GETRUSAGE
| #define RUSAGE_WHO_T int
| #define HAVE_GETCWD
| #define GETCWD_SIZE_T size_t
| #define TIME_WITH_SYS_TIME 1
| #define HAVE_LSTAT
| #define HAVE_READLINK 1
| #define ELOOP_VALUE ELOOP
| #define RETCLOSEDIRTYPE int
| #define HAVE_IOCTL 1
| #define IOCTL_REQUEST_T int
| #define IOCTL_DOTS
| #define HAVE_POLL 1
| #define HAVE_RELIABLE_POLL
| #define HAVE_SELECT 1
| #define HAVE_SYS_SELECT_H
| #define SELECT_WIDTH_T int
| #define SELECT_SET_T fd_set
| #define SELECT_CONST
| #define HAVE_RELIABLE_SELECT
| #define HAVE_GETTIMEOFDAY 1
| #define GETTIMEOFDAY_TZP_T struct timezone *
| #define HAVE_GETHOSTNAME 1
| #define HAVE_GETHOSTBYNAME
| #define HAVE_CONNECT 1
| #define CONNECT_CONST const
| #define CONNECT_NAME_T struct sockaddr *
| #define CONNECT_ADDRLEN_T int
| #define HAVE_SYS_UN_H 1
| #define HAVE_IPV4
| #define HAVE_INET_PTON 1
| #define HAVE_INET_NTOP 1
| #define HAVE_INET_ADDR 1
| #define HAVE_SETSOCKOPT 1
| #define HAVE_GETSOCKOPT 1
| #define HAVE_NETINET_IN_H 1
| #define HAVE_ARPA_INET_H 1
| #define RET_INET_ADDR_TYPE unsigned long
| #define INET_ADDR_CONST const
| #define INET_ADDR_SUFFIX
| #define SETSOCKOPT_CONST const
| #define SETSOCKOPT_ARG_T void*
| #define SETSOCKOPT_OPTLEN_T int
| #define CODE_ADDRESS_RANGE 0x00000000UL
| #define MALLOC_ADDRESS_RANGE 0x00000000UL
| #define SHLIB_ADDRESS_RANGE 0x00000000UL
| #define STACK_ADDRESS_RANGE 0x00000000UL
| #define HAVE_GETPAGESIZE
| #define RETGETPAGESIZETYPE size_t
| #define HAVE_MMAP
| /* end confdefs.h.  */
|
| #include <stdlib.h>
| #if defined __MACH__ && defined __APPLE__
| /* Avoid a crash on MacOS X.  */
| #include <mach/mach.h>
| #include <mach/mach_error.h>
| #include <mach/thread_status.h>
| #include <mach/exception.h>
| #include <mach/task.h>
| #include <pthread.h>
| /* The exception port on which our thread listens.  */
| static mach_port_t our_exception_port;
| /* The main function of the thread listening for exceptions of type
|    EXC_BAD_ACCESS.  */
| static void *
| mach_exception_thread (void *arg)
| {
|   /* Buffer for a message to be received.  */
|   struct {
|     mach_msg_header_t head;
|     mach_msg_body_t msgh_body;
|     char data[1024];
|   } msg;
|   mach_msg_return_t retval;
|   /* Wait for a message on the exception port.  */
|   retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
|                      our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|   if (retval != MACH_MSG_SUCCESS)
|     abort ();
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
|   mach_port_t self = mach_task_self ();
|   /* Allocate a port on which the thread shall listen for exceptions.  */
|   if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
|       == KERN_SUCCESS) {
|     /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
|     if (mach_port_insert_right (self, our_exception_port, our_exception_port,
|                                 MACH_MSG_TYPE_MAKE_SEND)
|         == KERN_SUCCESS) {
|       /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
|          for us.  */
|       exception_mask_t mask = EXC_MASK_BAD_ACCESS;
|       /* Create the thread listening on the exception port.  */
|       pthread_attr_t attr;
|       pthread_t thread;
|       if (pthread_attr_init (&attr) == 0
|           && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
|           && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
|         pthread_attr_destroy (&attr);
|         /* Replace the exception port info for these exceptions with our own.
|            Note that we replace the exception port for the entire task, not only
|            for a particular thread.  This has the effect that when our exception
|            port gets the message, the thread specific exception port has already
|            been asked, and we don't need to bother about it.
|            See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
|         task_set_exception_ports (self, mask, our_exception_port,
|                                   EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
|       }
|     }
|   }
| }
| #else
| /* Avoid a crash on POSIX systems.  */
| #include <signal.h>
| /* A POSIX signal handler.  */
| static void
| exception_handler (int sig)
| {
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
| #ifdef SIGSEGV
|   signal (SIGSEGV, exception_handler);
| #endif
| #ifdef SIGBUS
|   signal (SIGBUS, exception_handler);
| #endif
| }
| #endif
|
| #include <stdlib.h>
| #ifdef HAVE_UNISTD_H
| #include <unistd.h>
| #endif
| #include <fcntl.h>
| #ifdef OPEN_NEEDS_SYS_FILE_H
| #include <sys/file.h>
| #endif
| #include <sys/types.h>
| #include <sys/mman.h>
| int main () {
|
| #ifndef MAP_FILE
| #define MAP_FILE 0
| #endif
|   int flags = MAP_FILE | MAP_PRIVATE;
|   int fd = open("/dev/zero",O_RDONLY,0666);
|   if (fd<0) exit(1);
|   nocrash_init();
| #define bits_to_avoid 0
| #define my_shift 24
| #define my_low   1
| #ifdef FOR_SUN4_29
| #define my_high  31
| #define my_size  32768 /* hope that 32768 is a multiple of the page size */
| /* i*32 KB for i=1..31 gives a total of 15.5 MB, which is close to what we need */
| #else
| #define my_high  64
| #define my_size  8192 /* hope that 8192 is a multiple of the page size */
| /* i*8 KB for i=1..64 gives a total of 16.25 MB, which is close to what we need */
| #endif
|  {long i;
| #define i_ok(i)  ((i) & (bits_to_avoid >> my_shift) == 0)
|   for (i=my_low; i<=my_high; i++)
|     if (i_ok(i))
|       { caddr_t addr = (caddr_t)(i << my_shift);
| /* Check for 8 MB, not 16 MB. This is more likely to work on Solaris 2. */
| #if bits_to_avoid
|         long size = i*my_size;
| #else
|         long size = ((i+1)/2)*my_size;
| #endif
|         if (mmap(addr,size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) == (void*)-1) exit(1);
|     }
| #define x(i)  *(unsigned char *) ((i<<my_shift) + (i*i))
| #define y(i)  (unsigned char)((3*i-4)*(7*i+3))
|   for (i=my_low; i<=my_high; i++) if (i_ok(i)) { x(i) = y(i); }
|   for (i=my_high; i>=my_low; i--) if (i_ok(i)) { if (x(i) != y(i)) exit(1); }
|   exit(0);
| }}
|
|
configure:23087: gcc -o conftest.exe -g -O2 -I/usr/local/libsigsegv-cygwin/include  conftest.c  >&5
configure:23090: $? = 0
configure:23092: ./conftest.exe
configure:23095: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h.  */
|
| #define PACKAGE_NAME "GNU CLISP"
| #define PACKAGE_TARNAME "clisp"
| #define PACKAGE_VERSION "2.35 (2005-08-29)"
| #define PACKAGE_STRING "GNU CLISP 2.35 (2005-08-29)"
| #define PACKAGE_BUGREPORT "http://clisp.cons.org/"
| #define _GNU_SOURCE 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define __EXTENSIONS__ 1
| #define _POSIX_PTHREAD_SEMANTICS 1
| #define ASM_UNDERSCORE
| #ifndef __i386__
| #define __i386__ 1
| #endif
| #define HAVE_ICONV 1
| #define ICONV_CONST const
| #define HAVE_ICONV 1
| #define ENABLE_NLS 1
| #define HAVE_GETTEXT 1
| #define HAVE_DCGETTEXT 1
| #define HAVE_SIGSEGV 1
| #define return_void return
| #define HAVE_LONG_LONG 1
| #define HAVE_LONGLONG
| #define STDC_HEADERS 1
| #define HAVE_UNISTD_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_STATVFS_H 1
| #define HAVE_SYS_STATFS_H 1
| #define HAVE_OFFSETOF
| #define HAVE_STDBOOL_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_SYS_FILE_H 1
| #define HAVE_SYS_FILE_H 1
| #define DIRENT
| #define HAVE_SYS_UTSNAME_H
| #define HAVE_NETDB_H 1
| #define HAVE_SYS_SHM_H 1
| #define HAVE_SYS_IPC_H 1
| #define HAVE_TERMIOS_H 1
| #define HAVE_TERMIO_H 1
| #define HAVE_SYS_TERMIO_H 1
| #define HAVE_TCGETATTR
| #define HAVE_TCSAFLUSH
| #define HAVE_X11
| #define CADDR_T caddr_t
| #define SOCKLEN_T int
| #define SIZEOF_OFF_T 8
| #define SIZEOF_INO_T 8
| #define SIZEOF_STRUCT_TIMEVAL 8
| #define HAVE_ALLOCA_H 1
| #define HAVE_ALLOCA 1
| #define HAVE__JMP
| #define RETSIGTYPE void
| #define SIGNALBLOCK_SYSV
| #define SIGNALBLOCK_POSIX
| #define SIGNAL_NEED_REINSTALL
| #define SIGNAL_NEED_UNBLOCK
| #define SIGNAL_NEED_UNBLOCK_OTHERS
| #define HAVE_SIGACTION 1
| #define HAVE_SIGINTERRUPT 1
| #define HAVE_RAISE
| #define RETABORTTYPE void
| #define ABORT_VOLATILE
| #define HAVE_PERROR_DECL
| #define HAVE_STRERROR 1
| #define HAVE_SYSCONF 1
| #define HAVE_GETDTABLESIZE 1
| #define HAVE_MEMSET 1
| #define HAVE_SETSID 1
| #define HAVE_SETPGID 1
| #define HAVE_FSYNC 1
| #define HAVE_FLOCK 1
| #define HAVE_SHUTDOWN 1
| #define HAVE_USLEEP 1
| #define HAVE_UALARM 1
| #define HAVE_SETITIMER 1
| #define HAVE_NICE 1
| #define HAVE_FTIME 1
| #define HAVE_REALPATH 1
| #define HAVE_PUTENV 1
| #define HAVE_SETENV 1
| #define HAVE_DECL_ENVIRON 1
| #define HAVE_LC_MESSAGES 1
| #define HAVE_GETRLIMIT 1
| #define HAVE_SETRLIMIT 1
| #define SIZEOF_RLIM_T 4
| #define RLIMIT_RESOURCE_T int
| #define SETRLIMIT_CONST const
| #define HAVE_UNISTD_H 1
| #define HAVE_FORK 1
| #define HAVE_VFORK 1
| #define HAVE_WORKING_VFORK 1
| #define HAVE_WORKING_FORK 1
| #define PID_T pid_t
| #define HAVE_SYS_RESOURCE_H 1
| #define HAVE_SYS_TIMES_H 1
| #define HAVE_GETRUSAGE
| #define RUSAGE_WHO_T int
| #define HAVE_GETCWD
| #define GETCWD_SIZE_T size_t
| #define TIME_WITH_SYS_TIME 1
| #define HAVE_LSTAT
| #define HAVE_READLINK 1
| #define ELOOP_VALUE ELOOP
| #define RETCLOSEDIRTYPE int
| #define HAVE_IOCTL 1
| #define IOCTL_REQUEST_T int
| #define IOCTL_DOTS
| #define HAVE_POLL 1
| #define HAVE_RELIABLE_POLL
| #define HAVE_SELECT 1
| #define HAVE_SYS_SELECT_H
| #define SELECT_WIDTH_T int
| #define SELECT_SET_T fd_set
| #define SELECT_CONST
| #define HAVE_RELIABLE_SELECT
| #define HAVE_GETTIMEOFDAY 1
| #define GETTIMEOFDAY_TZP_T struct timezone *
| #define HAVE_GETHOSTNAME 1
| #define HAVE_GETHOSTBYNAME
| #define HAVE_CONNECT 1
| #define CONNECT_CONST const
| #define CONNECT_NAME_T struct sockaddr *
| #define CONNECT_ADDRLEN_T int
| #define HAVE_SYS_UN_H 1
| #define HAVE_IPV4
| #define HAVE_INET_PTON 1
| #define HAVE_INET_NTOP 1
| #define HAVE_INET_ADDR 1
| #define HAVE_SETSOCKOPT 1
| #define HAVE_GETSOCKOPT 1
| #define HAVE_NETINET_IN_H 1
| #define HAVE_ARPA_INET_H 1
| #define RET_INET_ADDR_TYPE unsigned long
| #define INET_ADDR_CONST const
| #define INET_ADDR_SUFFIX
| #define SETSOCKOPT_CONST const
| #define SETSOCKOPT_ARG_T void*
| #define SETSOCKOPT_OPTLEN_T int
| #define CODE_ADDRESS_RANGE 0x00000000UL
| #define MALLOC_ADDRESS_RANGE 0x00000000UL
| #define SHLIB_ADDRESS_RANGE 0x00000000UL
| #define STACK_ADDRESS_RANGE 0x00000000UL
| #define HAVE_GETPAGESIZE
| #define RETGETPAGESIZETYPE size_t
| #define HAVE_MMAP
| /* end confdefs.h.  */
|
| #include <stdlib.h>
| #if defined __MACH__ && defined __APPLE__
| /* Avoid a crash on MacOS X.  */
| #include <mach/mach.h>
| #include <mach/mach_error.h>
| #include <mach/thread_status.h>
| #include <mach/exception.h>
| #include <mach/task.h>
| #include <pthread.h>
| /* The exception port on which our thread listens.  */
| static mach_port_t our_exception_port;
| /* The main function of the thread listening for exceptions of type
|    EXC_BAD_ACCESS.  */
| static void *
| mach_exception_thread (void *arg)
| {
|   /* Buffer for a message to be received.  */
|   struct {
|     mach_msg_header_t head;
|     mach_msg_body_t msgh_body;
|     char data[1024];
|   } msg;
|   mach_msg_return_t retval;
|   /* Wait for a message on the exception port.  */
|   retval = mach_msg (&msg.head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof (msg),
|                      our_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
|   if (retval != MACH_MSG_SUCCESS)
|     abort ();
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
|   mach_port_t self = mach_task_self ();
|   /* Allocate a port on which the thread shall listen for exceptions.  */
|   if (mach_port_allocate (self, MACH_PORT_RIGHT_RECEIVE, &our_exception_port)
|       == KERN_SUCCESS) {
|     /* See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/mach_port_insert_right.html.  */
|     if (mach_port_insert_right (self, our_exception_port, our_exception_port,
|                                 MACH_MSG_TYPE_MAKE_SEND)
|         == KERN_SUCCESS) {
|       /* The exceptions we want to catch.  Only EXC_BAD_ACCESS is interesting
|          for us.  */
|       exception_mask_t mask = EXC_MASK_BAD_ACCESS;
|       /* Create the thread listening on the exception port.  */
|       pthread_attr_t attr;
|       pthread_t thread;
|       if (pthread_attr_init (&attr) == 0
|           && pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) == 0
|           && pthread_create (&thread, &attr, mach_exception_thread, NULL) == 0) {
|         pthread_attr_destroy (&attr);
|         /* Replace the exception port info for these exceptions with our own.
|            Note that we replace the exception port for the entire task, not only
|            for a particular thread.  This has the effect that when our exception
|            port gets the message, the thread specific exception port has already
|            been asked, and we don't need to bother about it.
|            See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/task_set_exception_ports.html.  */
|         task_set_exception_ports (self, mask, our_exception_port,
|                                   EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
|       }
|     }
|   }
| }
| #else
| /* Avoid a crash on POSIX systems.  */
| #include <signal.h>
| /* A POSIX signal handler.  */
| static void
| exception_handler (int sig)
| {
|   exit (1);
| }
| static void
| nocrash_init (void)
| {
| #ifdef SIGSEGV
|   signal (SIGSEGV, exception_handler);
| #endif
| #ifdef SIGBUS
|   signal (SIGBUS, exception_handler);
| #endif
| }
| #endif
| #define FOR_SUN4_29
|
| #include <stdlib.h>
| #ifdef HAVE_UNISTD_H
| #include <unistd.h>
| #endif
| #include <fcntl.h>
| #ifdef OPEN_NEEDS_SYS_FILE_H
| #include <sys/file.h>
| #endif
| #include <sys/types.h>
| #include <sys/mman.h>
| int main () {
|
| #ifndef MAP_FILE
| #define MAP_FILE 0
| #endif
|   int flags = MAP_FILE | MAP_PRIVATE;
|   int fd = open("/dev/zero",O_RDONLY,0666);
|   if (fd<0) exit(1);
|   nocrash_init();
| #define bits_to_avoid 0
| #define my_shift 24
| #define my_low   1
| #ifdef FOR_SUN4_29
| #define my_high  31
| #define my_size  32768 /* hope that 32768 is a multiple of the page size */
| /* i*32 KB for i=1..31 gives a total of 15.5 MB, which is close to what we need */
| #else
| #define my_high  64
| #define my_size  8192 /* hope that 8192 is a multiple of the page size */
| /* i*8 KB for i=1..64 gives a total of 16.25 MB, which is close to what we need */
| #endif
|  {long i;
| #define i_ok(i)  ((i) & (bits_to_avoid >> my_shift) == 0)
|   for (i=my_low; i<=my_high; i++)
|     if (i_ok(i))
|       { caddr_t addr = (caddr_t)(i << my_shift);
| /* Check for 8 MB, not 16 MB. This is more likely to work on Solaris 2. */
| #if bits_to_avoid
|         long size = i*my_size;
| #else
|         long size = ((i+1)/2)*my_size;
| #endif
|         if (mmap(addr,size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) == (void*)-1) exit(1);
|     }
| #define x(i)  *(unsigned char *) ((i<<my_shift) + (i*i))
| #define y(i)  (unsigned char)((3*i-4)*(7*i+3))
|   for (i=my_low; i<=my_high; i++) if (i_ok(i)) { x(i) = y(i); }
|   for (i=my_high; i>=my_low; i--) if (i_ok(i)) { if (x(i) != y(i)) exit(1); }
|   exit(0);
| }}
|
|
configure:23115: result: no

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Samuel Thibault
Hi,

Sam Steingold, le Mon 28 Nov 2005 09:55:52 -0500, a ?crit :

> | #define my_shift 24
> | #define my_low   1
> | #ifdef FOR_SUN4_29
> | #define my_high  31
> | #define my_size  32768 /* hope that 32768 is a multiple of the page size */
> | /* i*32 KB for i=1..31 gives a total of 15.5 MB, which is close to what we need */
> | #else
> | #define my_high  64
> | #define my_size  8192 /* hope that 8192 is a multiple of the page size */
> | /* i*8 KB for i=1..64 gives a total of 16.25 MB, which is close to what we need */
> | #endif
>...
> |       { caddr_t addr = (caddr_t)(i << my_shift);
> | /* Check for 8 MB, not 16 MB. This is more likely to work on Solaris 2. */
> | #if bits_to_avoid
> |         long size = i*my_size;
> | #else
> |         long size = ((i+1)/2)*my_size;
> | #endif
> |         if (mmap(addr,size,PROT_READ|PROT_WRITE,flags|MAP_FIXED,fd,0) == (void*)-1) exit(1);

This test is just so strange... How can this ever work on many systems ?
A system is free to refuse to mmap anything in the 0x1000000 area...

Can't this test just be turned into mmaping 16MB (not fixed), unmap()
it, and then, from this address, try to mmap pagesize() ? (instead of
obviously wrong 8KB guess...)

Regards,
Samuel

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

Corinna Vinschen-2
In reply to this post by Sam Steingold
On Nov 28 09:55, Sam Steingold wrote:

> > * Corinna Vinschen <[hidden email]> [2005-11-28 12:51:09 +0100]:
> >
> > Many mmap tests make such invalid assumptions about the memory.
>
> This is not just "tests" and the assumptions are not necessarily
> "invalid".  The appended test fails on cygwin but passes on just about
> every unix (linux, *bsd &c).
> This means that the cygwin version of CLISP lacks generational GC (while
> the win32 native version as well as linux, *bsd, solaris &c have it!)
> which is a major feature for memory-intensive computations.

No wonder, it's still based on crappy tests.  The attached configure
script is a good example of making bold assumptions which match a couple
of systems but the programmer didn't bother to verify the correctness of
the code.

Note: If the code works on most major Unixy systems, it isn't necessarily
correct.


Corinna

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

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

Reply | Threaded
Open this post in threaded view
|

Re: mmap() on 64K aligned address fails

René Berber-2
Corinna Vinschen wrote:
[snip]
> No wonder, it's still based on crappy tests.  The attached configure
> script is a good example of making bold assumptions which match a couple
> of systems but the programmer didn't bother to verify the correctness of
> the code.
>
> Note: If the code works on most major Unixy systems, it isn't necessarily
> correct.

I agree.

The sad thing is that not one function in all the libraries that come with the
gcc tree uses the MAP_FIXED flag, only a few of the tests use it.  So we end up
with bad tools (gcj-dbtool for instance core dumps because its badly implemented
for the case where it assumes there is no mmap) or crippled libraries.

Those bad assumptions are hurting their own software.
--
René Berber


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