[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 = &current->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 &current->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