ppcrcd/yaboot: Makefile include/stdlib.h lib/malloc.c yaboot.c

sparky cvs at pld-linux.org
Mon Sep 19 17:18:56 CEST 2005


Author: sparky
Date: Mon Sep 19 17:18:49 2005
New Revision: 6400

Modified:
   ppcrcd/yaboot/Makefile
   ppcrcd/yaboot/include/stdlib.h
   ppcrcd/yaboot/lib/malloc.c
   ppcrcd/yaboot/yaboot.c
Log:
- much!!! better malloc functions (from prom-libc)


Modified: ppcrcd/yaboot/Makefile
==============================================================================
--- ppcrcd/yaboot/Makefile	(original)
+++ ppcrcd/yaboot/Makefile	Mon Sep 19 17:18:49 2005
@@ -6,7 +6,7 @@
 CONFIG_FS_XFS           :=      y
 CONFIG_FS_REISERFS      :=      y
 
-VERSION = 1.3.13-ppcrcd
+VERSION = 1.3.13-ppcrcd.2
 
 # Debug mode (spam/verbose)
 DEBUG = 0
@@ -15,11 +15,11 @@
 
 # Load the bootstrap at 2Mb
 TEXTADDR	= 0x200000
-# Malloc block at 3Mb -> 4.5Mb
+# Malloc block at 3Mb -> 4Mb
 MALLOCADDR	= 0x300000
-MALLOCSIZE	= 0x180000
-# gzMalloc block (4.5->5Mb)
-GZMALLOCADDR    = 0x480000
+MALLOCSIZE	= 0x100000
+# gzMalloc block (4->4.5Mb)
+GZMALLOCADDR    = 0x400000
 GZMALLOCSIZE    = 0x080000
 # Load kernel at 20Mb and ramdisk just after
 KERNELADDR	= 0x01400000
@@ -69,7 +69,7 @@
 
 all: yaboot strip
 
-yaboot: $(OBJS)
+yaboot: $(OBJS) $(LLIBS)
 	@echo "	[LD]		$@"
 	@$(LD) $(LFLAGS) $(OBJS) $(LLIBS) $(lgcc) -o $@
 	@chmod -x yaboot

Modified: ppcrcd/yaboot/include/stdlib.h
==============================================================================
--- ppcrcd/yaboot/include/stdlib.h	(original)
+++ ppcrcd/yaboot/include/stdlib.h	Mon Sep 19 17:18:49 2005
@@ -7,14 +7,15 @@
 
 #include "stdarg.h"
 
-extern void malloc_init(void *bottom, unsigned long size);
-extern void malloc_dispose(void);
+extern int __alloc_freelist_init(void);
+//extern void malloc_init(void *bottom, unsigned long size);
+//extern void malloc_dispose(void);
 
 extern void *malloc(unsigned int size);
 extern void *realloc(void *ptr, unsigned int size);
 extern void free (void *m);
-extern void mark (void **ptr);
-extern void release (void *ptr);
+//extern void mark (void **ptr);
+//extern void release (void *ptr);
 
 extern int sprintf(char * buf, const char *fmt, ...);
 extern int vsprintf(char *buf, const char *fmt, va_list args);

Modified: ppcrcd/yaboot/lib/malloc.c
==============================================================================
--- ppcrcd/yaboot/lib/malloc.c	(original)
+++ ppcrcd/yaboot/lib/malloc.c	Mon Sep 19 17:18:49 2005
@@ -23,9 +23,219 @@
 #include "stddef.h"
 #include "string.h"
 
+#define MALLOC_DEBUG 1
+
 /* Imported functions */
 extern void prom_printf (char *fmt, ...);
+extern void *prom_claim (void *virt, unsigned int size, unsigned int align);
+
+/*
+ * memory allocation routines from prom-libc
+ */
+
+void free(void *memory);
+
+/*** bits/malloc.h ***/
+struct __alloc_area
+{
+	struct __alloc_area *next;
+	unsigned int length;
+	long long foo;
+};
+
+/*** __freelist.c ***/
+/* the list of free areas */
+struct __alloc_area *__freelist = NULL;
+
+/*** __alloc_freelist_init.c ***/
+int __alloc_freelist_init(void)
+{
+     /* return if the freelist has already been set up. this will mean that
+      * one can call _init() to more than once without probs
+      */
+     if (__freelist)
+	  return 0;
+
+     /* assign an initial area */
+     __freelist = (struct __alloc_area *) prom_claim(
+	  (void *)MALLOCADDR, ((MALLOCSIZE / sizeof(struct __alloc_area))
+				* sizeof(struct __alloc_area)) , 0);
+     if ((void *)__freelist == (void *)-1)
+	  return 1;
+     __freelist->next = NULL;
+     __freelist->length = (MALLOCSIZE / sizeof(struct __alloc_area)) - 1;
+     return 0;
+}
+
+
+/*** malloc.c ***/
+void *malloc(unsigned int bytes)
+{
+     struct __alloc_area *previous;
+     struct __alloc_area *current;
+     unsigned int units;
+
+     /* __freelist is still NULL, set up the initial entry */
+     if (!__freelist)
+	  __alloc_freelist_init();
+
+     /* determine the number of __alloc_area sized blocks needed to hold
+      * the number of bytes requested. needs to be an even number, otherwise
+      * the following header struct might be mis-aligned
+      */
+     units = (bytes + sizeof(struct __alloc_area) - 1) /
+	  sizeof(struct __alloc_area);
+
+     previous = NULL;
+     for (current = __freelist; current; current = current->next) {
+	  if (units < current->length + 1) {
+	       /* make area smaller, to accommodate a new area of
+		* the required size, and its header
+		*/
+	       current->length -= units;
+	       current->length -= 1;
+
+	       /* move the pointer so that it points to the new area
+		* being set up
+		*/
+	       current += current->length + 1;
+	       current->length = units;
+
+	       /* return a pointer to the user that starts
+		* immediately after the area header
+		*/
+	       return (void *)(current + 1);
+			
+	  } else if (units == current->length) {
+	       /* current area is exactly the right size */
+
+	       /* unlink this area from the list */
+	       if (previous)
+		    previous->next = current->next;
+			
+	       return (void *)(current + 1);
+	  }
+	  previous = current;
+     }
+     return NULL;
+}
+
+/*** realloc.c ***/
+void *realloc(void *old, unsigned int size)
+{
+     struct __alloc_area *optr;
+     void *new;
+     unsigned int olen;
+
+     if (old && !size) {
+	  free(old);
+	  return NULL;
+     } else if (!old && !size)
+	  return NULL;
+
+     if (!(new = malloc(size)))
+	  return NULL;
+
+     if (old) {
+	  optr = (struct __alloc_area *)old;
+	  optr--;
+	  olen = (optr->length * sizeof(struct __alloc_area));
+	  memcpy(new, old, olen <= size ? olen : size);
+	  free(old);
+     }
+     return new;
+}
 
+/*** free.c ***/
+/* join sequential areas in freelist */
+static void __alloc_freelist_join(void)
+{
+     struct __alloc_area *previous, *current;
+
+     previous = NULL;
+
+     /* loop through areas in the freelist */
+     for (current = __freelist; current; current = current->next) {
+	  if (previous && previous + previous->length + 1 == current) {
+	       /* current area starts immediately after the previous
+		* one, join them
+		*/
+
+	       /* increase previous area's length to include the
+		* current area's header and length
+		*/
+	       previous->length++;
+	       previous->length += current->length;
+
+	       /* take the current entry out of the list */
+	       previous->next = current->next;
+	       current = previous;
+	  } else
+	       previous = current;
+     }
+}
+
+void free(void *memory)
+{
+     struct __alloc_area *free;
+     struct __alloc_area *before;
+     struct __alloc_area *current;
+
+#ifdef MALLOC_DEBUG
+     /* check that memory isn't a NULL pointer (possibly from a failed
+      * malloc). this check is nice, but not compulsory
+      */
+     if (!memory) {
+	  prom_printf("WARNING: attempt to free a NULL pointer\n");
+	  return;
+     }
+#endif /* MALLOC_DEBUG */
+
+     /* set free to point to the pointer supplied, move free one element so
+      * that it points to the actual header
+      */
+     free = (struct __alloc_area *)memory;
+     free--;
+
+#ifdef MALLOC_DEBUG
+     /* check that this pointer isn't already in the freelist, or a pointer
+      * to something that's inside something in the freelist. again, this
+      * check isn't essential for a non-broken program
+      */
+     for (current = __freelist; current; current = current->next)
+	  if (free >= current && free < current + current->length) {
+	       prom_printf("WARNING: memory area already in freelist\n");
+	       return;
+	  }
+#endif /* MALLOC_DEBUG */
+
+     /* free puts areas back in the freelist in order of the pointers, so
+      * that sequential areas can be joined later
+      */
+
+     /* try and find the area that immediately preceeds this one */
+     before = NULL;
+     for (current = __freelist; current && free > current; 
+	  current = current->next)
+	  before = current;
+
+     if (before) {
+	  /* put this area in just after the area before it */
+	  free->next = before->next;
+	  before->next = free;
+     } else {
+	  /* nothing before this area, place at beginning of freelist */
+	  free->next = __freelist;
+	  __freelist = free;
+     }
+
+     /* join any sequential areas */
+     __alloc_freelist_join();
+}
+
+
+
+#if 0 // replaced by new malloc
 static char *malloc_ptr = 0;
 static char *malloc_top = 0;
 static char *last_alloc = 0;
@@ -93,7 +303,12 @@
 	last_alloc = caddr;
     }
 }
+#endif
+
+
+
 
+#if 0 // not used
 void mark (void **ptr)
 {
     if (!malloc_ptr)
@@ -107,7 +322,9 @@
     	return;
     malloc_ptr = (char *) ptr;
 }
+#endif
 
+// Should not be here
 char *strdup(char const *str)
 {
     char *p = malloc(strlen(str) + 1);

Modified: ppcrcd/yaboot/yaboot.c
==============================================================================
--- ppcrcd/yaboot/yaboot.c	(original)
+++ ppcrcd/yaboot/yaboot.c	Mon Sep 19 17:18:49 2005
@@ -196,6 +196,7 @@
      /* Initialize OF interface */
      prom_init ((prom_entry) r5);
 	
+#if 0
      /* Allocate some memory for malloc'ator */
      malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
      if (malloc_base == (void *)-1) {
@@ -206,7 +207,14 @@
      malloc_init(malloc_base, MALLOCSIZE);
      DEBUG_F("Malloc buffer allocated at %p (%d bytes)\n",
 	     malloc_base, MALLOCSIZE);
+#endif
+	if ( __alloc_freelist_init() ) {
+		prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
+			MALLOCSIZE, MALLOCADDR);
+		return -1;
+	}
 		
+   	
      /* A few useless DEBUG_F's */
      DEBUG_F("reloc_offset :  %ld         (should be 0)\n", reloc_offset());
      DEBUG_F("test_bss     :  %d         (should be 0)\n", test_bss);
@@ -237,7 +245,7 @@
      result = yaboot_main();
 
      /* Get rid of malloc pool */
-     malloc_dispose();
+//     malloc_dispose();
      prom_release(malloc_base, MALLOCSIZE);
      DEBUG_F("Malloc buffer released. Exiting with code %d\n",
 	     result);



More information about the pld-cvs-commit mailing list