[Dropping libvir-list]

Eric Blake wrote:
> >> If gnulib would give
> >> us posix_memalign on mingw, we could nuke this #if altogether.
> > 
> > That's pretty difficult (unless you also add a posix_memalign_free)
> > because at the time posix_memalign returns you have lost the base
> > pointer for free().
> 
> Providing a posix_memalign_free defeats the purpose - POSIX requires
> that plain free() will cover the memory returned by posix_memalign.  The
> list of platforms missing posix_memalign is a bit daunting:
> 
> MacOS X 10.5, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, 
> HP-UX 11,
> IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, MSVC 9, Interix 3.5, 
> BeOS.
> 
> but what would be interesting to know is how many of those platforms
> return page-aligned pointers for any malloc() request of a page or more
> of memory.

Tested with the attached program:

MacOS X 10.5  page-aligned for size >= 4 * pagesize
FreeBSD 6.4   page-aligned for size >= pagesize - 16
NetBSD 5.1    page-aligned for size >= pagesize - 16
OpenBSD 4.9   page-aligned for size >= pagesize
Minix 3.1.8   not page-aligned at all
AIX 5.1       not page-aligned at all
HP-UX 11      not page-aligned at all
IRIX 6.5      not page-aligned at all
OSF/1 5.1     not page-aligned at all
Solaris 10    not page-aligned at all
Cygwin 1.5.x  not page-aligned at all
mingw         not page-aligned at all
MSVC 9        not page-aligned at all
Interix 3.5 -- likely the same as MSVC.
BeOS        -- likely the same as glibc: not page-aligned at all

I tried a posix_memalign() implementation that assumes that if
p = malloc(n) and p < q < p + n, free(q) will be equivalent to free(p).
Results:
MacOS X 10.5  many error messages
FreeBSD 6.4   many error messages
NetBSD 5.1    crashes
OpenBSD 4.9   crashes
Minix 3.1.8   crashes
AIX 5.1       crashes
HP-UX 11      crashes
IRIX 6.5      crashes
OSF/1 5.1     runs out of memory, process cannot be killed with "kill -9"
Solaris 10    leaks memory
Cygwin 1.5.x  crashes
mingw         leaks memory, hangs
MSVC 9        leaks memory

So, there doesn't seem to be an avenue in second-guessing how the malloc()
implementation works internally.

> That is, we may be able to coerce malloc into aligned
> results by over-allocating and over-aligning the user's request, if the
> system malloc() has at least one mode of returning page-aligned memory.

However, over-allocating wastes memory. We have a 'pagealign_alloc' module
that does not waste memory.

> Another alternative is to override free() at the same time as providing
> posix_memalign().

I wouldn't like to slow down free(), which is used in many places, for the
sake of posix_memalign() (as opposed to pagealign_alloc()) which is rarely
used.

Bruno


2011-11-25  Bruno Haible  <br...@clisp.org>

        pagealign_alloc: Doc and comments.
        * doc/posix-functions/posix_memalign.texi: Refer to the pagealign_alloc
        module.
        * lib/pagealign_alloc.c (pagealign_alloc): Add comment.

--- doc/posix-functions/posix_memalign.texi.orig        Fri Nov 25 22:29:43 2011
+++ doc/posix-functions/posix_memalign.texi     Fri Nov 25 22:19:11 2011
@@ -17,3 +17,6 @@
 MacOS X 10.5, FreeBSD 6.0, NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, 
HP-UX 11,
 IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 1.5.x, mingw, MSVC 9, Interix 3.5, 
BeOS.
 @end itemize
+
+The Gnulib module @code{pagealign_alloc} provides a similar API
+that returns memory aligned on a system page boundary.
--- lib/pagealign_alloc.c.orig  Fri Nov 25 22:29:43 2011
+++ lib/pagealign_alloc.c       Fri Nov 25 22:29:26 2011
@@ -123,6 +123,9 @@
 pagealign_alloc (size_t size)
 {
   void *ret;
+  /* We prefer the mmap() approach over the posix_memalign() or malloc()
+     based approaches, since the latter often waste an entire memory page
+     per call.  */
 #if HAVE_MMAP
 # ifdef HAVE_MAP_ANONYMOUS
   const int fd = -1;

-- 
In memoriam Valentín Elizalde <http://en.wikipedia.org/wiki/Valentín_Elizalde>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main ()
{
  static int fib[] =
    { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578 };
  int pagesize = getpagesize();
  int block_sizes[16];
  int i;

  printf ("pagesize = 0x%X\n", pagesize);

  block_sizes[0] = pagesize / 4;
  block_sizes[1] = pagesize / 2 - 16;
  block_sizes[2] = pagesize / 2;
  block_sizes[3] = pagesize - 16;
  block_sizes[4] = pagesize;
  block_sizes[5] = pagesize * 3 / 2;
  block_sizes[6] = pagesize * 2;
  block_sizes[7] = pagesize * 5 / 2;
  block_sizes[8] = pagesize * 3;
  block_sizes[9] = pagesize * 4;
  block_sizes[10] = pagesize * 5;
  block_sizes[11] = pagesize * 8;
  block_sizes[12] = pagesize * 9;
  block_sizes[13] = pagesize * 16;
  block_sizes[14] = pagesize * 17;
  block_sizes[15] = pagesize * 32;

  for (i = 0; i < sizeof(fib)/sizeof(fib[0]); i++)
    {
      void *new_block = malloc (fib[i]);
      int j;

      printf ("After allocating %d bytes:\n", fib[i]);

      for (j = 0; j < sizeof(block_sizes)/sizeof(block_sizes[0]); j++)
        {
          int block_size = block_sizes[j];
          void *p = malloc (block_size);
          printf ("   size=0x%05X -> 0x%08lX\n", block_size, (unsigned long) p);
          free (p);
        }
    }

  return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main ()
{
  static int fib[] =
    { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578 };
  int pagesize = getpagesize();
  int block_sizes[16];
  int i;

  printf ("pagesize = 0x%X\n", pagesize);

  block_sizes[0] = pagesize / 4;
  block_sizes[1] = pagesize / 2 - 16;
  block_sizes[2] = pagesize / 2;
  block_sizes[3] = pagesize - 16;
  block_sizes[4] = pagesize;
  block_sizes[5] = pagesize * 3 / 2;
  block_sizes[6] = pagesize * 2;
  block_sizes[7] = pagesize * 5 / 2;
  block_sizes[8] = pagesize * 3;
  block_sizes[9] = pagesize * 4;
  block_sizes[10] = pagesize * 5;
  block_sizes[11] = pagesize * 8;
  block_sizes[12] = pagesize * 9;
  block_sizes[13] = pagesize * 16;
  block_sizes[14] = pagesize * 17;
  block_sizes[15] = pagesize * 32;

  for (i = 0; i < sizeof(fib)/sizeof(fib[0]); i++)
    {
      void *new_block = malloc (fib[i]);
      int j;

      printf ("After allocating %d bytes:\n", fib[i]);

      for (j = 0; j < sizeof(block_sizes)/sizeof(block_sizes[0]); j++)
        {
          int block_size = block_sizes[j];
          int k;
          printf ("   size=0x%05X ->", block_size);
          for (k = 0; k < 100; k++)
            {
              void *p = (void *) (((unsigned long) malloc (block_size + pagesize - 1) | (pagesize - 1)) + 1);
              if ((k % 25) == 0)
                printf (" 0x%08lX", (unsigned long) p);
              free (p);
            }
          printf ("\n");
        }
    }

  return 0;
}

Reply via email to