summaryrefslogtreecommitdiff
path: root/firmware/test/memory
diff options
context:
space:
mode:
authorAlan Korr <alkorr@rockbox.org>2002-04-15 23:19:10 +0000
committerAlan Korr <alkorr@rockbox.org>2002-04-15 23:19:10 +0000
commit27df7b0b96686771b9fafba33d0a97b4d77f6206 (patch)
tree638189ff3754910b98f4725167fe621c4c20436a /firmware/test/memory
parentf5747cf78a4506dca544fde5324fd020a988c73b (diff)
downloadrockbox-27df7b0b96686771b9fafba33d0a97b4d77f6206.zip
rockbox-27df7b0b96686771b9fafba33d0a97b4d77f6206.tar.gz
rockbox-27df7b0b96686771b9fafba33d0a97b4d77f6206.tar.bz2
rockbox-27df7b0b96686771b9fafba33d0a97b4d77f6206.tar.xz
*** empty log message ***
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@98 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/test/memory')
-rw-r--r--firmware/test/memory/config.h27
-rw-r--r--firmware/test/memory/defines.h39
-rw-r--r--firmware/test/memory/functions.h34
-rw-r--r--firmware/test/memory/inlines.h26
-rw-r--r--firmware/test/memory/makefile193
-rw-r--r--firmware/test/memory/memory-page.c434
-rw-r--r--firmware/test/memory/memory-slab.c463
-rw-r--r--firmware/test/memory/memory.h27
-rw-r--r--firmware/test/memory/return_values.h31
-rw-r--r--firmware/test/memory/test.l23
-rw-r--r--firmware/test/memory/test.y182
-rw-r--r--firmware/test/memory/types.h72
12 files changed, 1551 insertions, 0 deletions
diff --git a/firmware/test/memory/config.h b/firmware/test/memory/config.h
new file mode 100644
index 0000000..cb3b75f
--- /dev/null
+++ b/firmware/test/memory/config.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# error "This header file must be included ONLY from memory.h."
+#endif
+#ifndef __LIBRARY_MEMORY_CONFIG_H__
+# define __LIBRARY_MEMORY_CONFIG_H__
+# define PACKAGE_NAME "memory"
+# define PACKAGE_VERSION "0.1.0"
+# define MEMORY_PAGE_USE_SPLAY_TREE 1
+#endif \ No newline at end of file
diff --git a/firmware/test/memory/defines.h b/firmware/test/memory/defines.h
new file mode 100644
index 0000000..a6e48cc
--- /dev/null
+++ b/firmware/test/memory/defines.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# error "This header file must be included ONLY from memory.h."
+#endif
+#ifndef __LIBRARY_MEMORY_DEFINES_H__
+# define __LIBRARY_MEMORY_DEFINES_H__
+# ifndef MEMORY_PAGE_MINIMAL_ORDER
+# define MEMORY_PAGE_MINIMAL_ORDER (9) /* 512 bytes */
+# endif
+# ifndef MEMORY_PAGE_MAXIMAL_ORDER
+# define MEMORY_PAGE_MAXIMAL_ORDER (21) /* 2 Mbytes */
+# endif
+# ifndef MEMORY_PAGE_MINIMAL_SIZE
+# define MEMORY_PAGE_MINIMAL_SIZE (1 << MEMORY_PAGE_MINIMAL_ORDER)
+# endif
+# ifndef MEMORY_PAGE_MAXIMAL_SIZE
+# define MEMORY_PAGE_MAXIMAL_SIZE (1 << MEMORY_PAGE_MAXIMAL_ORDER)
+# endif
+# define MEMORY_TOTAL_PAGES (MEMORY_PAGE_MAXIMAL_SIZE / MEMORY_PAGE_MINIMAL_SIZE)
+# define MEMORY_TOTAL_BYTES (MEMORY_PAGE_MAXIMAL_SIZE)
+# define MEMORY_TOTAL_ORDERS (1 + MEMORY_PAGE_MAXIMAL_ORDER - MEMORY_PAGE_MINIMAL_ORDER)
+#endif \ No newline at end of file
diff --git a/firmware/test/memory/functions.h b/firmware/test/memory/functions.h
new file mode 100644
index 0000000..e0f6aea
--- /dev/null
+++ b/firmware/test/memory/functions.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# error "This header file must be included ONLY from memory.h."
+#endif
+# ifndef __LIBRARY_MEMORY_FUNCTIONS_H__
+# define __LIBRARY_MEMORY_FUNCTIONS_H__
+extern void memory_copy (void *target,void const *source,unsigned int count);
+extern void memory_set (void *target,int byte,unsigned int count);
+extern int memory_release_page (void *);
+extern void *memory_allocate_page (int);
+extern void memory_setup (void);
+# ifdef TEST
+void memory_spy_page (void *address);
+void memory_dump (int order);
+void memory_check (int order);
+# endif
+#endif
diff --git a/firmware/test/memory/inlines.h b/firmware/test/memory/inlines.h
new file mode 100644
index 0000000..dee78a6
--- /dev/null
+++ b/firmware/test/memory/inlines.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# error "This header file must be included ONLY from memory.h."
+#endif
+# ifndef __LIBRARY_MEMORY_INLINES_H__
+#define __LIBRARY_MEMORY_INLINES_H__
+
+
+#endif \ No newline at end of file
diff --git a/firmware/test/memory/makefile b/firmware/test/memory/makefile
new file mode 100644
index 0000000..2259cdf
--- /dev/null
+++ b/firmware/test/memory/makefile
@@ -0,0 +1,193 @@
+#############################################################################
+## __________ __ ___.
+## Open \______ \ ____ ____ | | _\_ |__ _______ ___
+## Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+## Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+## Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+## \/ \/ \/ \/ \/
+## Copyright Alan Korr, 2002. All rights reserved.
+##
+## Permission to use, copy, modify, and distribute this software for any
+## purpose is hereby granted without fee, provided that this copyright and
+## permissions notice appear in all copies and derivatives, and that no
+## charge may be made for the software and its documentation except to cover
+## cost of distribution.
+##
+## This software is provided "as is" without express or implied warranty.
+#############################################################################
+ARCH = test
+
+CC = gcc
+AS = as
+LD = ld
+AR = ar
+RL = ranlib
+OC = objcopy
+GZ = gzip -f
+
+PREFIX = ~/rockbox/$(ARCH)
+PACKAGE = memory
+VERSION = 0.1
+DEFINES = -DTEST
+
+#####################################################"
+# Compiler flags :
+
+CFLAGS = -g
+#CFLAGS += -save-temps
+CFLAGS += -Wall \
+ -W \
+ -Wshadow \
+ -Wpointer-arith \
+ -Waggregate-return \
+ -Wstrict-prototypes \
+ -Wredundant-decls \
+ -Winline \
+ -Wmissing-prototypes \
+ -Werror \
+ -Wsign-compare \
+ -Wmissing-declarations \
+ -Wmissing-noreturns \
+ -Wnested-externs
+CFLAGS += -pipe -O3
+CFLAGS += -fomit-frame-pointer \
+ -fschedule-insns
+CFLAGS += $(EXTRA_CFLAGS)
+CFLAGS += $(DEFINES)
+
+#######################################################################
+## PLEASE CONSIDER THERE IS NOTHING TO CHANGE IN THE FOLLOWING LINES
+## SINCE THERE ARE COMMON FOR ALL LIBRARY
+##
+
+.SUFFIXES : .o .c .s
+
+INCLUDES = -I. \
+ -I$(PREFIX)/headers
+
+STATIC_LIBRARY_PATH = $(PREFIX)/libraries
+
+LIBRARY = lib$(PACKAGE).a
+
+#######################################################################
+## PLEASE CHANGE ONLY THE FOLLOWING LINES
+##
+
+LIBS =
+
+HEADERS = $(PACKAGE).h \
+ config.h \
+ defines.h \
+ types.h \
+ return_values.h \
+ inlines.h \
+ functions.h
+
+SOURCES = $(PACKAGE)-page.c \
+ $(PACKAGE)-slab.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DEPENDENCIES = $(SOURCES:.c=.d)
+
+HEADER_PATH = $(PREFIX)/headers/$(PACKAGE)/.
+
+#######################################################################
+## PLEASE CONSIDER THERE IS NOTHING TO CHANGE IN THE FOLLOWING LINES
+## SINCE THERE ARE COMMON FOR ALL LIBRARY
+##
+
+%.o: %.c
+ @echo "Compiling" $<...
+ @$(CC) -o $(@) $(CFLAGS) $(INCLUDES) -c $<
+ @$(CC) -M $< $(CFLAGS) $(INCLUDES) > $(*F).d
+
+%.o: %.s
+ @echo "Assembling" $<...
+ @$(CC) -o $(@) $(CFLAGS) $(INCLUDES) -c $<
+ @$(CC) -M $< $(CFLAGS) $(INCLUDES) > $(*F).d
+
+.PHONY: splash all clean backup restore dist install
+
+all: splash $(LIBRARY) test
+
+splash:
+ @echo "<<< " $(PACKAGE) "-" $(VERSION) ">>>"
+
+####################################################
+# LIBRAY PART :
+
+$(LIBRARY): $(OBJECTS)
+ @echo "Creating library" $(LIBRARY)...
+ @$(AR) cru $(@) $(OBJECTS)
+ @$(RL) $(@)
+
+
+####################################################
+# TEST PART :
+
+test: test.tab.o test.lex.o $(LIBRARY)
+ @echo "Creating executable" $@...
+ @$(CC) $(INCLUDES) -g -o $(@) $(+) -lfl -lreadline
+
+test.tab.o: test.tab.c
+ @echo "Compiling" $<...
+ @$(CC) -I. -g -o $(@) -O3 -fomit-frame-pointer -c test.tab.c
+
+test.lex.o: test.lex.c
+ @echo "Compiling" $<...
+ @$(CC) -I. -g -o $(@) -O3 -fomit-frame-pointer -c test.lex.c
+
+test.tab.h: test.tab.c
+
+test.lex.c: test.l test.tab.h
+ @echo "Flex:" $<
+ @flex -otest.lex.c test.l
+
+test.tab.c: test.y
+ @echo "Bison:" $<
+ @bison -d test.y
+
+
+####################################################
+# MISCELLANOUS PART :
+
+clean:
+ @rm -f $(LIBRARY)
+ @rm -f $(OBJECTS) test.lex.o test.tab.o
+ @rm -f $(DEPENDENCIES)
+ @rm -f *~ test test.exe
+ @rm -f test.tab.h test.tab.c test.lex.c
+ @rm -f core
+
+backup:
+ @mkdir -p ./backup
+ @cp -f makefile ./backup
+ @cp -f test.l ./backup
+ @cp -f test.y ./backup
+ @cp -f $(SOURCES:.c=.txt) ./backup
+ @for header in $(HEADERS) ; do cp -f $$header ./backup ; done
+ @for source in $(SOURCES) ; do cp -f $$source ./backup ; done
+
+restore:
+ @cp -f ./backup/makefile .
+ @cp -f ./backup/test.l .
+ @cp -f ./backup/test.y .
+ @cp -f ./backup/$(SOURCES:.c=.txt)
+ @for header in $(HEADERS) ; do cp -f ./backup/$$header . ; done
+ @for source in $(SOURCES) ; do cp -f ./backup/$$source . ; done
+
+dist: backup
+ @mv backup $(PACKAGE)
+ @tar czvf $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)/*
+ @rm -f $(PACKAGE)/*
+ @rmdir $(PACKAGE)
+
+install: all
+ @mkdir -p $(PREFIX)/libraries
+ @cp $(LIBRARY) $(PREFIX)/libraries
+ @mkdir -p $(PREFIX)/headers/$(PACKAGE)
+ @for header in $(HEADERS) ; do cp $$header $(PREFIX)/headers/$(PACKAGE) ; done
+
+-include $(DEPENDENCIES)
+
diff --git a/firmware/test/memory/memory-page.c b/firmware/test/memory/memory-page.c
new file mode 100644
index 0000000..5ec46ec
--- /dev/null
+++ b/firmware/test/memory/memory-page.c
@@ -0,0 +1,434 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <memory.h>
+
+#define LESS -1
+#define MORE +1
+
+#ifdef TEST
+
+struct memory_free_page free_page[MEMORY_TOTAL_PAGES];
+
+static inline unsigned int get_offset (int order)
+ {
+ return (2 << order);
+ }
+
+// IA32 has no problem with shift operation
+static inline unsigned int get_size (int order)
+ {
+ return (MEMORY_PAGE_MINIMAL_SIZE << order);
+ }
+
+// Arghhhh ! I cannot align 'free_page' on 512-byte boundary (max is 16-byte for Cygwin)
+static inline struct memory_free_page *get_neighbour (struct memory_free_page *node,unsigned int size)
+ {
+ return ((struct memory_free_page *)((unsigned)free_page + (((unsigned)node - (unsigned)free_page) ^ size)));
+ }
+
+#else
+
+extern struct memory_free_page free_page[MEMORY_TOTAL_PAGES] asm("dram");
+
+static inline unsigned int get_offset (int order)
+ {
+ static unsigned short offset [MEMORY_TOTAL_ORDERS] =
+ { 2,4,8,16,32,64,128,256,512,1024,2048,4096,8192 };
+ return offset[order];
+ }
+
+// SH1 has very poor shift instructions (only <<1,>>1,<<2,>>2,<<8,>>8,<<16 and >>16).
+// so we should use a lookup table to speedup.
+static inline unsigned int get_size (int order)
+ {
+ return (get_offset (order))<<8;
+ }
+
+static inline struct memory_free_page *get_neighbour (struct memory_free_page *node,unsigned int size)
+ {
+ return ((struct memory_free_page *)((unsigned)node ^ size));
+ }
+
+#endif
+
+static char free_page_order[MEMORY_TOTAL_PAGES];
+static struct memory_free_page *free_page_list[MEMORY_TOTAL_ORDERS];
+
+static inline int get_order (struct memory_free_page *node)
+ {
+ return free_page_order[node - free_page];
+ }
+static inline void set_order (struct memory_free_page *node,int order)
+ {
+ free_page_order[node - free_page] = order;
+ }
+
+#if MEMORY_PAGE_USE_SPLAY_TREE
+
+# include <stdio.h>
+
+static struct memory_free_page *splay_page (struct memory_free_page *root,struct memory_free_page *node)
+ {
+ struct memory_free_page *down;
+ struct memory_free_page *less;
+ struct memory_free_page *more;
+ struct memory_free_page head;
+ head.less =
+ head.more = 0;
+ less =
+ more = &head;
+ while (1)
+ {
+ if (node < root)
+ {
+ if ((down = root->less))
+ {
+ if (node < down)
+ {
+ root->less = down->more;
+ down->more = root;
+ root = down;
+ if (!root->less)
+ break;
+ }
+ more->less = root;
+ more = root;
+ root = root->less;
+ continue;
+ }
+ break;
+ }
+ if (root < node)
+ {
+ if ((down = root->more))
+ {
+ if (root < node)
+ {
+ root->more = down->less;
+ down->less = root;
+ root = down;
+ if (!root->more)
+ break;
+ }
+ less->more = root;
+ less = root;
+ root = root->more;
+ continue;
+ }
+ }
+ break;
+ }
+ less->more = root->less;
+ more->less = root->more;
+ root->less = head.more;
+ root->more = head.less;
+ return root;
+ }
+
+static inline void insert_page (int order,struct memory_free_page *node)
+ {
+ struct memory_free_page *root = free_page_list[order];
+ if (!root)
+ {
+ node->less =
+ node->more = 0;
+ }
+ else if (node < (root = splay_page (root,node)))
+ {
+ node->less = root->less;
+ node->more = root;
+ root->less = 0;
+ }
+ else if (node > root)
+ {
+ node->less = root;
+ node->more = root->more;
+ node->more = 0;
+ }
+ free_page_list[order] = node;
+ set_order (node,order);
+ return;
+ }
+
+static inline struct memory_free_page *pop_page (int order,int want)
+ {
+ struct memory_free_page *root = free_page_list[order];
+ if (root)
+ {
+ root = splay_page (root,free_page);
+ free_page_list[order] = root->more;
+ set_order (root,~want);
+ }
+ return root;
+ }
+
+static inline void remove_page (int order,struct memory_free_page *node)
+ {
+ struct memory_free_page *root = free_page_list[order];
+ root = splay_page (root,node);
+ if (root->less)
+ {
+ node = splay_page (root->less,node);
+ node->more = root->more;
+ }
+ else
+ node = root->more;
+ free_page_list[order] = node;
+ }
+
+#else
+
+static inline void insert_page (int order,struct memory_free_page *node)
+ {
+ struct memory_free_page *head = free_page_list[order];
+ node->less = 0;
+ node->more = head;
+ if (head)
+ head->less = node;
+ free_page_list[order] = node;
+ set_order (node,order);
+ }
+
+static inline struct memory_free_page *pop_page (int order,int want)
+ {
+ struct memory_free_page *node = free_page_list[order];
+ if (node)
+ {
+ free_page_list[order] = node->more;
+ if (node->more)
+ node->more->less = 0;
+ set_order (node,~want);
+ }
+ return node;
+ }
+
+static inline void remove_page (int order,struct memory_free_page *node)
+ {
+ if (node->less)
+ node->less->more = node->more;
+ else
+ free_page_list[order] = node->more;
+ if (node->more)
+ node->more->less = node->less;
+ }
+
+#endif
+
+static inline void push_page (int order,struct memory_free_page *node)
+ {
+ node->less = 0;
+ node->more = 0;
+ free_page_list[order] = node;
+ set_order (node,order);
+ }
+
+static struct memory_free_page *allocate_page (unsigned int size,int order)
+ {
+ struct memory_free_page *node;
+ int min = order;
+ while ((unsigned)order <= (MEMORY_TOTAL_ORDERS - 1))
+ // order is valid ?
+ {
+ if (!(node = pop_page (order,min)))
+ // no free page of this order ?
+ {
+ ++order; size <<= 1;
+ continue;
+ }
+ while (order > min)
+ // split our larger page in smaller pages
+ {
+ --order; size >>= 1;
+ push_page (order,(struct memory_free_page *)((unsigned int)node + size));
+ }
+ return node;
+ }
+ return MEMORY_RETURN_FAILURE;
+ }
+
+static inline void release_page (struct memory_free_page *node,unsigned int size,int order)
+ {
+ struct memory_free_page *neighbour;
+ while ((order <= (MEMORY_TOTAL_ORDERS - 1)) &&
+ ((neighbour = get_neighbour (node,size)),
+ (get_order (neighbour) == order)))
+ // merge our released page with its contiguous page into a larger page
+ {
+ remove_page (order,neighbour);
+ ++order; size <<= 1;
+ if (neighbour < node)
+ node = neighbour;
+ }
+ insert_page (order,node);
+ }
+
+
+/*****************************************************************************/
+/* PUBLIC FUNCTIONS */
+/*****************************************************************************/
+
+void *memory_allocate_page (int order)
+ {
+ if (order < 0)
+ return MEMORY_RETURN_FAILURE;
+ return allocate_page (get_size (order),order);
+ }
+
+// release a page :
+// when called, 'address' MUST be a valid address pointing
+// to &dram[i], where i ranges from 0 to MEMORY_TOTAL_PAGES - 1.
+// FAILURE if block is already freed.
+int memory_release_page (void *address)
+ {
+ struct memory_free_page *node = (struct memory_free_page *)address;
+ int order = ~get_order (node);
+ if (order < 0)
+ return MEMORY_RETURN_FAILURE;
+ release_page (node,get_size (order),order);
+ return MEMORY_RETURN_SUCCESS;
+ }
+
+/* NOT VERY OPTIMIZED AT ALL BUT WE WILL DO IT WHEN PRIORITY COMES */
+void memory_copy (void *target,void const *source,unsigned int count)
+ {
+ while (count--)
+ *((char *)target)++ = *((char const *)source)++;
+ }
+
+/* NOT VERY OPTIMIZED AT ALL BUT WE WILL DO IT WHEN PRIORITY COMES */
+void memory_set (void *target,int byte,unsigned int count)
+ {
+ while (count--)
+ *((char *)target)++ = (char)byte;
+ }
+
+void memory_setup (void)
+ {
+#if 0
+ memory_set (free_page,0,MEMORY_TOTAL_BYTES);
+ memory_set (free_page_list,0,MEMORY_TOTAL_ORDERS *sizeof (struct memory_free_page *));
+#endif
+ memory_set (free_page_order + 1,(MEMORY_TOTAL_ORDERS - 1),MEMORY_TOTAL_PAGES);
+ free_page_order[0] = MEMORY_TOTAL_ORDERS - 1;
+ free_page_list[MEMORY_TOTAL_ORDERS - 1] = free_page;
+ }
+
+#ifdef TEST
+# include <stdio.h>
+# include <stdlib.h>
+# if MEMORY_PAGE_USE_SPLAY_TREE
+
+static void dump_splay_node (struct memory_free_page *node,int level)
+ {
+ if (!node)
+ return;
+ dump_splay_node (node->less,level+1);
+ printf ("\n%*s[%d-%d]",level,"",(node - free_page),(node - free_page) + (1 << get_order (node)) - 1);
+ dump_splay_node (node->more,level+1);
+ }
+
+static void dump_splay_tree (struct memory_free_page *root)
+ {
+ dump_splay_node (root,2); fflush (stdout);
+ }
+
+# endif
+
+void memory_spy_page (void *address)
+ {
+ struct memory_free_page *node = (struct memory_free_page *)address;
+ int order,used;
+ if (node)
+ {
+ order = get_order (node);
+ used = order < 0;
+ if (used)
+ order = ~order;
+ printf("\n(%s,%2d,%7d)",(used ? "used" : "free"),order,get_size (order));
+ }
+ }
+
+void memory_dump (int order)
+ {
+ struct memory_free_page *node = free_page_list[order];
+ printf("\n(%s,%2d,%7d)",node ? "free" : "none",order,get_size (order));
+# if MEMORY_PAGE_USE_SPLAY_TREE
+ dump_splay_tree (node);
+# else
+ while (node)
+ {
+ printf("[%d-%d]",(node - free_page),(node - free_page) + (1<<order) - 1);
+ node = node->more;
+ }
+# endif
+
+ }
+
+void memory_check (int order)
+ {
+ struct memory_free_page *node[4096],*swap;
+ unsigned int i = 0,j = 0;
+ while (i <= 12)
+ memory_dump (i++);
+ i = 0;
+ printf ("\nallocating...\n");
+ while (order >= 0)
+ {
+ j = order;
+ while ((swap = memory_allocate_page (j)))
+ {
+ node[i++] = swap;
+ printf("[%d-%d]",(swap - free_page),(swap - free_page) + ((1 << j)-1));
+ for (j += (rand () & 15); j > (unsigned int)order; j -= order);
+ }
+ --order;
+ }
+ node[i] = 0;
+ while (j <= 12)
+ memory_dump (j++);
+ j = 0;
+ printf ("\nreleasing...");
+ --i;
+ while (i > 0)
+ {
+ unsigned int k = 0;
+ printf ("\n");
+ swap = node[k++];
+#if 0
+ while (swap)
+ {
+ printf("[%d-%d]",(swap - free_page),(swap - free_page) + ((1 << ~get_order (swap))-1));
+ swap = node[k++];
+ }
+#endif
+ for (j += 1 + (rand () & 15); j >= i; j -= i);
+ swap = node[j];
+ node[j] = node[i];
+ memory_release_page (swap);
+ node[i] = 0;
+ --i;
+ }
+ memory_release_page (node[0]);
+ i = 0;
+ while (i <= 12)
+ memory_dump (i++);
+ printf("\n\n%s !",(get_order (free_page) == 12) ? "SUCCESS" : "FAILURE");
+ }
+
+#endif
diff --git a/firmware/test/memory/memory-slab.c b/firmware/test/memory/memory-slab.c
new file mode 100644
index 0000000..289818b
--- /dev/null
+++ b/firmware/test/memory/memory-slab.c
@@ -0,0 +1,463 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#if 0
+
+#include <memory.h>
+
+static struct memory_cache *free_block_cache[MEMORY_PAGE_MINIMAL_SIZE - ];
+static struct memory_cache *cache_list;
+
+static inline int get_order (unsigned size)
+ {
+ int order = 0;
+ size = (size + sizeof(struct memory_free_block) - 1) & - sizeof(struct memory_free_block);
+ while (size > 0)
+ {
+ ++order; size <<= 1;
+ }
+ return order;
+ }
+
+static inline struct memory_slab *get_slab (struct memory_cache *cache,void *address)
+ {
+#ifdef TEST
+ return (struct memory_slab *)((((unsigned)address + cache->page_size) & -cache->page_size) - sizeof (struct memory_slab));
+#else
+ return (struct memory_slab *)((free_page + (((unsigned)address - free_page + cache->page_size) & -cache->page_size) - sizeof (struct memory_slab)));
+#endif
+ }
+
+static struct memory_cache *splay_cache (struct memory_cache *root,unsigned int left)
+ {
+ struct memory_cache *down;
+ struct memory_cache *less;
+ struct memory_cache *more;
+ struct memory_cache head;
+ head.less =
+ head.more = 0;
+ less =
+ more = &head;
+ while (1)
+ {
+ if (left < root->left)
+ {
+ if ((down = root->less))
+ {
+ if (left < down->left)
+ {
+ root->less = down->more;
+ down->more = root;
+ root = down;
+ if (!root->less)
+ break;
+ }
+ more->less = root;
+ more = root;
+ root = root->less;
+ continue;
+ }
+ break;
+ }
+ if (root->left < left)
+ {
+ if ((down = root->more))
+ {
+ if (root->left < left)
+ {
+ root->more = down->less;
+ down->less = root;
+ root = down;
+ if (!root->more)
+ break;
+ }
+ less->more = root;
+ less = root;
+ root = root->more;
+ continue;
+ }
+ }
+ break;
+ }
+ less->more = root->less;
+ more->less = root->more;
+ root->less = head.more;
+ root->more = head.less;
+ return root;
+ }
+
+static inline struct memory_cache *insert_cache (struct memory_cache *root,struct memory_cache *node)
+ {
+ node->less =
+ node->more =
+ node->same = 0;
+ if (root)
+ {
+ if (node->left == ((root = splay_cache (root,node))->left))
+ {
+ node->less = root.less;
+ node->more = root.more;
+ node->same = root;
+ root->less = node;
+ }
+ else if (node < root)
+ {
+ node->less = root->less;
+ node->more = root;
+ root->less = 0;
+ }
+ else
+ {
+ node->less = root;
+ node->more = root->more;
+ node->more = 0;
+ }
+ }
+ return node;
+ }
+
+static inline struct memory_cache *remove_cache (struct memory_cache *root,struct memory_cache *node)
+ {
+ if (root)
+ {
+ root = splay_cache (root,node);
+ if (root != node)
+ {
+ node->less->same = node->same;
+ if (node->same)
+ node->same->less = node->less;
+ return root;
+ }
+ if (root->less)
+ {
+ node = splay_page (root->less,node);
+ node->more = root->more;
+ }
+ else
+ node = root->more;
+ }
+ return root;
+ }
+
+static inline struct memory_cache *move_cache (struct memory_cache *root,struct memory_cache *node,int delta)
+ {
+ if ((root = remove_cache (root,node)))
+ {
+ node->left += delta;
+ root = insert_cache (root,node);
+ }
+ return root;
+ }
+
+static inline struct memory_slab *push_slab (struct memory_cache *head,struct memory_cache *node)
+ {
+ node->less = head;
+ if (head)
+ {
+ node->more = head->more;
+ head->more = node;
+ }
+ else
+ node->more = 0;
+ return node;
+ }
+
+static inline struct memory_slab *pop_slab (struct memory_cache *head,struct memory_cache *node)
+ {
+ if (head)
+ head->more = node->more;
+ return node->more;
+ }
+
+static inline struct memory_slab *move_slab (struct memory_slab **from,struct memory_slab **to)
+ {
+ struct memory_slab *head = *from;
+ *from = (*from)->more;
+ if (*from)
+ (*from)->less = head->less;
+ head->less = 0;
+ head->more = (*to);
+ if (*to)
+ (*to)->prev = head;
+ *to = head;
+ return head;
+ }
+
+
+/*****************************************************************************/
+/* PUBLIC FUNCTIONS */
+/*****************************************************************************/
+
+///////////////////////////////////////////////////////////////////////////////
+// MEMORY CACHE :
+/////////////////
+//
+// - memory_grow_cache : allocate a new slab for a cache
+// - memory_shrink_cache : release free slabs from a cache
+// - memory_create_cache : create a new cache of size-fixed blocks
+// - memory_destroy_cache : destroy the cache and release all the slabs
+// - memory_cache_allocate : allocate a block from the cache
+// - memory_cache_release : release a block in the cache
+//
+
+struct memory_slab *memory_grow_cache (struct memory_cache *cache)
+ {
+ struct memory_slab *slab;
+ unsigned int page;
+ if (cache)
+ {
+ page = (unsigned int)memory_allocate_page (cache->page_order);
+ if (page)
+ {
+ struct memory_free_block *block,**link;
+ slab = (struct memory_slab *)(page + cache->page_size - sizeof (struct memory_slab));
+ slab->free = 0;
+ slab->left = 0;
+ link = &slab->free;
+ for ((unsigned int)block = page;
+ (unsigned int)block + cache->size < (unsigned int)slab;
+ (unsigned int)block += cache->size)
+ {
+ *link = block;
+ link = &block->link;
+ ++slab->free;
+ }
+ *link = 0;
+ cache->blocks_per_slab = slab->free;
+ cache->reap = push_slab (cache->reap,slab);
+ cache_list = move_cache (cache_list,cache,+1);
+ return slab;
+ }
+ }
+ return MEMORY_RETURN_FAILURE;
+ }
+
+static int memory_shrink_cache (struct memory_cache *cache,int all,int move)
+ {
+ struct memory_slab *slab;
+ unsigned int slabs = 0;
+ if (cache)
+ {
+ while ((slab = cache->reap))
+ {
+ ++slabs;
+ cache->reap = pop_slab (cache->reap,slab);
+ memory_release_page ((void *)slab);
+ if (all)
+ continue;
+ if (move)
+ cache_list = move_cache (cache_list,cache,-slabs);
+ return MEMORY_RETURN_SUCCESS;
+ }
+ }
+ return MEMORY_RETURN_FAILURE;
+ }
+
+int memory_shrink_cache (struct memory_cache *cache,int all)
+ {
+ return shrink_cache (cache,all,1 /* move cache in cache_list */);
+ }
+
+struct memory_cache *memory_create_cache (unsigned int size,int align,int flags)
+ {
+ struct memory_cache *cache;
+ unsigned int waste = 0,blocks_per_page;
+ int page_order;
+ unsigned int page_size;
+ unsigned int original_size = size;
+
+ // Align size on 'align' bytes ('align' should equal 1<<n)
+ // if 'align' is inferior to 4, 32-bit word alignment is done by default.
+ size = (align > 4) ? ((size + align - 1) & -align) : ((size + sizeof (int) - 1) & -sizeof (int));
+ if (!(cache = memory_cache_allocate (&cache_cache))
+ return MEMORY_RETURN_FAILURE;
+
+ cache->flags =
+ cache->left = 0;
+
+ cache->used =
+ cache->free =
+ cache->reap = 0;
+
+ cache->original_size = original_size;
+ cache->size = size;
+
+ page_size = 0;
+ page_order = MEMORY_PAGE_MINIMAL_SIZE;;
+
+ // Trying to determine what is the best number of pages per slab
+ for (;; ++order,(page_size <<= 1))
+ {
+ if (page_order >= MEMORY_MAXIMUM_PAGE_ORDER_PER_SLAB)
+ {
+ memory_cache_release (&cache_cache,cache);
+ return MEMORY_RETURN_FAILURE;
+ }
+
+ waste = page_size;
+ waste -= sizeof (struct memory_slab);
+
+ blocks_per_slab = waste / size;
+ waste -= block_per_slab * size;
+
+ if (blocks_per_slab < MEMORY_MINIMUM_BLOCKS_PER_SLAB)
+ {
+ ++page_order; page_size <<= 1;
+ continue;
+ }
+
+ // below 3% of lost space is correct
+ if ((waste << 16) / page_size) < 1967)
+ break;
+ ++page_order; page_size <<= 1;
+ }
+
+ cache->page_size = page_size;
+ cache->page_order = page_order;
+
+ cache_list = insert_cache (cache_list,cache);
+
+ return cache;
+ }
+
+int memory_destroy_cache (struct memory_cache *cache)
+ {
+ if (cache)
+ {
+ cache_list = remove_cache (cache_list,cache);
+ if (shrink_cache (cache,1 /* release all free slabs */,0 /* don't move in cache_list */))
+ return memory_cache_release (&cache_cache,cache);
+ }
+ return MEMORY_RETURN_FAILURE;
+ }
+
+void *memory_cache_allocate (struct memory_cache *cache)
+ {
+ if (cache)
+ {
+ do
+ {
+ struct memory_slab *slab;
+ if ((slab = cache->free))
+ {
+ if (slab->left > 0)
+ {
+ok: struct memory_free_block *block = slab->free;
+ slab->free = block->link;
+ if (--slab->left == 0)
+ move_slab (&cache->free,&cache->used);
+ return block;
+ }
+ }
+ if (cache->reap)
+ {
+ slab = move_slab (&cache->reap,&cache->free);
+ cache_list = move_cache (cache_list,cache,-1);
+ goto ok;
+ }
+ }
+ while (grow_cache (cache));
+ }
+ return MEMORY_RETURN_FAILURE;
+ }
+
+int memory_cache_release (struct memory_cache *cache,void *address)
+ {
+ struct memory_slab *slab = get_slab (cache,address);
+ slab->free = (struct memory_free_block *)address;
+ if (slab->left++ == 0)
+ move_slab (&cache->used,&cache->free);
+ else if (slab->left == cache->elements_per_slab)
+ {
+ move_slab (&cache->free,&cache->reap);
+ cache_list = move_cache (cache_list,cache,+1);
+ }
+ return MEMORY_RETURN_SUCCESS;
+ }
+
+
+///////////////////////////////////////////////////////////////////////////////
+// MEMORY BLOCK :
+/////////////////
+//
+// - memory_allocate_small_block : allocate a small block (no page)
+// - memory_release_small_block : release a small block (no page)
+// - memory_allocate_block : allocate a block (or a page)
+// - memory_release_block : release a block (or a page)
+//
+
+static inline void *allocate_small_block (int order)
+ {
+ struct memory_cache *cache = free_block_cache[order];
+ do
+ {
+ if (cache)
+ return memory_cache_allocate (cache);
+ }
+ while ((free_block_cache[order] = cache = memory_create_cache (size,0,0)));
+ return MEMORY_RETURN_FAILURE;
+ }
+
+void *memory_allocate_small_block (int order)
+ {
+ if (order < MEMORY_PAGE_MINIMAL_ORDER)
+ return allocate_small_block (order)
+ return MEMORY_RETURN_FAILURE;
+ }
+
+static inline int release_small_block (int order,void *address)
+ {
+ struct memory_cache *cache = free_block_cache[order];
+ if (cache)
+ return memory_cache_release (cache,address);
+ return MEMORY_RETURN_FAILURE;
+ }
+
+int memory_release_small_block (int order,void *address)
+ {
+ if (order < MEMORY_PAGE_MINIMAL_ORDER)
+ return memory_release_small_block (order,address);
+ return memory_release_page (address);
+ }
+
+void *memory_allocate_block (unsigned int size)
+ {
+ size += sizeof (int *);
+ int order = get_order (size);
+ if (size < MEMORY_PAGE_MINIMAL_SIZE)
+ {
+ int *block = (int *)allocate_block (order);
+ *block = order;
+ return block;
+ }
+ if (size < MEMORY_PAGE_MAXIMAL_SIZE)
+ return memory_allocate_page (order);
+ return MEMORY_RETURN_FAILURE;
+ }
+
+int memory_release_block (void *address)
+ {
+ int order = *((int *)address);
+ if (order < MEMORY_PAGE_MINIMAL_ORDER)
+ return release_block (order);
+ if (order < MEMORY_PAGE_MAXIMAL_ORDER)
+ return memory_release_page (address);
+ return MEMORY_RETURN_FAILURE;
+ }
+
+#endif \ No newline at end of file
diff --git a/firmware/test/memory/memory.h b/firmware/test/memory/memory.h
new file mode 100644
index 0000000..881cb50
--- /dev/null
+++ b/firmware/test/memory/memory.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# define __LIBRARY_MEMORY_H__
+# include <config.h>
+# include <defines.h>
+# include <types.h>
+# include <return_values.h>
+# include <inlines.h>
+# include <functions.h>
+#endif
diff --git a/firmware/test/memory/return_values.h b/firmware/test/memory/return_values.h
new file mode 100644
index 0000000..4546806
--- /dev/null
+++ b/firmware/test/memory/return_values.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+# error "This header file must be included ONLY from memory.h."
+#endif
+# ifndef __LIBRARY_MEMORY_RETURN_VALUES_H__
+#define __LIBRARY_MEMORY_RETURN_VALUES_H__
+
+enum
+ {
+ MEMORY_RETURN_SUCCESS = 1,
+ MEMORY_RETURN_FAILURE = 0
+ };
+
+#endif \ No newline at end of file
diff --git a/firmware/test/memory/test.l b/firmware/test/memory/test.l
new file mode 100644
index 0000000..7b938e9
--- /dev/null
+++ b/firmware/test/memory/test.l
@@ -0,0 +1,23 @@
+%{
+#include "test.tab.h"
+#define YY_INPUT(buf,result,max_size) \
+ result = read_input (buf,max_size);
+%}
+
+%s GETNUMBER
+
+%%
+
+<GETNUMBER>[0-9]+ { yylval = atoi(yytext); return NUMBER;}
+
+<INITIAL>"a"|"allocate" { BEGIN GETNUMBER; return ALLOCATE; }
+<INITIAL>"r"|"release" { BEGIN GETNUMBER; return RELEASE; }
+<INITIAL>"s"|"spy" { BEGIN GETNUMBER; return SPY; }
+<INITIAL>"c"|"check" { BEGIN GETNUMBER; return CHECK; }
+<INITIAL>"i"|"init" { return INIT; }
+<INITIAL>"d"|"dump" { return DUMP; }
+<INITIAL>"q"|"quit" { return QUIT; }
+[ \t] ;
+\n|. { BEGIN 0; return yytext[0]; }
+%%
+
diff --git a/firmware/test/memory/test.y b/firmware/test/memory/test.y
new file mode 100644
index 0000000..1c368a1
--- /dev/null
+++ b/firmware/test/memory/test.y
@@ -0,0 +1,182 @@
+%{
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+void allocate (int);
+void release (int);
+void spy (int);
+void dump (void);
+void prompt (void);
+%}
+
+%token NUMBER
+%token ALLOCATE
+%token RELEASE
+%token DUMP
+%token SPY
+%token CHECK
+%token INIT
+%token QUIT
+
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+
+%%
+commands
+ : command ';'
+ { }
+ | commands command ';'
+ { }
+ | error ';'
+ { yyerrok; }
+ ;
+
+command
+ : allocate
+ | release
+ | spy
+ | check
+ | INIT
+ { memory_setup (); }
+ | DUMP
+ { dump (); }
+ | QUIT
+ { return 0; }
+ ;
+
+allocate
+ : ALLOCATE expression
+ { allocate (yylval); }
+ ;
+
+release
+ : RELEASE expression
+ { release (yylval); }
+ ;
+
+spy
+ : SPY expression
+ { spy (yylval); }
+ ;
+
+check
+ : CHECK expression
+ { memory_check (yylval); }
+ ;
+
+expression
+ : expression '+' expression
+ { $$ = $1 + $3; }
+ | expression '-' expression
+ { $$ = $1 - $3; }
+ | expression '*' expression
+ { $$ = $1 * $3; }
+ | expression '/' expression
+ {
+ if($3 == 0)
+ yyerror("divide by zero");
+ else
+ $$ = $1 / $3;
+ }
+ | '-' expression %prec UMINUS
+ {
+ $$ = -$2;
+ }
+ | '(' expression ')'
+ {
+ $$ = $2;
+ }
+ | NUMBER
+ {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+int yyerror(char *s)
+ {
+ fprintf(stderr,"\nBad command");
+ return 1;
+ }
+
+void prompt (void)
+ {
+ printf("\n>"); fflush (stdout);
+ }
+
+void allocate (int order)
+ {
+ extern char free_page[0];
+ void *address;
+ printf("\nallocating a page of %d bytes...",512<<order);
+ if ((unsigned)order > 21)
+ printf (" bad order !");
+ else if ((address = memory_allocate_page (order)))
+ printf (" page #%d allocated !",((char *)address - free_page) >> 9);
+ else
+ printf (" cannot allocate a page !");
+ }
+
+void release (int page)
+ {
+ extern char free_page[0];
+ void *address = (void *)(free_page + (page << 9));
+ printf("\nreleasing page #%d...",page);
+ if ((unsigned)page >= (2*1024*1024/512))
+ printf (" bad page number !");
+ else if (memory_release_page (address))
+ printf (" page #%d released !",page);
+ else
+ printf (" cannot release this page !");
+ }
+
+void spy (int page)
+ {
+ extern char free_page[0];
+ void *address = (void *)(free_page + (page << 9));
+ printf("\nspying page #%d...",page);
+ if ((unsigned)page >= (2*1024*1024/512))
+ printf (" bad page number !");
+ else
+ memory_spy_page (address);
+ }
+
+void dump (void)
+ {
+ int order;
+ printf("\ndumping free pages list...");
+ for (order = 0; order < 13; ++order)
+ memory_dump (order);
+ }
+
+int main ()
+ {
+ yyparse();
+ return 0;
+ }
+
+int read_input (char *buffer,int max)
+ {
+ char *line = 0;
+ while (1)
+ {
+ line = readline ("\n>");
+ if (!line)
+ break;
+ if (*line)
+ add_history(line);
+ strncpy (buffer,line,max);
+ strcat (buffer,";");
+ free (line);
+ return strlen (buffer);
+ }
+ buffer[0] = ';';
+ return 1;
+ }
+
diff --git a/firmware/test/memory/types.h b/firmware/test/memory/types.h
new file mode 100644
index 0000000..05e97b6
--- /dev/null
+++ b/firmware/test/memory/types.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __LIBRARY_MEMORY_H__
+#error "This header file must be included ONLY from memory.h."
+#endif
+#ifndef __LIBRARY_MEMORY_TYPES_H__
+#define __LIBRARY_MEMORY_TYPES_H__
+
+struct memory_free_page
+ {
+ struct memory_free_page
+ *less,*more;
+ char
+ reserved[MEMORY_PAGE_MINIMAL_SIZE - 2*sizeof (struct memory_free_page *)];
+ };
+struct memory_free_block
+ {
+ struct memory_free_block
+ *link;
+ };
+
+struct memory_cache
+ {
+ struct memory_cache
+ *less,*more,*same;
+ unsigned int
+ left; // number of free slabs
+ struct memory_slab
+ *used;
+ struct memory_slab
+ *free;
+ struct memory_slab
+ *reap;
+ unsigned int
+ size,original_size;
+ unsigned int
+ page_size;
+ unsigned int
+ blocks_per_slab;
+ int
+ page_order;
+ unsigned int
+ flags;
+ };
+
+struct memory_slab
+ {
+ struct memory_slab
+ *less,*more;
+ unsigned int // left == number of free blocks left
+ left;
+ struct memory_free_block
+ *free;
+ };
+
+#endif \ No newline at end of file