[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug-gnulib] valloc()?
From: |
Bruno Haible |
Subject: |
Re: [bug-gnulib] valloc()? |
Date: |
Thu, 3 Mar 2005 15:03:57 +0100 |
User-agent: |
KMail/1.5 |
Derek Price wrote:
> Okay, I've implemented this as you suggested, Bruno. Installed in CVS,
> it passes tests in all four modes (MMAP, MMAP/NO-MAP_ANON,
> POSIX_MEMALIGN, OTHER). I've attached the patch, but I still have a few
> questions.
Thanks. I've installed this into gnulib, with the following minor
modifications:
- Indentation according to GNU standards.
- pagealign_alloc.h:
- Add comments.
- Include <stddef.h>, for size_t.
- pagealign_alloc.c:
- Remove the mention of "public domain" since it contradicts the GPL.
- Include pagealign_alloc.h first, to verify that it is self-consistent.
- Use the 'exit' module for EXIT_FAILURE.
- Don't use EINVAL in an error message that is already verbose enough.
- Drop the trailing dot in error messages that use an errno, since
they are displayed with a colon and the errno explanation following it.
- Fixed portability problem of void* computations like 'orig + pagesize -
1'.
- Use a typedef to avoid many #ifs.
- Rename input parameter 'out' to 'aligned_ptr'. (An input parameter called
'out' is somewhat paradox.)
- Don't use 'new' as variable name, since we might want to compile the
code with a C++ compiler some day.
- Removed unnecessary fields from 'memtable' and renamed it to
'memnode_table'.
- In get_memnode, use abort() instead of exit() to signal a bug in the
calling code.
- Make pagealign_alloc work also if a 'void *' does not fit in a 'long'.
- Use "#if HAVE_POSIX_MEMALIGN" consistently, not a mix of #if here and
#ifdef there.
- mmap.m4: Renamed to mmap-anon.m4 since it cares only about anonymous
mappings, not about file or shared mappings. ('grep' has a different
test for mmap, and 'clisp' yet another one.)
Write config.h, not <config.h>.
Do you still see some nits that could be improved?
Bruno
=========================== modules/pagealign_alloc ========================
Description:
Memory allocation aligned on page boundaries.
Files:
lib/pagealign_alloc.h
lib/pagealign_alloc.c
m4/mmap-anon.m4
m4/pagealign_alloc.m4
Depends-on:
error
exit
getpagesize
xalloc
configure.ac:
gl_PAGEALIGN_ALLOC
Makefile.am:
Include:
#include "pagealign_alloc.h"
License:
GPL
Maintainer:
bug-gnulib@gnu.org
============================= lib/pagealign_alloc.h ========================
/* Memory allocation aligned to system page boundaries.
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
#ifndef _PAGEALIGN_ALLOC_H
# define _PAGEALIGN_ALLOC_H
# include <stddef.h>
/* Allocate a block of memory of SIZE bytes, aligned on a system page
boundary.
If SIZE is not a multiple of the system page size, it will be rounded up
to the next multiple.
Return a pointer to the start of the memory block, or NULL if the allocation
failed. */
extern void *pagealign_alloc (size_t size);
/* Free a memory block.
PTR must be a pointer returned by pagealign_alloc. */
extern void pagealign_free (void *ptr);
#endif /* _PAGEALIGN_ALLOC_H */
============================= lib/pagealign_alloc.c ========================
/* Memory allocation aligned to system page boundaries.
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
USA. */
/* Written by Derek R. Price <derek@ximbiot.com>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "pagealign_alloc.h"
#include <errno.h>
#include <stdlib.h>
#if HAVE_FCNTL_H
# include <fcntl.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#if HAVE_MMAP
# include <sys/mman.h>
#endif
#include "error.h"
#include "exit.h"
#include "getpagesize.h"
#include "xalloc.h"
#if HAVE_MMAP || ! HAVE_POSIX_MEMALIGN
# if HAVE_MMAP
/* For each memory region, we store its size. */
typedef size_t info_t;
# else
/* For each memory region, we store the original pointer returned by
malloc(). */
typedef void * info_t;
# endif
/* A simple linked list of allocated memory regions. It is probably not the
most efficient way to store these, but anyway... */
typedef struct memnode_s memnode_t;
struct memnode_s
{
void *aligned_ptr;
info_t info;
memnode_t *next;
};
/* The list of currently allocated memory regions. */
static memnode_t *memnode_table = NULL;
static void
new_memnode (void *aligned_ptr, info_t info)
{
memnode_t *new_node = (memnode_t *) xmalloc (sizeof (memnode_t));
new_node->aligned_ptr = aligned_ptr;
new_node->info = info;
new_node->next = memnode_table;
memnode_table = new_node;
}
/* Dispose of the memnode containing a map for the ALIGNED_PTR in question
and return the content of the node's INFO field. */
static info_t
get_memnode (void *aligned_ptr)
{
info_t ret;
memnode_t *c;
memnode_t **p_next = &memnode_table;
for (c = *p_next; c != NULL; p_next = &c->next, c = c->next)
if (c->aligned_ptr == aligned_ptr)
break;
if (!c)
/* An attempt to free untracked memory. A wrong pointer was passed
to pagealign_free(). */
abort ();
/* Remove this entry from the list, save the return value, and free it. */
*p_next = c->next;
ret = c->info;
free (c);
return ret;
}
#endif /* HAVE_MMAP || !HAVE_POSIX_MEMALIGN */
void *
pagealign_alloc (size_t size)
{
void *ret;
#if HAVE_MMAP
int flags;
static int fd = -1; /* Only open /dev/zero once in order to avoid limiting
the amount of memory we may allocate based on the
number of open file descriptors. */
# ifdef HAVE_MAP_ANONYMOUS
flags = MAP_ANONYMOUS | MAP_PRIVATE;
fd = -1;
# else /* !HAVE_MAP_ANONYMOUS */
flags = MAP_FILE | MAP_PRIVATE;
if (fd == -1)
{
fd = open ("/dev/zero", O_RDONLY, 0666);
if (fd < 0)
error (EXIT_FAILURE, errno, "Failed to open /dev/zero for read");
}
# endif /* HAVE_MAP_ANONYMOUS */
ret = mmap (NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
if (!ret)
error (EXIT_FAILURE, errno, "mmap to /dev/zero failed");
new_memnode (ret, size);
#elif HAVE_POSIX_MEMALIGN
int status = posix_memalign (&ret, getpagesize (), size);
if (status)
error (EXIT_FAILURE, status, "posix_memalign failed");
#else /* !HAVE_MMAP && !HAVE_POSIX_MEMALIGN */
size_t pagesize = getpagesize ();
void *unaligned_ptr = xmalloc (size + pagesize - 1);
ret = (char *) unaligned_ptr
+ ((- (unsigned long) unaligned_ptr) & (pagesize - 1));
new_memnode (ret, unaligned_ptr);
#endif /* HAVE_MMAP && HAVE_POSIX_MEMALIGN */
return ret;
}
void
pagealign_free (void *aligned_ptr)
{
#if HAVE_MMAP
munmap (aligned_ptr, get_memnode (aligned_ptr));
#elif HAVE_POSIX_MEMALIGN
free (aligned_ptr);
#else
free (get_memnode (aligned_ptr));
#endif
}
=============================== m4/mmap_anon.m4 ============================
# mmap-anon.m4 serial 1
dnl Copyright (C) 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_MMAP],
[
dnl Work around a bug of AC_EGREP_CPP in autoconf-2.57.
AC_REQUIRE([AC_PROG_CPP])
AC_REQUIRE([AC_PROG_EGREP])
dnl Persuade glibc <sys/mman.h> to define MAP_ANONYMOUS.
AC_REQUIRE([AC_GNU_SOURCE])
# Check for mmap()
AC_FUNC_MMAP
# Try to allow MAP_ANONYMOUS.
gl_have_mmap_anonymous=no
if test $ac_cv_func_mmap_fixed_mapped = yes; then
AC_MSG_CHECKING([for MAP_ANONYMOUS])
AC_EGREP_CPP([I cant identify this map.], [
#include <sys/mman.h>
#ifdef MAP_ANONYMOUS
I cant identify this map.
#endif
],
[gl_have_mmap_anonymous=yes])
if test $gl_have_mmap_anonymous = no; then
AC_EGREP_HEADER([MAP_ANON], [
#include <sys/mman.h>
#ifdef MAP_ANON
I cant identify this map.
#endif
],
[AC_DEFINE(MAP_ANONYMOUS, MAP_ANON,
[Define to a substitute value for mmap()'s MAP_ANONYMOUS flag.])
gl_have_mmap_anonymous=yes])
fi
AC_MSG_RESULT($gl_have_mmap_anonymous)
if test $gl_have_mmap_anonymous = yes; then
AC_DEFINE(HAVE_MAP_ANONYMOUS, 1,
[Define to 1 if mmap()'s MAP_ANONYMOUS flag is available after including
config.h and <sys/mman.h>.])
fi
AH_VERBATIM([MAP_FILE],
[/* Define MAP_FILE when it isn't otherwise. */
#ifndef MAP_FILE
# define MAP_FILE 0
#endif])
fi
])
============================ m4/pagealign_alloc.m4 =========================
# pagealign_alloc.m4 serial 1
dnl Copyright (C) 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_PAGEALIGN_ALLOC],
[
dnl Persuade glibc <sys/mman.h> to define MAP_ANONYMOUS.
AC_REQUIRE([AC_GNU_SOURCE])
AC_LIBSOURCE([pagealign_alloc.h])
AC_LIBOBJ([pagealign_alloc])
gl_PREREQ_PAGEALIGN_ALLOC
])
# Prerequisites of lib/pagealign_alloc.c.
AC_DEFUN([gl_PREREQ_PAGEALIGN_ALLOC],
[
AC_REQUIRE([gl_FUNC_MMAP])
AC_REQUIRE([gl_GETPAGESIZE])
AC_CHECK_FUNCS_ONCE([posix_memalign])
AC_CHECK_HEADERS_ONCE([fcntl.h unistd.h])
])
============================================================================
- Re: [bug-gnulib] valloc()?, Bruno Haible, 2005/03/03
- Re: [bug-gnulib] valloc()?, Derek Price, 2005/03/02
- Message not available
- Re: [bug-gnulib] valloc()?, Bruno Haible, 2005/03/03
- Re: [bug-gnulib] valloc()?, Derek Price, 2005/03/03
- Re: [bug-gnulib] valloc()?, Bruno Haible, 2005/03/03
- Re: [bug-gnulib] valloc()?, Derek Price, 2005/03/03
- Message not available
- Re: [bug-gnulib] valloc()?, Bruno Haible, 2005/03/03