]> git.sur5r.net Git - cc65/commitdiff
Replaced _aligned_malloc by the POSIX compatible function posix_memalign
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Jul 2005 12:57:00 +0000 (12:57 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Jul 2005 12:57:00 +0000 (12:57 +0000)
(Greg King).

git-svn-id: svn://svn.cc65.org/cc65/trunk@3537 b7a2c559-68d2-44c3-8de9-860c34a00d81

include/stdlib.h
libsrc/common/Makefile
libsrc/common/_aligned_malloc.c [deleted file]
libsrc/common/pmemalign.c [new file with mode: 0644]

index 259b602333d3223cfbf5fb4035be511d524b737b..6bacd952b8ecd598520e569a0a8d5742e7fe05d7 100644 (file)
@@ -62,13 +62,14 @@ void __fastcall__ free (void* block);
 
 /* Non standard memory management functions */
 
-void* __fastcall__ _aligned_malloc (size_t size, size_t alignment);
-/* Allocate a block of memory with the given size, which is aligned to a
- * memory address that is a multiple of alignment. alignment MUST NOT be
- * zero and MUST be a power of two, otherwise a call to this function will
- * cause undefined behaviour. The function returns NULL if not enough memory
- * is available to satisfy the request. To free the allocated block, use the
- * free() function.
+int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size);
+/* Allocate a block of memory with the given "size", which is aligned to a
+ * memory address that is a multiple of "alignment".  "alignment" MUST NOT be
+ * zero, and MUST be a power of two; otherwise, this function will return
+ * EINVAL.  The function returns ENOMEM if not enough memory is available
+ * to satisfy the request.  "memptr" must point to a variable; that variable
+ * will return the address of the allocated memory.  Use free() to release that
+ * allocated block.
  */
 
 void __fastcall__ _heapadd (void* mem, size_t size);
index 151a0e339a9a10d318d3d9d10af824134aa39d7f..464124192f93cc5581bb6f55d394ae683720208a 100644 (file)
@@ -41,7 +41,6 @@ CFLAGS        = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
 
 # From C source-files
 C_OBJS =       _afailed.o              \
-                _aligned_malloc.o       \
                _hextab.o               \
                 _poserror.o             \
                _scanf.o                \
@@ -66,6 +65,7 @@ C_OBJS =      _afailed.o              \
                 localtime.o             \
                 mktime.o                \
                perror.o                \
+                pmemalign.o             \
                puts.o                  \
                qsort.o                 \
                realloc.o               \
diff --git a/libsrc/common/_aligned_malloc.c b/libsrc/common/_aligned_malloc.c
deleted file mode 100644 (file)
index a74608b..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*****************************************************************************/
-/*                                                                           */
-/*                              _aligned_malloc                              */
-/*                                                                           */
-/*                     Allocate an aligned memory block                      */
-/*                                                                           */
-/*                                                                           */
-/*                                                                           */
-/* (C) 2004-2005 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
-/*                                                                           */
-/*                                                                           */
-/* This software is provided 'as-is', without any expressed or implied       */
-/* warranty.  In no event will the authors be held liable for any damages    */
-/* arising from the use of this software.                                    */
-/*                                                                           */
-/* Permission is granted to anyone to use this software for any purpose,     */
-/* including commercial applications, and to alter it and redistribute it    */
-/* freely, subject to the following restrictions:                            */
-/*                                                                           */
-/* 1. The origin of this software must not be misrepresented; you must not   */
-/*    claim that you wrote the original software. If you use this software   */
-/*    in a product, an acknowledgment in the product documentation would be  */
-/*    appreciated but is not required.                                       */
-/* 2. Altered source versions must be plainly marked as such, and must not   */
-/*    be misrepresented as being the original software.                      */
-/* 3. This notice may not be removed or altered from any source              */
-/*    distribution.                                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-
-
-#include <stdlib.h>
-#include <_heap.h>
-
-
-
-/* This is a very simple version of an aligned memory allocator. We will
- * allocate a greater block, so we can place the aligned block within it
- * that is returned. We use our knowledge about the internal heap
- * structures to free the unused parts of the bigger block (the two chunks
- * below and above the aligned block).
- */
-
-
-
-void* __fastcall__ _aligned_malloc (size_t size, size_t alignment)
-/* Allocate a block of memory with the given size, which is aligned to a
- * memory address that is a multiple of alignment. alignment MUST NOT be
- * zero and MUST be a power of two, otherwise a call to this function will 
- * cause undefined behaviour. The function returns NULL if not enough memory 
- * is available to satisfy the request. To free the allocated block, use the
- * free() function.
- */
-{
-    size_t rawsize;
-    size_t uppersize;
-    size_t lowersize;
-    register struct usedblock* b;
-    register struct usedblock* u;
-    register struct usedblock* p;
-
-    /* Handle requests for zero sized blocks */
-    if (size == 0) {
-        return 0;
-    }
-
-    /* We don't really need alignment, but alignment-1 */
-    --alignment;
-
-    /* Round up the block size and allocate memory. We don't need to account
-     * for the additional admin data needed to manage the used block, since
-     * the block returned by malloc has this overhead added one time, and
-     * the worst thing that may happen is that we cannot free the upper and
-     * lower blocks.
-     */
-    b = malloc (size + alignment);
-
-    /* Handle out of memory */
-    if (b == 0) {
-        return 0;
-    }
-
-    /* Create a new pointer that points to the user visible aligned block. */
-    u = (struct usedblock*) (((unsigned)b + alignment) & ~alignment);
-
-    /* Get the raw block pointer, which is located just below the user visible
-     * block. The first word of this raw block is the total size of the block
-     * including the admin space.
-     */
-    b = (b-1)->start;
-    rawsize = b->size;
-
-    /* Get a pointer to the (raw) upper block */
-    p = (struct usedblock*) (size + (unsigned)u);
-
-    /* Check if we can free the space above the allocated block. This is the
-     * case if the size of the block is at least sizeof (struct freeblock)
-     * bytes and the size of the remaining block is at least of this size,
-     * too. If the upper block is smaller, we will just pass it to the caller
-     * together with the requested aligned block.
-     */
-    uppersize = rawsize + (unsigned)b - (unsigned)p;
-    if (uppersize >= sizeof (struct freeblock) &&
-        (rawsize - uppersize) >= sizeof (struct freeblock)) {
-
-        /* Setup the usedblock structure */
-        p->size  = uppersize;
-        p->start = p;
-
-        /* Generate a pointer to the user space and free the block */
-        free (p + 1);
-
-        /* Decrement the raw block size by the amount of space just free'd */
-        rawsize -= uppersize;
-    }
-
-    /* Check if we can free the space below the allocated block. This is the
-     * case, if the size of the block is at least sizeof (struct freeblock)
-     * bytes and the size of the remaining block is at least of this size,
-     * too. If the lower block is smaller, we will just pass it to the caller
-     * together with the requested aligned block.
-     * Beware: We need an additional struct usedblock in the lower block which
-     * is part of the block that is passed back to the caller.
-     */
-    lowersize = ((unsigned)u - (unsigned)b) - sizeof (struct usedblock);
-    if (lowersize >= sizeof (struct freeblock) &&
-        (rawsize - lowersize) >= sizeof (struct freeblock)) {
-
-        /* b does already point to the raw lower block. Setup the usedblock
-         * structure.
-         */
-        b->size  = lowersize;
-        b->start = b;
-
-        /* Generate a pointer to the user space and free the block */
-        free (b + 1);
-
-        /* Decrement the raw block size by the amount of space just free'd */
-        rawsize -= lowersize;
-
-        /* Set b to the raw user block */
-        b = u - 1;
-    }
-
-    /* u does now point to the user visible block, while b points to the raw
-     * block, and rawsize contains the size of the raw block. Setup the
-     * usedblock structure but beware: If we didn't free the lower block, it
-     * is splitted, which means that we must use u to write the start field,
-     * and b to write the size.
-     */
-    (u-1)->start = b;
-    b->size  = rawsize;
-
-    /* Return the user portion of the aligned block */
-    return u;
-}
-
-
-
diff --git a/libsrc/common/pmemalign.c b/libsrc/common/pmemalign.c
new file mode 100644 (file)
index 0000000..a8f34f7
--- /dev/null
@@ -0,0 +1,174 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                              posix_memalign                               */
+/*                                                                           */
+/*                     Allocate an aligned memory block                      */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2004-2005 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided "as-is," without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software.  If you use this software  */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated, but is not required.                                      */
+/* 2. Alterred source versions must be marked plainly as such, and must not  */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or alterred from any source             */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <stddef.h>                    /* define NULL */
+#include <stdlib.h>                    /* declare function's prototype */
+#include <_heap.h>
+
+#include <errno.h>
+#define EOK            0               /* No errors (non-standard name) */
+
+
+
+/* This is a very simple version of an aligned memory allocator.  We will
+ * allocate a greater block, so that we can place the aligned block (that is
+ * returned) within it.  We use our knowledge about the internal heap
+ * structures to free the unused parts of the bigger block (the two chunks
+ * below and above the aligned block).
+ */
+
+
+
+int __fastcall__ posix_memalign (void** memptr, size_t alignment, size_t size)
+/* Allocate a block of memory with the given "size", which is aligned to a
+ * memory address that is a multiple of "alignment".  "alignment" MUST NOT be
+ * zero, and MUST be a power of two; otherwise, this function will return
+ * EINVAL.  The function returns ENOMEM if not enough memory is available
+ * to satisfy the request.  "memptr" must point to a variable; that variable
+ * will return the address of the allocated memory.  Use free() to release that
+ * allocated block.
+ */
+{
+    size_t rawsize;
+    size_t uppersize;
+    size_t lowersize;
+    register struct usedblock* b;       /* points to raw Block */
+    register struct usedblock* u;       /* points to User block */
+    register struct usedblock* p;       /* Points to upper block */
+
+    /* Handle requests for zero-sized blocks */
+    if (size == 0) {
+        *memptr = NULL;
+        return EINVAL;
+    }
+
+    /* Test alignment: is it a power of two? There must be only one bit set. */
+    if (alignment == 0 || (alignment & --alignment) != 0) {
+        *memptr = NULL;
+        return EINVAL;
+    }
+
+    /* Augment the block size up to the alignment, and allocate memory.
+     * We don't need to account for the additional admin. data that's needed to
+     * manage the used block, because the block returned by malloc() has that
+     * overhead added one time; and, the worst thing that might happen is that
+     * we cannot free the upper and lower blocks.
+     */
+    b = malloc (size + alignment);
+
+    /* Handle out-of-memory */
+    if (b == NULL) {
+        *memptr = NULL;
+        return ENOMEM;
+    }
+
+    /* Create (and return) a new pointer that points to the user-visible
+     * aligned block.
+     */
+    u = *memptr = (struct usedblock*) (((unsigned)b + alignment) & ~alignment);
+
+    /* Get a pointer to the (raw) upper block */
+    p = (struct usedblock*) ((char*)u + size);
+
+    /* Get the raw-block pointer, which is located just below the visible
+     * unaligned block.  The first word of this raw block is the total size
+     * of the block, including the admin. space.
+     */
+    b = (b-1)->start;
+    rawsize = b->size;
+
+    /* Check if we can free the space above the user block.  That is the case
+     * if the size of the block is at least sizeof (struct freeblock) bytes,
+     * and the size of the remaining block is at least that size, too.
+     * If the upper block is smaller, then we just will pass it to the caller,
+     * together with the requested aligned block.
+     */
+    uppersize = rawsize - (lowersize = (char*)p - (char*)b);
+    if (uppersize >= sizeof (struct freeblock) &&
+        lowersize >= sizeof (struct freeblock)) {
+
+        /* Setup the usedblock structure */
+        p->size  = uppersize;
+        p->start = p;
+
+        /* Generate a pointer to the (upper) user space, and free that block */
+        free (p + 1);
+
+        /* Decrease the raw-block size by the amount of space just freed */
+        rawsize = lowersize;
+    }
+
+    /* Check if we can free the space below the user block.  That is the case
+     * if the size of the block is at least sizeof (struct freeblock) bytes,
+     * and the size of the remaining block is at least that size, too.  If the
+     * lower block is smaller, we just will pass it to the caller, together
+     * with the requested aligned block.
+     * Beware:  We need an additional struct usedblock, in the lower block,
+     * which is part of the block that is passed back to the caller.
+     */
+    lowersize = ((char*)u - (char*)b) - sizeof (struct usedblock);
+    if (           lowersize  >= sizeof (struct freeblock) &&
+        (rawsize - lowersize) >= sizeof (struct freeblock)) {
+
+        /* b already points to the raw lower-block.
+         * Set up the usedblock structure.
+         */
+        b->size  = lowersize;
+        b->start = b;
+
+        /* Generate a pointer to the (lower) user space, and free that block */
+        free (b + 1);
+
+        /* Decrease the raw-block size by the amount of space just freed */
+        rawsize -= lowersize;
+
+        /* Set b to the raw user-block (that will be returned) */
+        b = u - 1;
+    }
+
+    /* u points to the user-visible block, while b points to the raw block,
+     * and rawsize contains the length of the raw block.  Set up the usedblock
+     * structure, but beware:  If we didn't free the lower block, then it is
+     * split; which means that we must use b to write the size,
+     * and u to write the start field.
+     */
+    b->size = rawsize;
+    (u-1)->start = b;
+
+    return EOK;
+}
+
+
+