mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
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
This commit is contained in:
parent
19cb64885d
commit
7a624b8901
@ -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);
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
174
libsrc/common/pmemalign.c
Normal file
174
libsrc/common/pmemalign.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user