update mappings to reflect recent changes
[AROS.git] / compiler / clib / posix_memalign.c
blob6a564b05a56aa0abb343a519e78c1bf6b9569e50
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 POSIX function posix_memalign().
6 */
8 #include "__arosc_privdata.h"
9 #include "__memalign.h"
11 #include <errno.h>
12 #include <dos/dos.h>
13 #include <exec/memory.h>
14 #include <proto/exec.h>
15 #include <aros/symbolsets.h>
16 #include <aros/debug.h>
17 #include <sys/param.h>
19 /*****************************************************************************
21 NAME */
22 #include <stdlib.h>
24 int posix_memalign (
26 /* SYNOPSIS */
27 void **memptr,
28 size_t alignment,
29 size_t size)
31 /* FUNCTION
32 Allocate aligned memory.
34 INPUTS
35 memptr - Pointer to a place to store the pointer to allocated memory.
36 alignment - Alignment of allocated memory. The address of the
37 allocated memory will be a multiple of this value, which
38 must be a power of two and a multiple of sizeof(void *).
39 size - How much memory to allocate.
41 RESULT
42 Returns zero on success.
43 Returns EINVAL if the alignment parameter was not a power of two, or
44 was not a multiple of sizeof(void *).
45 Returns ENOMEM if there was insufficient memory to fulfill the request.
47 NOTES
48 Memory allocated by posix_memalign() should be freed with free(). If
49 not, it will be freed when the program terminates.
51 This function must not be used in a shared library or in a threaded
52 application.
54 If an error occurs, errno will not be set.
56 EXAMPLE
58 BUGS
60 SEE ALSO
61 free()
63 INTERNALS
65 ******************************************************************************/
67 struct aroscbase *aroscbase = __aros_getbase_aroscbase();
68 UBYTE *mem = NULL, *orig;
70 /* check the alignment is valid */
71 if (alignment % sizeof(void *) != 0 || !powerof2(alignment))
72 return EINVAL;
74 /* allocate enough space to satisfy the alignment and save some info */
75 mem = AllocPooled(aroscbase->acb_mempool, AROS_ALIGN(sizeof(size_t)) + sizeof(void *)
76 + AROS_ALIGN(sizeof(size_t)) + alignment + size);
77 if (mem == NULL)
78 return ENOMEM;
80 /* store the size for free(). it will add AROS_ALIGN(sizeof(size_t))
81 * itself */
82 *((size_t *) mem) = size + alignment + AROS_ALIGN(sizeof(void *));
83 mem += AROS_ALIGN(sizeof(size_t));
85 /* if it's already aligned correctly, then we just use it as-is */
86 if (((IPTR) mem & (alignment-1)) == 0) {
87 *memptr = mem;
88 return 0;
91 orig = mem;
93 /* Make room for a pointer to original malloc()-style allocation, and
94 * a magic value */
95 mem += sizeof(void *) + AROS_ALIGN(sizeof(size_t));
97 /* move forward to an even alignment boundary (if we get here, requested
98 * alignment is greater than AROS_WORSTALIGN) */
99 mem = (UBYTE *) (((IPTR) mem + alignment - 1) & -alignment);
100 *memptr = mem;
102 /* store a magic number in the place that free() will look for the
103 * allocation size, so it can handle this specially */
104 mem -= AROS_ALIGN(sizeof(size_t *));
105 *((size_t *) mem) = MEMALIGN_MAGIC;
107 /* then store the original pointer before it, for free() to find */
108 mem -= sizeof(void *);
109 *((void **) mem) = orig;
111 return 0;
112 } /* posix_memalign */