From e4341e950b0134537177d77f569d1b6366c64698 Mon Sep 17 00:00:00 2001 From: otto <> Date: Mon, 5 Nov 2018 08:23:40 +0000 Subject: [PATCH] Implement C11's aligned_alloc(3). ok guenther@ --- src/include/stdlib.h | 7 +++++- src/lib/libc/stdlib/malloc.3 | 45 ++++++++++++++++++++++++++++++++---- src/lib/libc/stdlib/malloc.c | 44 ++++++++++++++++++++++++++++++++++- 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/include/stdlib.h b/src/include/stdlib.h index cc359ab3..d546444c 100644 --- a/src/include/stdlib.h +++ b/src/include/stdlib.h @@ -1,4 +1,4 @@ -/* $OpenBSD: stdlib.h,v 1.72 2017/09/05 03:16:13 schwarze Exp $ */ +/* $OpenBSD: stdlib.h,v 1.73 2018/11/05 08:23:40 otto Exp $ */ /* $NetBSD: stdlib.h,v 1.25 1995/12/27 21:19:08 jtc Exp $ */ /*- @@ -221,6 +221,11 @@ unsigned long long strtoull(const char *__restrict, char **__restrict, int); #endif +#if __ISO_C_VISIBLE >= 2011 +void * + aligned_alloc(size_t, size_t); +#endif + /* * The Open Group Base Specifications, Issue 6; IEEE Std 1003.1-2001 (POSIX) */ diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3 index 1f5d9c71..71c329f9 100644 --- a/src/lib/libc/stdlib/malloc.3 +++ b/src/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/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 81c30812..70e7f37d 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/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 * Copyright (c) 2012 Matthew Dempsky @@ -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 {