summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2018-11-05 08:23:41 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2018-11-05 08:23:41 +0000
commitcecf1f096e82006d6c9e3371fdea05125f38e03e (patch)
treeabc4ae1480031cdbb165dec6efe69ca14084cd4e /lib/libc/stdlib
parent57933f13bb51bbf48a0c323eca44b7457aa56b98 (diff)
Implement C11's aligned_alloc(3). ok guenther@
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/malloc.345
-rw-r--r--lib/libc/stdlib/malloc.c44
2 files changed, 84 insertions, 5 deletions
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3
index 1f5d9c71044..71c329f9ece 100644
--- a/lib/libc/stdlib/malloc.3
+++ b/lib/libc/stdlib/malloc.3
@@ -30,9 +30,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $OpenBSD: malloc.3,v 1.115 2017/05/15 18:05:34 tb Exp $
+.\" $OpenBSD: malloc.3,v 1.116 2018/11/05 08:23:40 otto Exp $
.\"
-.Dd $Mdocdate: May 15 2017 $
+.Dd $Mdocdate: November 5 2018 $
.Dt MALLOC 3
.Os
.Sh NAME
@@ -42,7 +42,8 @@
.Nm free ,
.Nm reallocarray ,
.Nm recallocarray ,
-.Nm freezero
+.Nm freezero ,
+.Nm aligned_alloc
.Nd memory allocation and deallocation
.Sh SYNOPSIS
.In stdlib.h
@@ -60,6 +61,8 @@
.Fn recallocarray "void *ptr" "size_t oldnmemb" "size_t nmemb" "size_t size"
.Ft void
.Fn freezero "void *ptr" "size_t size"
+.Ft void *
+.Fn aligned_alloc "size_t alignment" "size_t size"
.Vt char *malloc_options ;
.Sh DESCRIPTION
The standard functions
@@ -206,7 +209,7 @@ is not
.Dv NULL ,
the
.Fa size
-argument must be equal or smaller than the size of the earlier allocation
+argument must be equal to or smaller than the size of the earlier allocation
that returned
.Fa ptr .
.Fn freezero
@@ -215,6 +218,21 @@ guarantees the memory range starting at
with length
.Fa size
is discarded while deallocating the whole object originally allocated.
+.Pp
+The
+.Fn aligned_alloc
+function allocates
+.Fa size
+bytes of memory such that the allocation's base address is a multiple of
+.Fa alignment .
+The requested
+.Fa alignment
+must be a power of 2.
+If
+.Fa size
+is not a multiple of
+.Fa alignment ,
+behavior is undefined.
.Sh RETURN VALUES
Upon successful completion, the allocation functions
return a pointer to the allocated space; otherwise,
@@ -223,6 +241,17 @@ is returned and
.Va errno
is set to
.Er ENOMEM .
+The function
+.Fn aligned_alloc
+returns
+.Dv NULL
+and sets
+.Va errno
+to
+.Er EINVAL
+if
+.Fa alignment
+is not a power of 2.
.Pp
If
.Fa nmemb
@@ -514,6 +543,10 @@ and
.Fn free
functions conform to
.St -ansiC .
+The
+.Fn aligned_alloc
+function conforms to
+.St -isoC-2011 .
.Pp
If
.Fa nmemb
@@ -588,6 +621,10 @@ The
.Fn freezero
function appeared in
.Ox 6.2 .
+The
+.Fn aligned_alloc
+function appeared in
+.Ox 6.5 .
.Sh CAVEATS
When using
.Fn malloc ,
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 81c30812a46..70e7f37dc82 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malloc.c,v 1.249 2018/04/07 09:57:08 otto Exp $ */
+/* $OpenBSD: malloc.c,v 1.250 2018/11/05 08:23:40 otto Exp $ */
/*
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@@ -2058,6 +2058,48 @@ err:
}
/*DEF_STRONG(posix_memalign);*/
+void *
+aligned_alloc(size_t alignment, size_t size)
+{
+ struct dir_info *d;
+ int saved_errno = errno;
+ void *r;
+
+ /* Make sure that alignment is a positive power of 2. */
+ if (((alignment - 1) & alignment) != 0 || alignment == 0) {
+ errno = EINVAL;
+ return NULL;
+ };
+ /* Per spec, size should be a multiple of alignment */
+ if ((size & (alignment - 1)) != 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ d = getpool();
+ if (d == NULL) {
+ _malloc_init(0);
+ d = getpool();
+ }
+ _MALLOC_LOCK(d->mutex);
+ d->func = "aligned_alloc";
+ if (d->active++) {
+ malloc_recurse(d);
+ return NULL;
+ }
+ r = omemalign(d, alignment, size, 0, CALLER);
+ d->active--;
+ _MALLOC_UNLOCK(d->mutex);
+ if (r == NULL) {
+ if (mopts.malloc_xmalloc)
+ wrterror(d, "out of memory");
+ return NULL;
+ }
+ errno = saved_errno;
+ return r;
+}
+/*DEF_STRONG(aligned_alloc);*/
+
#ifdef MALLOC_STATS
struct malloc_leak {