purge remaining gpl code from clib, and make clib build again
[tangerine.git] / compiler / clib / posix_memalign.c
blob9b996627e3ce87c1137229c141ec6d430ac1f9b3
1 /*
2 Copyright © 1995-2007, 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 <sys/types.h>
23 #include <stdlib.h>
25 int posix_memalign (
27 /* SYNOPSIS */
28 void **memptr,
29 size_t alignment,
30 size_t size)
32 /* FUNCTION
33 Allocate aligned memory.
35 INPUTS
36 memptr - Pointer to a place to store the pointer to allocated memory.
37 alignment - Alignment of allocated memory. The address of the
38 allocated memory will be a multiple of this value, which
39 must be a power of two and a multiple of sizeof(void *).
40 size - How much memory to allocate.
42 RESULT
43 Returns zero on success.
44 Returns EINVAL if the alignment parameter was not a power of two, or
45 was not a multiple of sizeof(void *).
46 Returns ENOMEM if there was insufficient memory to fulfill the request.
48 NOTES
49 Memory allocated by posix_memalign() should be freed with free(). If
50 not, it will be freed when the program terminates.
52 This function must not be used in a shared library or in a threaded
53 application.
55 If an error occurs, errno will not be set.
57 EXAMPLE
59 BUGS
61 SEE ALSO
62 free()
64 INTERNALS
66 ******************************************************************************/
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(__startup_mempool, size + alignment + AROS_ALIGN(sizeof(size_t)) + AROS_ALIGN(sizeof(void *)));
76 if (mem == NULL)
77 return ENOMEM;
79 /* store the size for free(). it will add sizeof(size_t) itself */
80 *((size_t *) mem) = size + alignment + AROS_ALIGN(sizeof(void *));
81 mem += AROS_ALIGN(sizeof(size_t));
83 /* if its already aligned correctly, then we just use it as-is */
84 if (((IPTR) mem & (alignment-1)) == 0) {
85 *memptr = mem;
86 return 0;
89 orig = mem;
91 /* move forward to an even alignment boundary */
92 mem = (UBYTE *) (((IPTR) mem + alignment - 1) & -alignment);
94 /* store a magic number in the place that free() will look for the
95 * allocation size, so it can handle this specially */
96 ((size_t *) mem)[-1] = MEMALIGN_MAGIC;
98 /* then store the original pointer before it, for free() to find */
99 ((void **) &(((size_t *) mem)[-1]))[-1] = orig;
101 *memptr = mem;
102 return 0;
103 } /* posix_memalign */