This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] SPU allocator


Hi Jeff -

Can you comment or apply? Thanks ...

I have added a memalign since my last posting of this patch.

Details:

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-18 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,10 @@ 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 $(srcdir)/../../../../compile \
+	$(srcdir)/../../../../compile
 subdir = .
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \
@@ -87,49 +90,55 @@ 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-memcmp.$(OBJEXT) \
+	lib_a-iscanf.$(OBJEXT) lib_a-malignr.$(OBJEXT) \
+	lib_a-mallocr.$(OBJEXT) lib_a-memcmp.$(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-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 =
@@ -254,22 +263,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 memcmp.c memcpy.c memmove.c memset.c perror.c printf.S \
-	putc.c putchar.c puts.c remove.c rename.c rewind.c scanf.S \
+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 \
+	memcmp.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
+	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
@@ -431,6 +449,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
 
@@ -515,6 +539,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
 
@@ -563,6 +593,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-memcmp.o: memcmp.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memcmp.o `test -f 'memcmp.c' || echo '$(srcdir)/'`memcmp.c
 
@@ -611,6 +653,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
 
@@ -976,6 +1024,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 memcmp.c memcpy.c memmove.c memset.c perror.c printf.S \
-	putc.c putchar.c puts.c remove.c rename.c rewind.c scanf.S \
+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 \
+	memcmp.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
+	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 $@


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]