|
@@ -0,0 +1,94 @@
|
|
|
+
|
|
|
+ * libc/stdlib/malloc/memalign.c -- memalign (`aligned malloc') function
|
|
|
+ *
|
|
|
+ * Copyright (C) 2002 NEC Corporation
|
|
|
+ * Copyright (C) 2002 Miles Bader <miles@gnu.org>
|
|
|
+ *
|
|
|
+ * This file is subject to the terms and conditions of the GNU Lesser
|
|
|
+ * General Public License. See the file COPYING.LIB in the main
|
|
|
+ * directory of this archive for more details.
|
|
|
+ *
|
|
|
+ * Written by Miles Bader <miles@gnu.org>
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <sys/mman.h>
|
|
|
+
|
|
|
+#include "malloc.h"
|
|
|
+#include "heap.h"
|
|
|
+
|
|
|
+
|
|
|
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
|
|
+
|
|
|
+
|
|
|
+ ______________________ TOTAL _________________________
|
|
|
+ / \
|
|
|
+ +---------------+-------------------------+--------------+
|
|
|
+ | | | |
|
|
|
+ +---------------+-------------------------+--------------+
|
|
|
+ \____ INIT ____/ \______ RETURNED _______/ \____ END ___/
|
|
|
+*/
|
|
|
+
|
|
|
+void *
|
|
|
+memalign (size_t alignment, size_t size)
|
|
|
+{
|
|
|
+ void *mem, *base;
|
|
|
+ unsigned long tot_addr, tot_end_addr, addr, end_addr;
|
|
|
+ struct heap *heap = &__malloc_heap;
|
|
|
+
|
|
|
+
|
|
|
+ size = HEAP_ADJUST_SIZE (size);
|
|
|
+
|
|
|
+
|
|
|
+ system memory. We over-allocate enough to be sure that we'll get
|
|
|
+ enough memory to hold a properly aligned block of size SIZE,
|
|
|
+ _somewhere_ in the result. */
|
|
|
+ mem = malloc (size + 2 * alignment);
|
|
|
+ if (! mem)
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ if (alignment < MALLOC_ALIGNMENT)
|
|
|
+ return mem;
|
|
|
+
|
|
|
+
|
|
|
+ use the user-address for calculations, since that's where the
|
|
|
+ alignment matters. */
|
|
|
+ base = MALLOC_BASE (mem);
|
|
|
+
|
|
|
+
|
|
|
+ tot_addr = (unsigned long)mem;
|
|
|
+ tot_end_addr = (unsigned long)base + MALLOC_SIZE (mem);
|
|
|
+
|
|
|
+
|
|
|
+ addr = MALLOC_ROUND_UP (tot_addr, alignment);
|
|
|
+
|
|
|
+
|
|
|
+ initial part of MEM to the heap. */
|
|
|
+ if (addr != tot_addr)
|
|
|
+ {
|
|
|
+ size_t init_size = addr - tot_addr;
|
|
|
+
|
|
|
+
|
|
|
+ if (init_size < HEAP_MIN_SIZE)
|
|
|
+ {
|
|
|
+ addr = MALLOC_ROUND_UP (tot_addr + HEAP_MIN_SIZE, alignment);
|
|
|
+ init_size = addr - tot_addr;
|
|
|
+ }
|
|
|
+
|
|
|
+ __heap_free (heap, base, init_size);
|
|
|
+
|
|
|
+
|
|
|
+ base += init_size;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ end_addr = addr + size;
|
|
|
+ if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr)
|
|
|
+ __heap_free (heap, (void *)end_addr, tot_end_addr - end_addr);
|
|
|
+ else
|
|
|
+
|
|
|
+ end_addr = tot_end_addr;
|
|
|
+
|
|
|
+ return MALLOC_SETUP (base, end_addr - (unsigned long)base);
|
|
|
+}
|