From ac7d5ef06a6d6e8d84abbd1f0b82162725f98326 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 11 May 1995 17:39:37 +0000 Subject: Initial revision --- c/src/exec/libcsupport/src/malloc.c | 280 ++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 c/src/exec/libcsupport/src/malloc.c (limited to 'c/src/exec/libcsupport/src/malloc.c') diff --git a/c/src/exec/libcsupport/src/malloc.c b/c/src/exec/libcsupport/src/malloc.c new file mode 100644 index 0000000000..7d0ba04143 --- /dev/null +++ b/c/src/exec/libcsupport/src/malloc.c @@ -0,0 +1,280 @@ +/* + * RTEMS Malloc Family Implementation + * + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include +#ifdef RTEMS_LIBC +#include +#endif +#include "libcsupport.h" +#ifdef RTEMS_NEWLIB +#include +#endif + +#include +#include +#include +#include +#include +#include + +/* + * XXX: Do we really need to duplicate these? It appears that they + * only cause typing problems. + */ + +#if 0 +void *malloc(size_t); +void *calloc(size_t, size_t); +void *realloc(void *, size_t); +void free(void *); +void *sbrk(size_t); +#endif + +rtems_id RTEMS_Malloc_Heap; +size_t RTEMS_Malloc_Sbrk_amount; + +void RTEMS_Malloc_Initialize( + void *start, + size_t length, + size_t sbrk_amount +) +{ + rtems_status_code status; + void *starting_address; + rtems_unsigned32 u32_address; + + /* + * If the starting address is 0 then we are to attempt to + * get length worth of memory using sbrk. Make sure we + * align the address that we get back. + */ + + starting_address = start; + + if (!starting_address) { + u32_address = (unsigned int)sbrk(length); + + if (u32_address == -1) { + rtems_fatal_error_occurred( RTEMS_NO_MEMORY ); + /* DOES NOT RETURN!!! */ + } + + if (u32_address & (CPU_ALIGNMENT-1)) { + u32_address = (u32_address + CPU_ALIGNMENT) & ~(CPU_ALIGNMENT-1); + /* XXX: if we do any alignment .. then length should be shortened */ + } + + starting_address = (void *)u32_address; + } + + /* + * Unfortunately we cannot use assert if this fails because if this + * has failed we do not have a heap and if we do not have a heap + * STDIO cannot work because there will be no buffers. + */ + + status = rtems_region_create( + rtems_build_name( 'H', 'E', 'A', 'P' ), + starting_address, + length, + 8, /* XXX : use CPU dependent RTEMS constant */ + RTEMS_DEFAULT_ATTRIBUTES, + &RTEMS_Malloc_Heap + ); + if ( status != RTEMS_SUCCESSFUL ) + rtems_fatal_error_occurred( status ); +} + +void *malloc( + size_t size +) +{ + void *return_this; + void *starting_address; + rtems_unsigned32 the_size; + rtems_unsigned32 sbrk_amount; + rtems_status_code status; + + if ( !size ) + return (void *) 0; + + /* + * Try to give a segment in the current region if there is not + * enough space then try to grow the region using rtems_region_extend(). + * If this fails then return a NULL pointer. + */ + + status = rtems_region_get_segment( + RTEMS_Malloc_Heap, + size, + RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT, + &return_this + ); + + if ( status != RTEMS_SUCCESSFUL ) { + /* + * Round to the "requested sbrk amount" so hopefully we won't have + * to grow again for a while. This effectively does sbrk() calls + * in "page" amounts. + */ + + sbrk_amount = RTEMS_Malloc_Sbrk_amount; + + if ( sbrk_amount == 0 ) + return (void *) 0; + + the_size = ((size + sbrk_amount) / sbrk_amount * sbrk_amount); + + if (((rtems_unsigned32)starting_address = sbrk(the_size)) == -1) + return (void *) 0; + + /* + fprintf(stderr, "Extended the C heap starting at 0x%x for %d bytes\n", + (unsigned32)starting_address, the_size); + */ + + status = rtems_region_extend( + RTEMS_Malloc_Heap, + starting_address, + the_size + ); + if ( status != RTEMS_SUCCESSFUL ) { + sbrk(-the_size); + return(FALSE); + errno = ENOMEM; + return (void *) 0; + } + status = rtems_region_get_segment( + RTEMS_Malloc_Heap, + size, + RTEMS_NO_WAIT, + RTEMS_NO_TIMEOUT, + &return_this + ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = ENOMEM; + return (void *) 0; + } + } + + return return_this; +} + +void *calloc( + size_t nelem, + size_t elsize +) +{ + register char *cptr; + int length; + + length = nelem * elsize; + cptr = malloc( length ); + if ( cptr ) + memset( cptr, '\0', length ); + + return cptr; +} + +void *realloc( + void *ptr, + size_t size +) +{ + rtems_unsigned32 old_size; + rtems_status_code status; + char *new_area; + + if ( !ptr ) + return malloc( size ); + + if ( !size ) { + free( ptr ); + return (void *) 0; + } + + status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + return (void *) 0; + } + + new_area = malloc( size ); + if ( !new_area ) { + free( ptr ); + return (void *) 0; + } + + memcpy( new_area, ptr, (size < old_size) ? size : old_size ); + free( ptr ); + + return new_area; + +} + +void free( + void *ptr +) +{ + rtems_status_code status; + + if ( !ptr ) + return; + + status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr ); + if ( status != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + assert( 0 ); + } +} + +/* + * "Reentrant" versions of the above routines implemented above. + */ + +#ifdef RTEMS_NEWLIB +void *malloc_r( + struct _reent *ignored, + size_t size +) +{ + return malloc( size ); +} + +void *calloc_r( + size_t nelem, + size_t elsize +) +{ + return calloc( nelem, elsize ); +} + +void *realloc_r( + void *ptr, + size_t size +) +{ + return realloc_r( ptr, size ); +} + +void free_r( + void *ptr +) +{ + free( ptr ); +} +#endif + -- cgit v1.2.3