[PATCH] SPU allocator
Jeff Johnston
jjohnstn@redhat.com
Wed Feb 20 00:55:00 GMT 2008
Patrick Mansfield wrote:
> On Tue, Feb 19, 2008 at 10:46:20AM -0800, Patrick Mansfield wrote:
>
>> On Mon, Feb 18, 2008 at 01:01:31PM -0800, Patrick Mansfield wrote:
>>
>>> Hi Jeff -
>>>
>>>
1. Have you rigorously tested this? The malloc code in place has been
around for a while.
Have you looked at general performance in addition to just the
number of mallocs
possible? The current code is meant to be a good compromise of
everything:
------- from mallocr.c -------
* Why use this malloc?
This is not the fastest, most space-conserving, most portable, or
most tunable malloc ever written. However it is among the fastest
while also being among the most space-conserving, portable and tunable.
Consistent balance across these factors results in a good
general-purpose
allocator. For a high-level description, see
http://g.oswego.edu/dl/html/malloc.html
------- end of snippet ---------
2. The malloc.h changes would need cleaning up. I want us to move away
from
all the special clauses. You can either replace malloc.h for spu
entirely or else
you can use machine/malloc.h to define the macros in addition to
some flags that
malloc.h can test for. For now, you will have to leave in the
Cygwin tests which
I can remove later. Note the functions are also declared in
stdlib.h. If you are
looking to short-circuit internal calls, you need to consider this.
3. You don't have thread locking macros. This isn't a problem with
single threaded
only, but it would make sense to think about it early if future
multi-threaded support is
desired.
4. You don't have other mem object files such as vallocr replaced.
This will cause you
grief because libc/stdlib will build them based on the original
mallocr.c.
-- Jeff J.
>>> Can you comment or apply? Thanks ...
>>>
>> I messed up on the Makefile.am, I will repost soon with a proper
>> Makefile.am that doesn't have the memcmp.
>>
>
> OK here is the repost, same as last go but without memcmp in the
> Makefiles:
>
> Add a SPU specific malloc implementation that functions better with a
> limited amount of memory.
>
> A small test program (that does not call free nor realloc) with this
> allocator shows:
>
> [elm3a225 test]$ spu-size max-mallocs
> text data bss dec hex filename
> 6760 852 160 7772 1e5c max-mallocs
>
> Where base newlib has:
>
> [elm3a225 test]$ spu-size base-max-mallocs
> text data bss dec hex filename
> 10856 1924 240 13020 32dc base-max-mallocs
>
> And with the above test program compared with the newlib malloc including
> use of the extra space available, we can do:
>
> size max number of allocations
> (bytes) base SPU (new code)
> 8 15054 15617
> 32 5018 6928
> 64 3010 3672
> 128 1672 1892
> 512 456 484
> 1024 231 243
> 4096 57 60
>
> Newlib ChangeLog:
>
> 2008-02-19 Patrick Mansfield <patmans@us.ibm.com>
>
> * configure.host: For SPU, compile with -DMALLOC_PROVIDED.
> * libc/include/malloc.h: Add #if checks for __SPU__ to map _nnn_r
> malloc functions to nnn.
> * libc/machine/spu/Makefile.am: Add new files.
> * libc/machine/spu/Makefile.in: Regenerate.
> * libc/machine/spu/malloc.c: New file. Original SPU malloc design
> and code by Joel Schopp. Cleanups, bug fixes and memalign added
> by Patrick Mansfield.
> * libc/machine/spu/callocr.c: New file.
> * libc/machine/spu/freer.c: New file.
> * libc/machine/spu/malignr.c: New file.
> * libc/machine/spu/mallocr.c: New file.
> * libc/machine/spu/reallocr.c: New file.
>
> Index: quilt/newlib/libc/machine/spu/malloc.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/malloc.c
> @@ -0,0 +1,548 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from
> + this software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +/*
> + * SPU specific allocator: implements a best fit allocator designed to
> + * work well within a limited amount of memory (less than 256Kb in the
> + * SPU's Local Store).
> + */
> +#include <stddef.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdlib.h>
> +#include <stdint.h>
> +#include <errno.h>
> +
> +/* minimum size in bytes to add to free list */
> +#define SBRK_SIZE 16
> +
> +#define SPU_SIZE 262144
> +/* ALLOC_MIN >= ALIGN */
> +#define ALLOC_MIN 16
> +#define ALIGN 16
> +
> +#define ROUND_UP(x,y) ((x + y - 1) & ~(y - 1))
> +
> +typedef struct free_node {
> + uint32_t size;
> + struct free_node *prev;
> + struct free_node *next;
> + uint32_t pad;
> +} free_node_t;
> +
> +#define TRACKING_SIZE 512
> +#define TRACKING_COUNT (TRACKING_SIZE / sizeof(uint32_t) - 1)
> +
> +#define SMALL_ALLOC 8
> +#define SMALL_ALLOC_OFFSET 0x8
> +
> +typedef struct tracking_node {
> + struct tracking_node *next;
> + uint32_t header[TRACKING_COUNT];
> +} tracking_node_t;
> +
> +#define ADDR_MASK 0x0003FFFC /* 18 bit address and assume 4 byte alignment */
> +#define ADDR_SHIFT 14
> +#define SIZE_MASK 0x0003FFFC /* 18 bit size assume 4 byte increment */
> +#define SIZE_SHIFT 2
> +#define HEADER_ADDR_MASK 0xFFFF0000
> +#define HEADER_SIZE_MASK 0x0000FFFF
> +#define ENCODE_HEADER(addr, size) \
> + ((((uint32_t)addr & ADDR_MASK) << ADDR_SHIFT) | \
> + ((size & SIZE_MASK) >> SIZE_SHIFT))
> +#define DECODE_HEADER_ADDR(header) ((header & HEADER_ADDR_MASK) >> ADDR_SHIFT)
> +#define DECODE_HEADER_SIZE(header) ((header & HEADER_SIZE_MASK) << SIZE_SHIFT)
> +
> +extern uint32_t * __find_tracker (free_node_t *node);
> +extern uint32_t __remove_tracker (free_node_t *node);
> +extern void * __insert_tracker (free_node_t *node);
> +extern void __resize_tracker (free_node_t *node, uint32_t newsize);
> +extern free_node_t * __coalesce_node (free_node_t *node);
> +extern void __insert_node (free_node_t *node);
> +extern void * __extract (free_node_t *ptr, uint32_t size);
> +
> +#ifdef DEFINE_MALLOC
> +
> +static free_node_t *head = NULL;
> +static tracking_node_t *thead = NULL;
> +
> +/*
> + * Free areas (free_node_t) are stored in an unsorted link list, as this
> + * decreases code size, but does not give poor performance because of the
> + * small amount of memory and so likely small number of free nodes to
> + * manage.
> + */
> +void
> +__insert_node (free_node_t *node)
> +{
> + node->prev = NULL;
> + node->next = head;
> + if (head)
> + head->prev = node;
> + head = node;
> +}
> +
> +static void
> +remove_node (free_node_t *node)
> +{
> + if (head == node)
> + head = node->next;
> + if (node->next)
> + node->next->prev = node->prev;
> + if (node->prev)
> + node->prev->next = node->next;
> +}
> +
> +#define IS_BEFORE(x,y) (((uint32_t)x + x->size) == (uint32_t)y)
> +
> +/*
> + * When adding memory via sbrk() or freeing it via free(), memory is
> + * coalesced in order to form larger free blocks.
> + */
> +free_node_t *
> +__coalesce_node (free_node_t *node)
> +{
> + free_node_t *current = head;
> +
> + while (current != NULL) {
> + if (IS_BEFORE (current, node)) {
> + remove_node (current);
> + current->size += node->size;
> + node = current;
> + }
> + if (IS_BEFORE (node, current)) {
> + remove_node (current);
> + node->size += current->size;
> + }
> + current = current->next;
> + }
> + return node;
> +}
> +
> +static int
> +add_space (uint32_t size)
> +{
> + free_node_t *ptr;
> + free_node_t *node;
> +
> + if (size < SBRK_SIZE)
> + size = SBRK_SIZE;
> +
> + while (1) {
> + ptr = sbrk (size);
> + if ((uint32_t) ptr != -1) {
> + break;
> + } else {
> + /* If allocation failed try half as much */
> + size = size / 2;
> + if (size < ALLOC_MIN)
> + return -1;
> + size = ROUND_UP(size, ALIGN);
> + }
> + }
> +
> + /* FIFO insertion */
> + node = ptr;
> + node->size = size;
> + node = __coalesce_node (node);
> + __insert_node (node);
> +
> + return size;
> +}
> +
> +/*
> + * __extract: ptr must *not* be on the node list. Add a new node that
> + * leaves size bytes as used by ptr.
> + */
> +void *
> +__extract (free_node_t *ptr, uint32_t size)
> +{
> + free_node_t *ptr2;
> +
> + ptr2 = (free_node_t *) ((uint32_t) ptr + size);
> + ptr2->size = ptr->size - size;
> + __insert_node (ptr2);
> + ptr->size = size;
> + return ptr;
> +}
> +
> +static void *
> +internal_malloc (size_t size)
> +{
> + free_node_t *target = NULL;
> + free_node_t *current = head;
> + int ret;
> +
> + size = ROUND_UP (size, ALIGN);
> +
> + /* if the free list is empty add some to it */
> + if (current == NULL) {
> + ret = add_space (size);
> + current = head;
> + if (ret < 0)
> + return NULL;
> + }
> +
> + while (1) {
> + /* find the smallest big enough free block */
> + while (current != NULL) {
> + if (current->size >= size) {
> + if (target == NULL)
> + target = current;
> + else if (target->size > current->size)
> + target = current;
> + }
> + current = current->next;
> + }
> +
> + if (target) {
> + break;
> + } else {
> + /*
> + * free blocks, but none big enough. allocate one big enough and go
> + * again
> + */
> + ret = add_space (size);
> + if (ret < 0)
> + return NULL;
> + current = head;
> + }
> + }
> +
> + remove_node (target);
> + /*
> + * If the node we found has more space than we need free up the extra
> + * space.
> + */
> + if (target->size >= (size + ALLOC_MIN))
> + target = __extract (target, size);
> + return (void *) target;
> +}
> +
> +/*
> + * Headers (trackers) are maintained out of line (not in the allocated
> + * memory) in order to save space: with the standard newlib malloc(), a 32
> + * byte alignment must be used, so a 16 byte allocation must use 32 bytes
> + * (for the header plus the allocated data). Using an out of line header,
> + * a 16 byte allocation can be done using 20 bytes.
> + */
> +void *
> +__insert_tracker (free_node_t *node)
> +{
> + tracking_node_t *current = thead;
> + uint32_t *slot;
> + int i;
> +
> + while (1) {
> + while (current) {
> + for (i = 0; i < TRACKING_COUNT; i++) {
> + if (current->header[i] == 0) {
> + slot = ¤t->header[i];
> + *slot = ENCODE_HEADER (node, node->size);
> + return node;
> + }
> + }
> + /* didn't find one but have more to search */
> + current = current->next;
> + }
> +
> + /* still didn't find one try to allocate more */
> + current = internal_malloc (TRACKING_SIZE);
> + if (current == NULL) {
> + node->prev = NULL;
> + node->next = head;
> + head = node;
> + return NULL;
> + }
> +
> + /* FIXME, see if there is a faster way to 0 */
> + memset (current->header, 0, TRACKING_COUNT * 4);
> + current->next = thead;
> + thead = current;
> + }
> +}
> +
> +uint32_t *
> +__find_tracker (free_node_t *node)
> +{
> + tracking_node_t *current = thead;
> + int i;
> +
> + for (current = thead; current; current = current->next)
> + for (i = 0; i < TRACKING_SIZE; i++)
> + if ((uint32_t) node == DECODE_HEADER_ADDR (current->header[i]))
> + return ¤t->header[i];
> +
> + return NULL;
> +}
> +
> +uint32_t
> +__remove_tracker (free_node_t *node)
> +{
> + uint32_t *track;
> + uint32_t ret;
> +
> + track = __find_tracker(node);
> + if (track) {
> + ret = DECODE_HEADER_SIZE (*track);
> + *track = 0;
> + } else {
> + /*
> + * Probably node was not gotten via malloc()!
> + */
> + ret = 0;
> + }
> + return ret;
> +
> +}
> +
> +void
> +__resize_tracker (free_node_t *node, uint32_t newsize)
> +{
> + uint32_t *track;
> +
> + track = __find_tracker(node);
> + if (track)
> + *track = ENCODE_HEADER (node, newsize);
> +}
> +
> +/*
> + * All allocations are in increments of 16 bytes, even if only 1 or 2
> + * bytes were requested. Since the tracker will take another 4 bytes,
> + * that is a minimum of 20 bytes, and is bad for small allocations.
> + *
> + * We don't generally care about smaller allocations as they are a bad
> + * idea to begin with, but as a small concession to the fact that there
> + * are likely to be a few out there anyway we do some magic to avoid doing
> + * the 4 bytes in the header tracker. As a result only 16 bytes are used
> + * for a small allocation (1-8 bytes) and 20 bytes for a large allocation
> + * (9bytes-256KB).
> + */
> +
> +void *
> +malloc (size_t size)
> +{
> + void *ret = NULL;
> +
> + if (size == 0)
> + size = 1;
> + /*
> + * This check covers negative numbers and numbers that would
> + * overflow if rounded up.
> + */
> + if (size > SPU_SIZE)
> + goto out;
> +
> + ret = internal_malloc (size);
> + if (size > SMALL_ALLOC)
> + ret = __insert_tracker (ret);
> + else if (ret)
> + ret = ret + SMALL_ALLOC_OFFSET;
> +
> +out:
> + if (!ret)
> + errno = ENOMEM;
> + return ret;
> +}
> +#endif
> +
> +#ifdef DEFINE_FREE
> +void
> +free (void *ptr)
> +{
> + free_node_t *node;
> +
> + if (ptr == NULL)
> + return;
> + if ((uint32_t) ptr & SMALL_ALLOC_OFFSET) {
> + node = (free_node_t *) ((uint32_t) ptr - SMALL_ALLOC_OFFSET);
> + node->size = 16;
> + } else {
> + node = ptr;
> + node->size = __remove_tracker (node);
> + }
> + node = __coalesce_node (node);
> + __insert_node (node);
> +}
> +#endif
> +
> +#ifdef DEFINE_REALLOC
> +
> +#define MIN(a,b) (((a) < (b)) ? (a) : (b))
> +
> +/*
> + * realloc is not optimized - it does not try to extend previously
> + * malloced space, it is just a malloc-copy-free.
> + */
> +
> +void *
> +realloc (void *ptr, size_t size)
> +{
> + void *new_ptr;
> + uint32_t *track;
> + size_t old_size = 0;
> +
> + if (ptr == NULL)
> + return malloc (size);
> +
> + new_ptr = malloc (size);
> + if (!new_ptr) {
> + errno = ENOMEM;
> + return 0;
> + }
> +
> + if ((uint32_t) ptr & SMALL_ALLOC_OFFSET) {
> + old_size = SMALL_ALLOC_OFFSET;
> + } else {
> + track = __find_tracker ((free_node_t*) ptr);
> + if (track)
> + old_size = DECODE_HEADER_SIZE(*track);
> + else
> + old_size = 0; /* realloc() un-malloced ptr value! */
> + }
> + memcpy (new_ptr, ptr, MIN (size, old_size));
> + free (ptr);
> + return (new_ptr);
> +}
> +#endif
> +
> +#ifdef DEFINE_CALLOC
> +void *
> +calloc (size_t n, size_t size)
> +{
> + void* ret;
> +
> + ret = malloc(n * size);
> + if (ret)
> + memset(ret, 0, n * size);
> + return ret;
> +}
> +#endif
> +
> +#ifdef DEFINE_MEMALIGN
> +
> +void *memalign(size_t align, size_t bytes)
> +{
> + char *malloc_val, *aligned_val, *free_loc, *end_val;
> + size_t free_length, cur_size, keep_length;
> + free_node_t *node;
> +
> + /*
> + * Check that align is a power of 2, treat 0 as OK.
> + */
> + if (align & (align - 1))
> + return NULL;
> +
> + if (align < 8)
> + align = 8;
> + if (bytes <= SMALL_ALLOC) {
> + if (align == 8) {
> + /*
> + * Small allocations have an 8 byte alignment.
> + */
> + return malloc(bytes);
> + }
> + } else if (align <= ALIGN) {
> + /*
> + * Larger allocations have 16 (ALIGN) byte alignment. We can't do
> + * this if bytes <= SMALL_ALLOC, since we would get aligned on an 8
> + * byte or smaller boundary.
> + */
> + return malloc(bytes);
> + }
> +
> + /*
> + * At this point, we have:
> + *
> + * align is a power of 2
> + * align > 16 *or* (bytes <= SMALL_ALLOC) && align >= 16
> + */
> +
> + /*
> + * Allocate a size increased by the alignment that we need, plus
> + * ALLOC_MIN so we have room to adjust the leftover space.
> + */
> + aligned_val = malloc_val = malloc (bytes + align + ALLOC_MIN);
> + if (!malloc_val)
> + return NULL;
> + node = (free_node_t *) malloc_val;
> +
> + if (((int) malloc_val % align) != 0) {
> + /*
> + * unaligned.
> + */
> + aligned_val = (char *) (((int) malloc_val + align - 1) & -align);
> +
> + /*
> + * Free the unused leading portion.
> + *
> + * Since the SPU malloc will have returned mod 16 or better (in
> + * malloc_val), we have to have gotten 16 or better alignment, can't
> + * have anything less than 16 bytes here to free up, and must be a
> + * multiple of 16 (to be freed).
> + *
> + * Do the same as free() and then adjust the size.
> + */
> + node = (free_node_t *) malloc_val;
> + cur_size = __remove_tracker (node);
> + free_length = aligned_val - malloc_val;
> + node->size = free_length;
> + node = __coalesce_node (node);
> + __insert_node (node);
> +
> + node = (free_node_t *) aligned_val;
> + /*
> + * cur_size should equal bytes + align + ALLOC_MIN rounded up to 16,
> + * since malloc() rounds it up.
> + */
> + node->size = cur_size - free_length;
> + __insert_tracker(node);
> + }
> +
> + /*
> + * If possible, free any unused trailing portions. We can only free in
> + * chunks of 16 bytes on a 16 byte alignment.
> + */
> + free_length = node->size - bytes;
> + free_loc = aligned_val + bytes;
> + end_val = (char*) ROUND_UP((uint32_t) free_loc, ALIGN);
> + free_length = free_length - (end_val - free_loc);
> + if (free_length >= ALLOC_MIN) {
> + keep_length = ROUND_UP(bytes, ALIGN);
> + /*
> + * __extract: pass in the starting point and how much to *keep*.
> + */
> + aligned_val = __extract ((free_node_t *) aligned_val, keep_length);
> + __resize_tracker((free_node_t*) aligned_val, keep_length);
> + }
> +
> + return aligned_val;
> +}
> +#endif
> Index: quilt/newlib/libc/machine/spu/Makefile.in
> ===================================================================
> --- quilt.orig/newlib/libc/machine/spu/Makefile.in
> +++ quilt/newlib/libc/machine/spu/Makefile.in
> @@ -73,7 +73,9 @@ DIST_COMMON = $(srcdir)/../../../../conf
> $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
> $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
> $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
> - $(srcdir)/../../../../compile
> + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
> + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \
> + $(srcdir)/../../../../compile $(srcdir)/../../../../compile
> subdir = .
> ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
> am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \
> @@ -87,49 +89,54 @@ CONFIG_CLEAN_FILES =
> LIBRARIES = $(noinst_LIBRARIES)
> ARFLAGS = cru
> lib_a_AR = $(AR) $(ARFLAGS)
> -lib_a_LIBADD =
> -am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-clearerr.$(OBJEXT) \
> - lib_a-creat.$(OBJEXT) lib_a-fclose.$(OBJEXT) \
> - lib_a-feof.$(OBJEXT) lib_a-ferror.$(OBJEXT) \
> - lib_a-fflush.$(OBJEXT) lib_a-fgetc.$(OBJEXT) \
> - lib_a-fgetpos.$(OBJEXT) lib_a-fgets.$(OBJEXT) \
> - lib_a-fileno.$(OBJEXT) lib_a-fiprintf.$(OBJEXT) \
> - lib_a-fiscanf.$(OBJEXT) lib_a-fopen.$(OBJEXT) \
> - lib_a-fprintf.$(OBJEXT) lib_a-fputc.$(OBJEXT) \
> - lib_a-fputs.$(OBJEXT) lib_a-fread.$(OBJEXT) \
> +am__DEPENDENCIES_1 = $(lpfx)calloc.$(oext) $(lpfx)free.$(oext) \
> + $(lpfx)malign.$(oext) $(lpfx)malloc.$(oext) \
> + $(lpfx)realloc.$(oext)
> +lib_a_DEPENDENCIES = $(am__DEPENDENCIES_1)
> +am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-callocr.$(OBJEXT) \
> + lib_a-clearerr.$(OBJEXT) lib_a-creat.$(OBJEXT) \
> + lib_a-fclose.$(OBJEXT) lib_a-feof.$(OBJEXT) \
> + lib_a-ferror.$(OBJEXT) lib_a-fflush.$(OBJEXT) \
> + lib_a-fgetc.$(OBJEXT) lib_a-fgetpos.$(OBJEXT) \
> + lib_a-fgets.$(OBJEXT) lib_a-fileno.$(OBJEXT) \
> + lib_a-fiprintf.$(OBJEXT) lib_a-fiscanf.$(OBJEXT) \
> + lib_a-fopen.$(OBJEXT) lib_a-fprintf.$(OBJEXT) \
> + lib_a-fputc.$(OBJEXT) lib_a-fputs.$(OBJEXT) \
> + lib_a-fread.$(OBJEXT) lib_a-freer.$(OBJEXT) \
> lib_a-freopen.$(OBJEXT) lib_a-fscanf.$(OBJEXT) \
> lib_a-fseek.$(OBJEXT) lib_a-fsetpos.$(OBJEXT) \
> lib_a-ftell.$(OBJEXT) lib_a-fwrite.$(OBJEXT) \
> lib_a-getc.$(OBJEXT) lib_a-getchar.$(OBJEXT) \
> lib_a-gets.$(OBJEXT) lib_a-iprintf.$(OBJEXT) \
> - lib_a-iscanf.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \
> + lib_a-iscanf.$(OBJEXT) lib_a-malignr.$(OBJEXT) \
> + lib_a-mallocr.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \
> lib_a-memmove.$(OBJEXT) lib_a-memset.$(OBJEXT) \
> lib_a-perror.$(OBJEXT) lib_a-printf.$(OBJEXT) \
> lib_a-putc.$(OBJEXT) lib_a-putchar.$(OBJEXT) \
> - lib_a-puts.$(OBJEXT) lib_a-remove.$(OBJEXT) \
> - lib_a-rename.$(OBJEXT) lib_a-rewind.$(OBJEXT) \
> - lib_a-scanf.$(OBJEXT) lib_a-setbuf.$(OBJEXT) \
> - lib_a-setvbuf.$(OBJEXT) lib_a-siprintf.$(OBJEXT) \
> - lib_a-siscanf.$(OBJEXT) lib_a-sleep.$(OBJEXT) \
> - lib_a-sniprintf.$(OBJEXT) lib_a-snprintf.$(OBJEXT) \
> - lib_a-sprintf.$(OBJEXT) lib_a-sscanf.$(OBJEXT) \
> - lib_a-stdio.$(OBJEXT) lib_a-strcat.$(OBJEXT) \
> - lib_a-strchr.$(OBJEXT) lib_a-strcmp.$(OBJEXT) \
> - lib_a-strcpy.$(OBJEXT) lib_a-strcspn.$(OBJEXT) \
> - lib_a-strlen.$(OBJEXT) lib_a-strncat.$(OBJEXT) \
> - lib_a-strncmp.$(OBJEXT) lib_a-strncpy.$(OBJEXT) \
> - lib_a-strpbrk.$(OBJEXT) lib_a-strrchr.$(OBJEXT) \
> - lib_a-strspn.$(OBJEXT) lib_a-strxfrm.$(OBJEXT) \
> - lib_a-tmpfile.$(OBJEXT) lib_a-tmpnam.$(OBJEXT) \
> - lib_a-ungetc.$(OBJEXT) lib_a-usleep.$(OBJEXT) \
> - lib_a-vfiprintf.$(OBJEXT) lib_a-vfiscanf.$(OBJEXT) \
> - lib_a-vfprintf.$(OBJEXT) lib_a-vfscanf.$(OBJEXT) \
> - lib_a-viprintf.$(OBJEXT) lib_a-viscanf.$(OBJEXT) \
> - lib_a-vprintf.$(OBJEXT) lib_a-vscanf.$(OBJEXT) \
> - lib_a-vsiprintf.$(OBJEXT) lib_a-vsiscanf.$(OBJEXT) \
> - lib_a-vsniprintf.$(OBJEXT) lib_a-vsnprintf.$(OBJEXT) \
> - lib_a-vsprintf.$(OBJEXT) lib_a-vsscanf.$(OBJEXT) \
> - lib_a-stack_reg_va.$(OBJEXT)
> + lib_a-puts.$(OBJEXT) lib_a-reallocr.$(OBJEXT) \
> + lib_a-remove.$(OBJEXT) lib_a-rename.$(OBJEXT) \
> + lib_a-rewind.$(OBJEXT) lib_a-scanf.$(OBJEXT) \
> + lib_a-setbuf.$(OBJEXT) lib_a-setvbuf.$(OBJEXT) \
> + lib_a-siprintf.$(OBJEXT) lib_a-siscanf.$(OBJEXT) \
> + lib_a-sleep.$(OBJEXT) lib_a-sniprintf.$(OBJEXT) \
> + lib_a-snprintf.$(OBJEXT) lib_a-sprintf.$(OBJEXT) \
> + lib_a-sscanf.$(OBJEXT) lib_a-stdio.$(OBJEXT) \
> + lib_a-strcat.$(OBJEXT) lib_a-strchr.$(OBJEXT) \
> + lib_a-strcmp.$(OBJEXT) lib_a-strcpy.$(OBJEXT) \
> + lib_a-strcspn.$(OBJEXT) lib_a-strlen.$(OBJEXT) \
> + lib_a-strncat.$(OBJEXT) lib_a-strncmp.$(OBJEXT) \
> + lib_a-strncpy.$(OBJEXT) lib_a-strpbrk.$(OBJEXT) \
> + lib_a-strrchr.$(OBJEXT) lib_a-strspn.$(OBJEXT) \
> + lib_a-strxfrm.$(OBJEXT) lib_a-tmpfile.$(OBJEXT) \
> + lib_a-tmpnam.$(OBJEXT) lib_a-ungetc.$(OBJEXT) \
> + lib_a-usleep.$(OBJEXT) lib_a-vfiprintf.$(OBJEXT) \
> + lib_a-vfiscanf.$(OBJEXT) lib_a-vfprintf.$(OBJEXT) \
> + lib_a-vfscanf.$(OBJEXT) lib_a-viprintf.$(OBJEXT) \
> + lib_a-viscanf.$(OBJEXT) lib_a-vprintf.$(OBJEXT) \
> + lib_a-vscanf.$(OBJEXT) lib_a-vsiprintf.$(OBJEXT) \
> + lib_a-vsiscanf.$(OBJEXT) lib_a-vsniprintf.$(OBJEXT) \
> + lib_a-vsnprintf.$(OBJEXT) lib_a-vsprintf.$(OBJEXT) \
> + lib_a-vsscanf.$(OBJEXT) lib_a-stack_reg_va.$(OBJEXT)
> lib_a_OBJECTS = $(am_lib_a_OBJECTS)
> DEFAULT_INCLUDES = -I. -I$(srcdir)
> depcomp =
> @@ -203,6 +210,11 @@ STRIP = @STRIP@
> USE_LIBTOOL_FALSE = @USE_LIBTOOL_FALSE@
> USE_LIBTOOL_TRUE = @USE_LIBTOOL_TRUE@
> VERSION = @VERSION@
> +ac_ct_AR = @ac_ct_AR@
> +ac_ct_AS = @ac_ct_AS@
> +ac_ct_RANLIB = @ac_ct_RANLIB@
> +ac_ct_READELF = @ac_ct_READELF@
> +ac_ct_STRIP = @ac_ct_STRIP@
> aext = @aext@
> am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
> am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
> @@ -218,23 +230,18 @@ build_cpu = @build_cpu@
> build_os = @build_os@
> build_vendor = @build_vendor@
> datadir = @datadir@
> -datarootdir = @datarootdir@
> -docdir = @docdir@
> -dvidir = @dvidir@
> exec_prefix = @exec_prefix@
> host = @host@
> host_alias = @host_alias@
> host_cpu = @host_cpu@
> host_os = @host_os@
> host_vendor = @host_vendor@
> -htmldir = @htmldir@
> includedir = @includedir@
> infodir = @infodir@
> install_sh = @install_sh@
> libdir = @libdir@
> libexecdir = @libexecdir@
> libm_machine_dir = @libm_machine_dir@
> -localedir = @localedir@
> localstatedir = @localstatedir@
> lpfx = @lpfx@
> machine_dir = @machine_dir@
> @@ -243,10 +250,8 @@ mkdir_p = @mkdir_p@
> newlib_basedir = @newlib_basedir@
> oext = @oext@
> oldincludedir = @oldincludedir@
> -pdfdir = @pdfdir@
> prefix = @prefix@
> program_transform_name = @program_transform_name@
> -psdir = @psdir@
> sbindir = @sbindir@
> sharedstatedir = @sharedstatedir@
> sys_dir = @sys_dir@
> @@ -256,22 +261,31 @@ AUTOMAKE_OPTIONS = cygnus
> INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
> noinst_LIBRARIES = lib.a
> AM_CCASFLAGS = $(INCLUDES)
> -lib_a_SOURCES = setjmp.S clearerr.c creat.c fclose.c feof.c ferror.c fflush.c \
> - fgetc.c fgetpos.c fgets.c fileno.c fiprintf.S fiscanf.S fopen.c \
> - fprintf.S fputc.c fputs.c fread.c freopen.c fscanf.S fseek.c \
> - fsetpos.c ftell.c fwrite.c getc.c getchar.c gets.c iprintf.S \
> - iscanf.S memcpy.c memmove.c memset.c perror.c printf.S \
> - putc.c putchar.c puts.c remove.c rename.c rewind.c scanf.S \
> - setbuf.c setvbuf.c siprintf.S siscanf.S sleep.c sniprintf.S \
> - snprintf.S sprintf.S sscanf.S stdio.c strcat.c strchr.c strcmp.c \
> - strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \
> - strrchr.c strspn.c strxfrm.c tmpfile.c tmpnam.c ungetc.c usleep.c \
> +lib_a_SOURCES = setjmp.S callocr.c clearerr.c creat.c fclose.c feof.c \
> + ferror.c fflush.c fgetc.c fgetpos.c fgets.c fileno.c fiprintf.S \
> + fiscanf.S fopen.c fprintf.S fputc.c fputs.c fread.c freer.c \
> + freopen.c fscanf.S fseek.c fsetpos.c ftell.c fwrite.c getc.c \
> + getchar.c gets.c iprintf.S iscanf.S malignr.c mallocr.c memcpy.c \
> + memmove.c memset.c perror.c printf.S putc.c putchar.c puts.c \
> + reallocr.c remove.c rename.c rewind.c scanf.S setbuf.c setvbuf.c \
> + siprintf.S siscanf.S sleep.c sniprintf.S snprintf.S sprintf.S \
> + sscanf.S stdio.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c \
> + strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c \
> + strspn.c strxfrm.c tmpfile.c tmpnam.c ungetc.c usleep.c \
> vfiprintf.c vfiscanf.c vfprintf.c vfscanf.c viprintf.c viscanf.c \
> vprintf.c vscanf.c vsiprintf.c vsiscanf.c vsniprintf.c vsnprintf.c \
> vsprintf.c vsscanf.c stack_reg_va.S
>
> +LIBADD_OBJS = \
> + $(lpfx)calloc.$(oext) \
> + $(lpfx)free.$(oext) \
> + $(lpfx)malign.$(oext) \
> + $(lpfx)malloc.$(oext) \
> + $(lpfx)realloc.$(oext)
> +
> lib_a_CCASFLAGS = $(AM_CCASFLAGS)
> lib_a_CFLAGS = $(AM_CFLAGS)
> +lib_a_LIBADD = $(LIBADD_OBJS)
> ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
> CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
> all: all-am
> @@ -433,6 +447,12 @@ lib_a-stack_reg_va.obj: stack_reg_va.S
> .c.obj:
> $(COMPILE) -c `$(CYGPATH_W) '$<'`
>
> +lib_a-callocr.o: callocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-callocr.o `test -f 'callocr.c' || echo '$(srcdir)/'`callocr.c
> +
> +lib_a-callocr.obj: callocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-callocr.obj `if test -f 'callocr.c'; then $(CYGPATH_W) 'callocr.c'; else $(CYGPATH_W) '$(srcdir)/callocr.c'; fi`
> +
> lib_a-clearerr.o: clearerr.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-clearerr.o `test -f 'clearerr.c' || echo '$(srcdir)/'`clearerr.c
>
> @@ -517,6 +537,12 @@ lib_a-fread.o: fread.c
> lib_a-fread.obj: fread.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fread.obj `if test -f 'fread.c'; then $(CYGPATH_W) 'fread.c'; else $(CYGPATH_W) '$(srcdir)/fread.c'; fi`
>
> +lib_a-freer.o: freer.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-freer.o `test -f 'freer.c' || echo '$(srcdir)/'`freer.c
> +
> +lib_a-freer.obj: freer.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-freer.obj `if test -f 'freer.c'; then $(CYGPATH_W) 'freer.c'; else $(CYGPATH_W) '$(srcdir)/freer.c'; fi`
> +
> lib_a-freopen.o: freopen.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-freopen.o `test -f 'freopen.c' || echo '$(srcdir)/'`freopen.c
>
> @@ -565,6 +591,18 @@ lib_a-gets.o: gets.c
> lib_a-gets.obj: gets.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-gets.obj `if test -f 'gets.c'; then $(CYGPATH_W) 'gets.c'; else $(CYGPATH_W) '$(srcdir)/gets.c'; fi`
>
> +lib_a-malignr.o: malignr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-malignr.o `test -f 'malignr.c' || echo '$(srcdir)/'`malignr.c
> +
> +lib_a-malignr.obj: malignr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-malignr.obj `if test -f 'malignr.c'; then $(CYGPATH_W) 'malignr.c'; else $(CYGPATH_W) '$(srcdir)/malignr.c'; fi`
> +
> +lib_a-mallocr.o: mallocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mallocr.o `test -f 'mallocr.c' || echo '$(srcdir)/'`mallocr.c
> +
> +lib_a-mallocr.obj: mallocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-mallocr.obj `if test -f 'mallocr.c'; then $(CYGPATH_W) 'mallocr.c'; else $(CYGPATH_W) '$(srcdir)/mallocr.c'; fi`
> +
> lib_a-memcpy.o: memcpy.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memcpy.o `test -f 'memcpy.c' || echo '$(srcdir)/'`memcpy.c
>
> @@ -607,6 +645,12 @@ lib_a-puts.o: puts.c
> lib_a-puts.obj: puts.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-puts.obj `if test -f 'puts.c'; then $(CYGPATH_W) 'puts.c'; else $(CYGPATH_W) '$(srcdir)/puts.c'; fi`
>
> +lib_a-reallocr.o: reallocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-reallocr.o `test -f 'reallocr.c' || echo '$(srcdir)/'`reallocr.c
> +
> +lib_a-reallocr.obj: reallocr.c
> + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-reallocr.obj `if test -f 'reallocr.c'; then $(CYGPATH_W) 'reallocr.c'; else $(CYGPATH_W) '$(srcdir)/reallocr.c'; fi`
> +
> lib_a-remove.o: remove.c
> $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-remove.o `test -f 'remove.c' || echo '$(srcdir)/'`remove.c
>
> @@ -972,6 +1016,21 @@ uninstall-am:
> mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
> uninstall-am uninstall-info-am
>
> +
> +$(lpfx)calloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_CALLOC -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)free.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_FREE -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)malign.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)malloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_MALLOC -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)realloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_REALLOC -c $(srcdir)/malloc.c -o $@
> # Tell versions [3.59,3.63) of GNU make to not export all variables.
> # Otherwise a system limit (for SysV at least) may be exceeded.
> .NOEXPORT:
> Index: quilt/newlib/libc/machine/spu/callocr.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/callocr.c
> @@ -0,0 +1,43 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from this
> + software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +#include <reent.h>
> +#include <malloc.h>
> +
> +/*
> + * For __SPU__, _calloc_r is defined to calloc, but in case malloc.h is
> + * not included, include a function for it.
> + */
> +#undef _calloc_r
> +void *
> +_calloc_r (struct _reent *reent, size_t nmemb, size_t bytes)
> +{
> + return calloc (nmemb, bytes);
> +}
> Index: quilt/newlib/libc/machine/spu/freer.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/freer.c
> @@ -0,0 +1,43 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from this
> + software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +#include <reent.h>
> +#include <malloc.h>
> +
> +/*
> + * For __SPU__, _free_r is defined to free, but in case malloc.h is
> + * not included, include a function for it.
> + */
> +#undef _free_r
> +void
> +_free_r (struct _reent *reent, void *ptr)
> +{
> + free (ptr);
> +}
> Index: quilt/newlib/libc/machine/spu/mallocr.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/mallocr.c
> @@ -0,0 +1,43 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from this
> + software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +#include <reent.h>
> +#include <malloc.h>
> +
> +/*
> + * For __SPU__, _malloc_r is defined to malloc, but in case malloc.h is
> + * not included, include a function for it.
> + */
> +#undef _malloc_r
> +void *
> +_malloc_r (struct _reent *reent, size_t bytes)
> +{
> + return malloc (bytes);
> +}
> Index: quilt/newlib/libc/machine/spu/reallocr.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/reallocr.c
> @@ -0,0 +1,43 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from this
> + software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +#include <reent.h>
> +#include <malloc.h>
> +
> +/*
> + * For __SPU__, _realloc_r is defined to realloc, but in case malloc.h is
> + * not included, include a function for it.
> + */
> +#undef _realloc_r
> +void *
> +_realloc_r (struct _reent *reent, void *ptr, size_t bytes)
> +{
> + return realloc (ptr, bytes);
> +}
> Index: quilt/newlib/libc/include/malloc.h
> ===================================================================
> --- quilt.orig/newlib/libc/include/malloc.h
> +++ quilt/newlib/libc/include/malloc.h
> @@ -35,7 +35,7 @@ struct mallinfo {
> /* The routines. */
>
> extern _PTR malloc _PARAMS ((size_t));
> -#ifdef __CYGWIN__
> +#if defined(__CYGWIN__) || defined(__SPU__)
> #undef _malloc_r
> #define _malloc_r(r, s) malloc (s)
> #else
> @@ -43,7 +43,7 @@ extern _PTR _malloc_r _PARAMS ((struct _
> #endif
>
> extern _VOID free _PARAMS ((_PTR));
> -#ifdef __CYGWIN__
> +#if defined(__CYGWIN__) || defined(__SPU__)
> #undef _free_r
> #define _free_r(r, p) free (p)
> #else
> @@ -51,7 +51,7 @@ extern _VOID _free_r _PARAMS ((struct _r
> #endif
>
> extern _PTR realloc _PARAMS ((_PTR, size_t));
> -#ifdef __CYGWIN__
> +#if defined(__CYGWIN__) || defined(__SPU__)
> #undef _realloc_r
> #define _realloc_r(r, p, s) realloc (p, s)
> #else
> @@ -59,7 +59,7 @@ extern _PTR _realloc_r _PARAMS ((struct
> #endif
>
> extern _PTR calloc _PARAMS ((size_t, size_t));
> -#ifdef __CYGWIN__
> +#if defined(__CYGWIN__) || defined(__SPU__)
> #undef _calloc_r
> #define _calloc_r(r, s1, s2) calloc (s1, s2);
> #else
> @@ -67,7 +67,7 @@ extern _PTR _calloc_r _PARAMS ((struct _
> #endif
>
> extern _PTR memalign _PARAMS ((size_t, size_t));
> -#ifdef __CYGWIN__
> +#if defined(__CYGWIN__) || defined(__SPU__)
> #undef _memalign_r
> #define _memalign_r(r, s1, s2) memalign (s1, s2);
> #else
> Index: quilt/newlib/configure.host
> ===================================================================
> --- quilt.orig/newlib/configure.host
> +++ quilt/newlib/configure.host
> @@ -268,7 +268,7 @@ case "${host_cpu}" in
> stdio_dir=
> libm_machine_dir=spu
> machine_dir=spu
> - newlib_cflags="${newlib_cflags} -D_POSIX_MODE -ffunction-sections -fdata-sections "
> + newlib_cflags="${newlib_cflags} -DMALLOC_PROVIDED -D_POSIX_MODE -ffunction-sections -fdata-sections "
> ;;
> *)
> echo '***' "Newlib does not support CPU ${host_cpu}" 1>&2
> Index: quilt/newlib/libc/machine/spu/malignr.c
> ===================================================================
> --- /dev/null
> +++ quilt/newlib/libc/machine/spu/malignr.c
> @@ -0,0 +1,43 @@
> +/*
> + (C) Copyright 2007, 2008
> + International Business Machines Corporation,
> + All rights reserved.
> +
> + Redistribution and use in source and binary forms, with or without
> + modification, are permitted provided that the following conditions are met:
> +
> + * Redistributions of source code must retain the above copyright notice,
> + this list of conditions and the following disclaimer.
> + * Redistributions in binary form must reproduce the above copyright
> + notice, this list of conditions and the following disclaimer in the
> + documentation and/or other materials provided with the distribution.
> + * Neither the names of the copyright holders nor the names of their
> + contributors may be used to endorse or promote products derived from this
> + software without specific prior written permission.
> +
> + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
> + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
> + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
> + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
> + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +*/
> +
> +#include <reent.h>
> +#include <malloc.h>
> +
> +/*
> + * For __SPU__, _memalign_r is defined to memalign, but in case malloc.h
> + * is not included, include a function for it.
> + */
> +#undef _memalign_r
> +void *
> +_memalign_r (struct _reent *reent, size_t alignment, size_t bytes)
> +{
> + return memalign (alignment, bytes);
> +}
> Index: quilt/newlib/libc/machine/spu/Makefile.am
> ===================================================================
> --- quilt.orig/newlib/libc/machine/spu/Makefile.am
> +++ quilt/newlib/libc/machine/spu/Makefile.am
> @@ -8,23 +8,47 @@ noinst_LIBRARIES = lib.a
>
> AM_CCASFLAGS = $(INCLUDES)
>
> -lib_a_SOURCES = setjmp.S clearerr.c creat.c fclose.c feof.c ferror.c fflush.c \
> - fgetc.c fgetpos.c fgets.c fileno.c fiprintf.S fiscanf.S fopen.c \
> - fprintf.S fputc.c fputs.c fread.c freopen.c fscanf.S fseek.c \
> - fsetpos.c ftell.c fwrite.c getc.c getchar.c gets.c iprintf.S \
> - iscanf.S memcpy.c memmove.c memset.c perror.c printf.S \
> - putc.c putchar.c puts.c remove.c rename.c rewind.c scanf.S \
> - setbuf.c setvbuf.c siprintf.S siscanf.S sleep.c sniprintf.S \
> - snprintf.S sprintf.S sscanf.S stdio.c strcat.c strchr.c strcmp.c \
> - strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \
> - strrchr.c strspn.c strxfrm.c tmpfile.c tmpnam.c ungetc.c usleep.c \
> +lib_a_SOURCES = setjmp.S callocr.c clearerr.c creat.c fclose.c feof.c \
> + ferror.c fflush.c fgetc.c fgetpos.c fgets.c fileno.c fiprintf.S \
> + fiscanf.S fopen.c fprintf.S fputc.c fputs.c fread.c freer.c \
> + freopen.c fscanf.S fseek.c fsetpos.c ftell.c fwrite.c getc.c \
> + getchar.c gets.c iprintf.S iscanf.S malignr.c mallocr.c memcpy.c \
> + memmove.c memset.c perror.c printf.S putc.c putchar.c puts.c \
> + reallocr.c remove.c rename.c rewind.c scanf.S setbuf.c setvbuf.c \
> + siprintf.S siscanf.S sleep.c sniprintf.S snprintf.S sprintf.S \
> + sscanf.S stdio.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c \
> + strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c \
> + strspn.c strxfrm.c tmpfile.c tmpnam.c ungetc.c usleep.c \
> vfiprintf.c vfiscanf.c vfprintf.c vfscanf.c viprintf.c viscanf.c \
> vprintf.c vscanf.c vsiprintf.c vsiscanf.c vsniprintf.c vsnprintf.c \
> vsprintf.c vsscanf.c stack_reg_va.S
>
> +LIBADD_OBJS = \
> + $(lpfx)calloc.$(oext) \
> + $(lpfx)free.$(oext) \
> + $(lpfx)malign.$(oext) \
> + $(lpfx)malloc.$(oext) \
> + $(lpfx)realloc.$(oext)
> +
> lib_a_CCASFLAGS = $(AM_CCASFLAGS)
> lib_a_CFLAGS = $(AM_CFLAGS)
>
> +lib_a_LIBADD = $(LIBADD_OBJS)
> +
> ACLOCAL_AMFLAGS = -I ../../.. -I ../../../..
> CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
>
> +$(lpfx)calloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_CALLOC -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)free.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_FREE -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)malign.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_MEMALIGN -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)malloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_MALLOC -c $(srcdir)/malloc.c -o $@
> +
> +$(lpfx)realloc.$(oext): malloc.c
> + $(COMPILE) -DDEFINE_REALLOC -c $(srcdir)/malloc.c -o $@
>
More information about the Newlib
mailing list