Hi Paul, > C11 and C++17 have aligned_alloc, which Emacs uses in preference to > posix_memalign.
Just noticed it as well, when looking at the glibc documentation [1]. Patch below. > I suggest preferring aligned_alloc to > posix_memalign since aligned_alloc should be available on more systems as the > new standards take hold. I prefer posix_memalign to aligned_alloc, because aligned_alloc requires additionally that the SIZE is a multiple of the ALIGNMENT. Currently all platforms that have aligned_alloc also have posix_memalign. But I agree with you that there is hope that some systems (maybe native Windows?) may get aligned_alloc sooner than posix_memalign. > Also, how about naming the new module 'aligned-alloc' and having it implement > aligned_alloc? That would make for more-seamless integration. This is not possible without overriding malloc and free - which surely would cause a lot of trouble. [1] https://www.gnu.org/software/libc/manual/html_node/Aligned-Memory-Blocks.html 2020-07-21 Bruno Haible <br...@clisp.org> aligned-malloc: Optionally use aligned_alloc. * lib/aligned-malloc.h: Verify the alignment. (aligned_malloc): Use aligned_alloc as an alternative. * modules/aligned-malloc (configure.ac): Test for aligned_alloc. * doc/posix-functions/aligned_alloc.texi: Mention the modules 'aligned-malloc' and 'pagealign_alloc'. diff --git a/doc/posix-functions/aligned_alloc.texi b/doc/posix-functions/aligned_alloc.texi index c938f30..a4897b9 100644 --- a/doc/posix-functions/aligned_alloc.texi +++ b/doc/posix-functions/aligned_alloc.texi @@ -16,3 +16,9 @@ Portability problems not fixed by Gnulib: This function is missing on all non-glibc platforms: glibc 2.15, Mac OS X 10.5, FreeBSD 6.4, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin, mingw, MSVC 14, Android 8.1. @end itemize + +The Gnulib module @code{aligned-malloc} provides functions for +allocating and freeing blocks of suitably aligned memory. + +The Gnulib module @code{pagealign_alloc} provides a similar API for +allocating and freeing blocks of memory aligned on a system page boundary. diff --git a/lib/aligned-malloc.h b/lib/aligned-malloc.h index 86382fd..9baaab4 100644 --- a/lib/aligned-malloc.h +++ b/lib/aligned-malloc.h @@ -29,17 +29,29 @@ The block can be freed through aligned_free(), NOT through free(). Upon failure, it returns NULL. */ -/* This module exists instead of a posix_memalign() or memalign() emulation, - because we can't reasonably emulate posix_memalign() or memalign(): +/* This module exists instead of a posix_memalign(), aligned_alloc(), or + memalign() emulation, because we can't reasonably emulate posix_memalign(), + aligned_alloc(), or memalign(): If malloc() returned p, only free (p) is allowed, not free (p + 1), free (p + 2), free (p + 4), free (p + 8), or similar. - We can use posix_memalign(). On older systems, we can alternatively use - memalign() instead. In the Solaris documentation of memalign() it is not - specified how a memory block returned by memalign() can be freed, but - it actually can be freed with free(). */ + We can use posix_memalign(), a POSIX function. -#if ((ALIGNMENT) <= MALLOC_ALIGNMENT) || HAVE_POSIX_MEMALIGN || HAVE_MEMALIGN + We can also use aligned_alloc(), an ISO C11 and POSIX function. But it's + a bit more awkward to use. + + On older systems, we can alternatively use memalign() instead. In the + Solaris documentation of memalign() it is not specified how a memory block + returned by memalign() can be freed, but it actually can be freed with + free(). */ + +#if !defined ALIGNMENT +# error "ALIGNMENT is not defined" +#endif +#if !((ALIGNMENT) > 0 && ((ALIGNMENT) & ((ALIGNMENT) - 1)) == 0) +# error "ALIGNMENT is not a power of 2" +#endif +#if ((ALIGNMENT) <= MALLOC_ALIGNMENT) || HAVE_POSIX_MEMALIGN || HAVE_ALIGNED_ALLOC || HAVE_MEMALIGN # if (ALIGNMENT) <= MALLOC_ALIGNMENT /* Simply use malloc. */ @@ -70,6 +82,23 @@ aligned_malloc (size_t size) return NULL; } +# elif HAVE_ALIGNED_ALLOC +/* Use aligned_alloc. */ + +static inline void * +aligned_malloc (size_t size) +{ + /* Round up SIZE to the next multiple of ALIGNMENT, + namely (SIZE + ALIGNMENT - 1) & ~(ALIGNMENT - 1). */ + size += (ALIGNMENT) - 1; + if (size >= (ALIGNMENT) - 1) /* no overflow? */ + { + size &= ~(size_t)((ALIGNMENT) - 1); + return aligned_alloc ((ALIGNMENT), size); + } + return NULL; +} + # elif HAVE_MEMALIGN /* HP-UX, IRIX, Solaris <= 10 */ /* Use memalign. */ diff --git a/modules/aligned-malloc b/modules/aligned-malloc index 29483d8..d562e3d 100644 --- a/modules/aligned-malloc +++ b/modules/aligned-malloc @@ -11,7 +11,7 @@ stdint configure.ac: gl_MALLOC_ALIGNMENT AC_REQUIRE([AC_C_INLINE]) -AC_CHECK_FUNCS([posix_memalign memalign]) +AC_CHECK_FUNCS([posix_memalign aligned_alloc memalign]) Makefile.am: