2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
5 POSIX function posix_memalign().
8 #include "__arosc_privdata.h"
9 #include "__memalign.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 /*****************************************************************************
32 Allocate aligned memory.
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.
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.
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
54 If an error occurs, errno will not be set.
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
))
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
);
80 /* store the size for free(). it will add AROS_ALIGN(sizeof(size_t))
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) {
93 /* Make room for a pointer to original malloc()-style allocation, and
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
);
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
;
112 } /* posix_memalign */