summaryrefslogtreecommitdiff
path: root/lib/aligned-malloc.h
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2020-07-21 18:09:35 +0200
committerBruno Haible <bruno@clisp.org>2020-07-21 18:20:01 +0200
commitac34618e85013bfec4650f02e8e79c5de6d80fb3 (patch)
tree2c0b5c6b04ab1f28aef3c978ab71ed147a69d473 /lib/aligned-malloc.h
parentfd8403522f26c5dca64fcc29bcf4c6b4c5b08335 (diff)
downloadgnulib-ac34618e85013bfec4650f02e8e79c5de6d80fb3.tar.gz
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'.
Diffstat (limited to 'lib/aligned-malloc.h')
-rw-r--r--lib/aligned-malloc.h43
1 files changed, 36 insertions, 7 deletions
diff --git a/lib/aligned-malloc.h b/lib/aligned-malloc.h
index 86382fd25b..9baaab4cfe 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. */