revert between 56095 -> 55830 in arch
[AROS.git] / compiler / stdc / malloc_align.c
blob6a8d3be86cd57d529f5b558d25c076364ac5037f
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 AROS extension function malloc_align().
6 */
8 #include <exec/types.h>
10 #include "__memalign.h"
12 #include <errno.h>
14 #define powerof2(x) ((((x)-1)&(x))==0)
16 /*****************************************************************************
18 NAME */
19 #include <stdlib.h>
21 void *malloc_align (
23 /* SYNOPSIS */
24 size_t size,
25 size_t alignment)
27 /* FUNCTION
28 Allocate aligned memory.
30 INPUTS
31 size - How much memory to allocate.
32 alignment - Alignment of allocated memory. The address of the
33 allocated memory will be a multiple of this value, which
34 must be a power of two and a multiple of sizeof(void *).
36 RESULT
37 A pointer to the allocated memory or NULL.
39 NOTES
40 errno is set to EINVAL if the alignment parameter was not a power of
41 two, or was not a multiple of sizeof(void *).
42 errno is set to ENOMEM if there was insufficient memory to fulfill
43 the request.
44 Memory allocated by malloc_align() should be freed with free(). If
45 not, it will be freed when the program terminates.
47 This function is AROS specific.
49 EXAMPLE
51 BUGS
53 SEE ALSO
54 calloc(), free(), malloc()
56 INTERNALS
58 ******************************************************************************/
60 char *mem = NULL, *orig, *tmp;
62 /* check the alignment is valid */
63 if (alignment % sizeof(void *) != 0 || !powerof2(alignment))
65 errno = EINVAL;
66 return NULL;
69 /* allocate enough space to satisfy the alignment and save some info */
70 mem = malloc(size + alignment + AROS_ALIGN(sizeof(size_t)) + AROS_ALIGN(sizeof(void *)));
71 if (mem == NULL)
73 errno = ENOMEM;
74 return NULL;
77 /* if it's already aligned correctly, then we just use it as-is */
78 if (((IPTR) mem & (alignment-1)) == 0)
79 return mem;
81 orig = mem;
83 /* move forward to an even alignment boundary */
84 mem = (char *) (((IPTR) mem + alignment - 1) & -alignment);
85 tmp = mem;
87 /* store a magic number in the place that free() will look for the
88 * allocation size, so it can handle this specially */
89 tmp -= AROS_ALIGN(sizeof(size_t *));
90 *((size_t *) tmp) = MEMALIGN_MAGIC;
92 /* then store the original pointer before it, for free() to find */
93 tmp -= sizeof(void *);
94 *((void **) tmp) = orig;
96 return mem;
97 } /* posix_memalign */