1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00

Added support for multiple RAM spaces using the TLSF allocator.

This takes care of my LPC2888 board (any many other board out there)
that have RAM both on the CPU itself and on a separate chip.
To use it add "allocator=tlsf" to your scons build command.
Even though the code for all the platform was modified, the new code
should not modify the "old" allocator behaviour.
Also added a new "mem" command to the shell, it gives information about
the current RAM state (total, used, free).
NOT YET TESTED !!! So use with care.
This commit is contained in:
Bogdan Marinescu 2008-08-13 13:42:57 +00:00
parent 4901305cb9
commit 09ac410a02
12 changed files with 1273 additions and 28 deletions

View File

@ -1,6 +1,7 @@
import os, sys
target = ARGUMENTS.get( 'target', 'lua' ).lower()
cputype = ARGUMENTS.get( 'cpu', 'at91sam7x256' ).lower()
allocator = ARGUMENTS.get( 'allocator', 'newlib' ).lower()
# List of platform/CPU combinations
cpu_list = { 'at91sam7x' : [ 'at91sam7x256', 'at91sam7x512' ],
@ -28,6 +29,8 @@ else:
output = 'elua_' + target + '_' + cputype
cdefs = '-D%s' % cputype
if allocator == 'tlsf':
cdefs = cdefs + ' -DUSE_TLSF'
# Lua source files and include path
lua_files = """lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c
@ -49,7 +52,7 @@ local_include = local_include + " -Isrc/modules -Isrc/platform/%s" % platform
local_libs = ''
# Application files
app_files = " src/romfs.c src/main.c src/xmodem.c src/shell.c src/term.c"
app_files = " src/romfs.c src/main.c src/xmodem.c src/shell.c src/term.c src/tlsf.c"
# Newlib related files
newlib_files = " src/newlib/devman.c src/newlib/stubs.c src/newlib/genstd.c"

View File

@ -152,7 +152,7 @@ u32 platform_pd_get_cpu_frequency();
// *****************************************************************************
// Allocator support
void* platform_get_first_free_ram();
void* platform_get_last_free_ram();
void* platform_get_first_free_ram( unsigned id );
void* platform_get_last_free_ram( unsigned id );
#endif

43
inc/tlsf.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Two Levels Segregate Fit memory allocator (TLSF)
* Version 2.4.3
*
* Written by Miguel Masmano Tello <mimastel@doctor.upv.es>
*
* Thanks to Ismael Ripoll for his suggestions and reviews
*
* Copyright (C) 2008, 2007, 2006, 2005, 2004
*
* This code is released using a dual license strategy: GPL/LGPL
* You can choose the licence that better fits your requirements.
*
* Released under the terms of the GNU General Public License Version 2.0
* Released under the terms of the GNU Lesser General Public License Version 2.1
*
*/
#ifndef _TLSF_H_
#define _TLSF_H_
#include <sys/types.h>
extern size_t init_memory_pool(size_t, void *);
extern size_t get_used_size(void *);
extern size_t get_max_size(void *);
extern void destroy_memory_pool(void *);
extern size_t add_new_area(void *, size_t, void *);
extern void *malloc_ex(size_t, void *);
extern void free_ex(void *, void *);
extern void *realloc_ex(void *, size_t, void *);
extern void *calloc_ex(size_t, size_t, void *);
extern void *tlsf_malloc(size_t size);
extern void tlsf_free(void *ptr);
extern void *tlsf_realloc(void *ptr, size_t size);
extern void *tlsf_calloc(size_t nelem, size_t elem_size);
// BogdanM - added for eLua
void tlsf_elua_init();
size_t tlsf_elua_get_block_size( void* ptr );
#endif

View File

@ -11,9 +11,9 @@
#include "build.h"
#include "lua.h"
#include "term.h"
#include "tlsf.h"
extern char etext[];
extern char end[];
// ****************************************************************************
// XMODEM support code
@ -163,6 +163,10 @@ int main( void )
// This should never happen
while( 1 );
}
// Initialize the TLSF allocator
// (if TLSF is not used, the next function does nothing)
tlsf_elua_init();
// Initialize device manager
dm_init();
@ -176,7 +180,7 @@ int main( void )
// Initialize terminal
term_init( TERMINAL_LINES, TERMINAL_COLS, term_out, term_in, term_translate );
printf( ".text ends at %p, first free RAM is at %p, last free ram is at %p\r\n", etext, platform_get_first_free_ram(), platform_get_last_free_ram() );
printf( ".text ends at %p\n", etext );
// Run the shell
if( shell_init( XMODEM_MAX_FILE_SIZE ) == 0 )

View File

@ -9,6 +9,7 @@
#include "devman.h"
#include "ioctl.h"
#include "platform.h"
#include "tlsf.h"
// Utility function: look in the device manager table and find the index
// for the given name. Returns an index into the device structure, -1 if error.
@ -49,6 +50,7 @@ static int find_dm_entry( const char* name, char **pactname )
}
if( i == dm_get_num_devices() )
return -1;
// Find the actual first char of the name
preal ++;
if( *preal == '\0' )
@ -176,6 +178,8 @@ _ssize_t _write_r( struct _reent *r, int file, const void *ptr, size_t len )
// *****************************************************************************
// _sbrk_r
// Only used if we're using the default Newlib allocator (dlmalloc), not TLSF
#ifndef USE_TLSF
static char *heap_ptr;
void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
@ -187,8 +191,8 @@ void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
else
{
if( heap_ptr == NULL )
heap_ptr = ( char* )platform_get_first_free_ram();
if( heap_ptr + incr >= ( char* )platform_get_last_free_ram() )
heap_ptr = ( char* )platform_get_first_free_ram( 0 );
if( heap_ptr + incr > ( char* )platform_get_last_free_ram( 0 ) )
ptr = ( void* )-1;
else
{
@ -198,6 +202,7 @@ void* _sbrk_r( struct _reent* r, ptrdiff_t incr )
}
return ptr;
}
#endif
// *****************************************************************************
// _lseek_r
@ -284,5 +289,120 @@ int __svfscanf_r( struct _reent *r, FILE *stream, const char *format, va_list ap
{
return __svfiscanf_r( r, stream, format, ap );
}
#endif // #ifdef LUA_INTONLY
#endif
// If USE_TLSF is defined, "redirect" allocator calls from Newlib to TLSF
#ifdef USE_TLSF
// malloc: try to allocate in all the memory pools
void* _malloc_r( struct _reent* r, size_t size )
{
unsigned i = 0;
void* temp = NULL;
while( 1 )
{
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
break;
if( ( temp = malloc_ex( size, temp ) ) != NULL )
break;
i ++;
}
return temp;
}
// calloc: try to allocate in all the memory pools
void* _calloc_r( struct _reent* r, size_t nelem, size_t elem_size )
{
unsigned i = 0;
void* temp = NULL;
while( 1 )
{
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
break;
if( ( temp = calloc_ex( nelem, elem_size, temp ) ) != NULL )
break;
i ++;
}
return temp;
}
// free: find memory pool with the given pointer, then free it
void _free_r( struct _reent* r, void* ptr )
{
unsigned i = 0;
u32 lstart, lend;
while( 1 )
{
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
break;
lend = ( u32 )platform_get_last_free_ram( i );
if( ( lstart <= ( u32 )ptr ) && ( ( u32 )ptr <= lend ) )
{
free_ex( ptr, ( void* )lstart );
break;
}
i ++;
}
}
// realloc: this is a bit more complex. First we identify the correct memory
// pool and try to realloc there. If this doesn't work, we try to realloc in
// another pool before giving up.
void* _relloc_r( struct _reent* r, void* ptr, size_t size )
{
void* temp;
u32 lstart, lend;
unsigned i = 0;
size_t prevsize;
// Realloc with ptr == NULL : malloc
// Realloc with size == 0 : free
if( !ptr )
return size ? _malloc_r( r, size ) : NULL;
else if( !size )
{
_free_r( r, ptr );
return NULL;
}
// At this point we know that this is an actual realloc
// Identify the memory pool
while( 1 )
{
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
return NULL;
lend = ( u32 )platform_get_last_free_ram( i );
if( ( lstart <= ( u32 )ptr ) && ( ( u32 )ptr <= lend ) )
break;
i ++;
}
// Easy case: realloc succeeds in the same memory pool
if( ( temp = realloc_ex( ptr, size, ( void* )lstart ) ) != NULL )
return temp;
// If realloc returned NULL, look for another pool
prevsize = tlsf_elua_get_block_size( ptr );
i = 0;
while( 1 )
{
if( ( temp = platform_get_first_free_ram( i ) ) == NULL )
break;
if( ( u32 )temp != lstart )
{
if( ( temp = malloc_ex( size, temp ) ) != NULL )
{
memcpy( temp, ptr, prevsize < size ? prevsize : size );
free_ex( ptr, ( void* )lstart );
break;
}
}
i ++;
}
return temp;
}
#endif // #ifdef USE_TLSF

View File

@ -381,9 +381,9 @@ u32 platform_pd_get_cpu_frequency()
// Allocator support
extern char end[];
void* platform_get_first_free_ram()
void* platform_get_first_free_ram( unsigned id )
{
return ( void* )end;
return id > 0 ? NULL : ( void* )end;
}
#define SRAM_ORIGIN 0x200000
@ -393,7 +393,7 @@ void* platform_get_first_free_ram()
#define SRAM_SIZE 0x20000
#endif
void* platform_get_last_free_ram()
void* platform_get_last_free_ram( unsigned id )
{
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
return id > 0 ? NULL : ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 );
}

View File

@ -106,13 +106,13 @@ int platform_uart_recv( unsigned id, unsigned timer_id, int timeout )
// Allocator support
extern char end[];
void* platform_get_first_free_ram()
void* platform_get_first_free_ram( unsigned id )
{
return ( void* )end;
return id > 0 ? NULL : ( void* )end;
}
#define MY_STACK_SIZE ( 16 * 1024 )
void* platform_get_last_free_ram()
void* platform_get_last_free_ram( unsigned id )
{
return ( void* )( lastmem - MY_STACK_SIZE );
return id > 0 ? NULL : ( void* )( lastmem - MY_STACK_SIZE - 1 );
}

View File

@ -458,14 +458,14 @@ u32 platform_pd_get_cpu_frequency()
extern char end[];
void* platform_get_first_free_ram()
void* platform_get_first_free_ram( unsigned id )
{
return ( void* )end;
return id > 0 ? NULL : ( void* )end;
}
#define STACK_SIZE 256
#define SRAM_SIZE ( 64 * 1024 )
void* platform_get_last_free_ram()
void* platform_get_last_free_ram( unsigned id )
{
return ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE );
return id > 0 ? NULL : ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE - 1 );
}

View File

@ -304,15 +304,22 @@ u32 platform_pd_get_cpu_frequency()
extern char end[];
void* platform_get_first_free_ram()
void* platform_get_first_free_ram( unsigned id )
{
return ( void* )end;
if( id > 1 )
return NULL;
else
return id == 0 ? ( void* )end : ( void* )SDRAM_BASE_ADDR;
}
#define SRAM_ORIGIN 0x00400000
#define SRAM_SIZE 0x10000
void* platform_get_last_free_ram()
void* platform_get_last_free_ram( unsigned id )
{
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
if( id > 1 )
return NULL;
else
return id == 0 ? ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) :
( void* )( SDRAM_BASE_ADDR + SDRAM_SIZE - 1 );
}

View File

@ -421,15 +421,15 @@ u32 platform_pd_get_cpu_frequency()
// Allocator support
extern char end[];
void* platform_get_first_free_ram()
void* platform_get_first_free_ram( unsigned id )
{
return ( void* )end;
return id > 0 ? NULL : ( void* )end;
}
#define SRAM_ORIGIN 0x40000000
#define SRAM_SIZE 0x18000
void* platform_get_last_free_ram()
void* platform_get_last_free_ram( unsigned id )
{
return ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL );
return id > 0 ? NULL : ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 );
}

View File

@ -9,6 +9,9 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include "tlsf.h"
#include "platform.h"
#include "build.h"
#ifdef BUILD_SHELL
@ -42,6 +45,7 @@ static void shell_help( char* args )
printf( " lua [args] - run Lua with the given arguments\n" );
printf( " recv - receive a file (XMODEM) and execute it\n" );
printf( " ver - print eLua version\n" );
printf( " mem - RAM usage data\n" );
printf( " exit - exit from this shelll\n" );
}
@ -152,6 +156,31 @@ static void shell_ver( char* args )
printf( "For more information go to http://elua.berlios.de\n" );
}
// 'mem' handler
static void shell_mem( char* args )
{
unsigned i = 0;
u32 lstart, lend;
args = args;
while( 1 )
{
if( ( lstart = ( u32 )platform_get_first_free_ram( i ) ) == 0 )
break;
lend = ( u32 )platform_get_last_free_ram( i );
printf( "Start:0x%08lX Size:%8ld ", lstart, lend - lstart + 1 );
#ifdef USE_TLSF
u32 temp = get_used_size( ( void* )lstart );
printf( "Used:%8ld Free:%8ld\n", temp, lend - lstart + 1 - temp );
#else
struct mallinfo allocdata;
allocdata = mallinfo();
printf( "Used:%8ld Free:%8ld\n", ( long )allocdata.uordblks, ( long )allocdata.fordblks );
#endif
i ++;
}
}
// Insert shell commands here
static const SHELL_COMMAND shell_commands[] =
{
@ -159,6 +188,7 @@ static const SHELL_COMMAND shell_commands[] =
{ "lua", shell_lua },
{ "recv", shell_recv },
{ "ver", shell_ver },
{ "mem", shell_mem },
{ "exit", NULL },
{ NULL, NULL }
};

1038
src/tlsf.c Normal file

File diff suppressed because it is too large Load Diff