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