summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/has/aligned-alloc.c8
-rw-r--r--build/header.mk1
-rw-r--r--src/alloc.c15
-rw-r--r--src/alloc.h34
-rw-r--r--tests/alloc.c8
5 files changed, 27 insertions, 39 deletions
diff --git a/build/has/aligned-alloc.c b/build/has/aligned-alloc.c
deleted file mode 100644
index 4460038..0000000
--- a/build/has/aligned-alloc.c
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright © Tavian Barnes <tavianator@tavianator.com>
-// SPDX-License-Identifier: 0BSD
-
-#include <stdlib.h>
-
-int main(void) {
- return !aligned_alloc(_Alignof(void *), sizeof(void *));
-}
diff --git a/build/header.mk b/build/header.mk
index 88a8986..e9f1abc 100644
--- a/build/header.mk
+++ b/build/header.mk
@@ -18,7 +18,6 @@ HEADERS := \
gen/has/acl-get-tag-type.h \
gen/has/acl-is-trivial-np.h \
gen/has/acl-trivial.h \
- gen/has/aligned-alloc.h \
gen/has/builtin-riscv-pause.h \
gen/has/confstr.h \
gen/has/extattr-get-file.h \
diff --git a/src/alloc.c b/src/alloc.c
index 779e1d7..4e68e13 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -20,24 +20,22 @@
# define ALLOC_MAX (SIZE_MAX / 2)
#endif
-/** Portable aligned_alloc()/posix_memalign(). */
+/** posix_memalign() wrapper. */
static void *xmemalign(size_t align, size_t size) {
bfs_assert(has_single_bit(align));
bfs_assert(align >= sizeof(void *));
- bfs_assert(is_aligned(align, size));
-#if BFS_HAS_ALIGNED_ALLOC
- return aligned_alloc(align, size);
-#else
+ // Since https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2072.htm,
+ // aligned_alloc() doesn't require the size to be a multiple of align.
+ // But the sanitizers don't know about that yet, so always use
+ // posix_memalign().
void *ptr = NULL;
errno = posix_memalign(&ptr, align, size);
return ptr;
-#endif
}
void *alloc(size_t align, size_t size) {
bfs_assert(has_single_bit(align));
- bfs_assert(is_aligned(align, size));
if (size > ALLOC_MAX) {
errno = EOVERFLOW;
@@ -53,7 +51,6 @@ void *alloc(size_t align, size_t size) {
void *zalloc(size_t align, size_t size) {
bfs_assert(has_single_bit(align));
- bfs_assert(is_aligned(align, size));
if (size > ALLOC_MAX) {
errno = EOVERFLOW;
@@ -73,8 +70,6 @@ void *zalloc(size_t align, size_t size) {
void *xrealloc(void *ptr, size_t align, size_t old_size, size_t new_size) {
bfs_assert(has_single_bit(align));
- bfs_assert(is_aligned(align, old_size));
- bfs_assert(is_aligned(align, new_size));
if (new_size == 0) {
free(ptr);
diff --git a/src/alloc.h b/src/alloc.h
index 4f119e0..7865d5d 100644
--- a/src/alloc.h
+++ b/src/alloc.h
@@ -30,25 +30,24 @@ static inline size_t align_ceil(size_t align, size_t size) {
}
/**
- * Saturating array size.
- *
- * @align
- * Array element alignment.
- * @size
- * Array element size.
- * @count
- * Array element count.
- * @return
- * size * count, saturating to the maximum aligned value on overflow.
+ * Saturating size addition.
*/
-static inline size_t array_size(size_t align, size_t size, size_t count) {
+static inline size_t size_add(size_t lhs, size_t rhs) {
+ size_t ret = lhs + rhs;
+ return ret >= lhs ? ret : (size_t)-1;
+}
+
+/**
+ * Saturating size multiplication.
+ */
+static inline size_t size_mul(size_t size, size_t count) {
size_t ret = size * count;
- return ret / size == count ? ret : ~(align - 1);
+ return ret / size == count ? ret : (size_t)-1;
}
/** Saturating array sizeof. */
#define sizeof_array(type, count) \
- array_size(alignof(type), sizeof(type), count)
+ size_mul(sizeof(type), count)
/** Size of a struct/union field. */
#define sizeof_member(type, member) \
@@ -72,13 +71,8 @@ static inline size_t array_size(size_t align, size_t size, size_t count) {
* to the maximum aligned value on overflow.
*/
static inline size_t flex_size(size_t align, size_t min, size_t offset, size_t size, size_t count) {
- size_t ret = size * count;
- size_t overflow = ret / size != count;
-
- size_t extra = offset + align - 1;
- ret += extra;
- overflow |= ret < extra;
- ret |= -overflow;
+ size_t ret = size_mul(size, count);
+ ret = size_add(ret, offset + align - 1);
ret = align_floor(align, ret);
// Make sure flex_sizeof(type, member, 0) >= sizeof(type), even if the
diff --git a/tests/alloc.c b/tests/alloc.c
index f91b428..046613a 100644
--- a/tests/alloc.c
+++ b/tests/alloc.c
@@ -11,6 +11,14 @@
#include <stdint.h>
void check_alloc(void) {
+ // Check aligned allocation
+ void *ptr;
+ bfs_everify((ptr = zalloc(64, 129)));
+ bfs_check((uintptr_t)ptr % 64 == 0);
+ bfs_echeck((ptr = xrealloc(ptr, 64, 129, 65)));
+ bfs_check((uintptr_t)ptr % 64 == 0);
+ free(ptr);
+
// Check sizeof_flex()
struct flexible {
alignas(64) int foo[8];