From 7a624b8901a256cded665ac72249b91679ac2a15 Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 24 Jul 2005 12:57:00 +0000 Subject: [PATCH] Replaced _aligned_malloc by the POSIX compatible function posix_memalign (Greg King). git-svn-id: svn://svn.cc65.org/cc65/trunk@3537 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- include/stdlib.h | 15 +-- libsrc/common/Makefile | 2 +- libsrc/common/_aligned_malloc.c | 163 ------------------------------ libsrc/common/pmemalign.c | 174 ++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 171 deletions(-) delete mode 100644 libsrc/common/_aligned_malloc.c create mode 100644 libsrc/common/pmemalign.c diff --git a/include/stdlib.h b/include/stdlib.h index 259b60233..6bacd952b 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -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); diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile index 151a0e339..464124192 100644 --- a/libsrc/common/Makefile +++ b/libsrc/common/Makefile @@ -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 index a74608b35..000000000 --- a/libsrc/common/_aligned_malloc.c +++ /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 -#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 index 000000000..a8f34f7f6 --- /dev/null +++ b/libsrc/common/pmemalign.c @@ -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 /* define NULL */ +#include /* declare function's prototype */ +#include <_heap.h> + +#include +#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; +} + + + -- 2.39.5