⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 malloc.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
字号:
/* *  RTEMS Malloc Family Implementation * * *  COPYRIGHT (c) 1989-1999. *  On-Line Applications Research Corporation (OAR). * *  The license and distribution terms for this file may be *  found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * *  $Id: malloc.c,v 1.30.2.5 2003/11/26 17:51:00 joel Exp $ */#if HAVE_CONFIG_H#include "config.h"#endif#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__#include <rtems.h>#include <rtems/libcsupport.h>#include <rtems/score/apimutex.h>#ifdef RTEMS_NEWLIB#include <sys/reent.h>#endif#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <assert.h>#include <errno.h>#include <string.h>#include <unistd.h>    /* sbrk(2) */#include <chain.h>Chain_Control RTEMS_Malloc_GC_list;rtems_id RTEMS_Malloc_Heap;size_t RTEMS_Malloc_Sbrk_amount;#ifdef RTEMS_DEBUG#define MALLOC_STATS#define MALLOC_DIRTY#endif#ifdef MALLOC_STATS#define MSBUMP(f,n)    rtems_malloc_stats.f += (n)struct {    unsigned32  space_available;             /* current size of malloc area */    unsigned32  malloc_calls;                /* # calls to malloc */    unsigned32  free_calls;    unsigned32  realloc_calls;    unsigned32  calloc_calls;    unsigned32  max_depth;		     /* most ever malloc'd at 1 time */    unsigned64  lifetime_allocated;    unsigned64  lifetime_freed;} rtems_malloc_stats;#else			/* No rtems_malloc_stats */#define MSBUMP(f,n)#endifvoid RTEMS_Malloc_Initialize(  void   *start,  size_t  length,  size_t  sbrk_amount){  rtems_status_code   status;  void               *starting_address;  rtems_unsigned32    old_address;  rtems_unsigned32    u32_address;  /*   *  Initialize the garbage collection list to start with nothing on it.   */  Chain_Initialize_empty(&RTEMS_Malloc_GC_list);  /*   * 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;  RTEMS_Malloc_Sbrk_amount = sbrk_amount;  if (!starting_address) {    u32_address = (unsigned int)sbrk(length);    if (u32_address == (rtems_unsigned32) -1) {      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );      /* DOES NOT RETURN!!! */    }    if (u32_address & (CPU_HEAP_ALIGNMENT-1)) {      old_address = u32_address;      u32_address = (u32_address + CPU_HEAP_ALIGNMENT) & ~(CPU_HEAP_ALIGNMENT-1);       /*	* adjust the length by whatever we aligned by	*/      length -= u32_address - old_address;    }    starting_address = (void *)u32_address;  }  /*   *  If the BSP is not clearing out the workspace, then it is most likely   *  not clearing out the initial memory for the heap.  There is no    *  standard supporting zeroing out the heap memory.  But much code   *  with UNIX history seems to assume that memory malloc'ed during   *  initialization (before any free's) is zero'ed.  This is true most   *  of the time under UNIX because zero'ing memory when it is first   *  given to a process eliminates the chance of a process seeing data   *  left over from another process.  This would be a security violation.   */  if ( rtems_cpu_configuration_get_do_zero_of_workspace() )     memset( starting_address, 0, length );  /*   *  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,    CPU_HEAP_ALIGNMENT,    RTEMS_DEFAULT_ATTRIBUTES,    &RTEMS_Malloc_Heap  );  if ( status != RTEMS_SUCCESSFUL )    rtems_fatal_error_occurred( status );#ifdef MALLOC_STATS  /* zero all the stats */  (void) memset( &rtems_malloc_stats, 0, sizeof(rtems_malloc_stats) );#endif    MSBUMP(space_available, length);}#ifdef RTEMS_NEWLIBvoid *malloc(  size_t  size){  void              *return_this;  void              *starting_address;  rtems_unsigned32   the_size;  rtems_unsigned32   sbrk_amount;  rtems_status_code  status;  Chain_Node        *to_be_freed;  MSBUMP(malloc_calls, 1);  if ( !size )    return (void *) 0;  /*   *  Do not attempt to allocate memory if in a critical section or ISR.   */  if (_System_state_Is_up(_System_state_Get())) {    if (_Thread_Dispatch_disable_level > 0)      return (void *) 0;     if (_ISR_Nest_level > 0)      return (void *) 0;  }   /*   *  If some free's have been deferred, then do them now.   */  while ((to_be_freed = Chain_Get(&RTEMS_Malloc_GC_list)) != NULL)    free(to_be_freed);  /*   * 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 = (void *)sbrk(the_size))             == (rtems_unsigned32) -1)      return (void *) 0;    status = rtems_region_extend(      RTEMS_Malloc_Heap,      starting_address,      the_size    );    if ( status != RTEMS_SUCCESSFUL ) {      sbrk(-the_size);      errno = ENOMEM;      return (void *) 0;    }        MSBUMP(space_available, the_size);    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;    }  }#ifdef MALLOC_STATS  if (return_this)  {      unsigned32 actual_size;      unsigned32 current_depth;      status = rtems_region_get_segment_size(                   RTEMS_Malloc_Heap, return_this, &actual_size);      MSBUMP(lifetime_allocated, actual_size);      current_depth = rtems_malloc_stats.lifetime_allocated -                   rtems_malloc_stats.lifetime_freed;      if (current_depth > rtems_malloc_stats.max_depth)          rtems_malloc_stats.max_depth = current_depth;  }#endif#ifdef MALLOC_DIRTY  (void) memset(return_this, 0xCF, size);#endif  return return_this;}void *calloc(  size_t nelem,  size_t elsize){  register char *cptr;  int length;  MSBUMP(calloc_calls, 1);  length = nelem * elsize;  cptr = malloc( length );  if ( cptr )    memset( cptr, '\0', length );  MSBUMP(malloc_calls, -1);   /* subtract off the malloc */  return cptr;}void *realloc(  void *ptr,  size_t size){  rtems_unsigned32  old_size;  rtems_status_code status;  char *new_area;  MSBUMP(realloc_calls, 1);  /*   *  Do not attempt to allocate memory if in a critical section or ISR.   */  if (_System_state_Is_up(_System_state_Get())) {    if (_Thread_Dispatch_disable_level > 0)      return (void *) 0;     if (_ISR_Nest_level > 0)      return (void *) 0;  }   /*   * Continue with calloc().   */  if ( !ptr )    return malloc( size );  if ( !size ) {    free( ptr );    return (void *) 0;  }  new_area = malloc( size );   MSBUMP(malloc_calls, -1);   /* subtract off the malloc */  /*   *  There used to be a free on this error case but it is wrong to    *  free the memory per OpenGroup Single UNIX Specification V2   *  and the C Standard.   */  if ( !new_area ) {    return (void *) 0;  }  status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &old_size );  if ( status != RTEMS_SUCCESSFUL ) {    errno = EINVAL;    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;  MSBUMP(free_calls, 1);  if ( !ptr )    return;  /*   *  Do not attempt to free memory if in a critical section or ISR.   */  if (_System_state_Is_up(_System_state_Get())) {    if ((_Thread_Dispatch_disable_level > 0) || (_ISR_Nest_level > 0)) {      Chain_Append(&RTEMS_Malloc_GC_list, (Chain_Node *)ptr);      return;    }  } #ifdef MALLOC_STATS  {      unsigned32        size;      status = rtems_region_get_segment_size( RTEMS_Malloc_Heap, ptr, &size );      if ( status == RTEMS_SUCCESSFUL ) {          MSBUMP(lifetime_freed, size);      }  }#endif    status = rtems_region_return_segment( RTEMS_Malloc_Heap, ptr );  if ( status != RTEMS_SUCCESSFUL ) {    errno = EINVAL;    assert( 0 );  }}/* end if RTEMS_NEWLIB */#endif#ifdef MALLOC_STATS/* * Dump the malloc statistics * May be called via atexit()  (installable by our bsp) or * at any time by user */void malloc_dump(void){    unsigned32 allocated = rtems_malloc_stats.lifetime_allocated -                     rtems_malloc_stats.lifetime_freed;    printf("Malloc stats\n");    printf("  avail:%uk  allocated:%uk (%d%%) "              "max:%uk (%d%%) lifetime:%Luk freed:%Luk\n",           (unsigned int) rtems_malloc_stats.space_available / 1024,           (unsigned int) allocated / 1024,           /* avoid float! */           (allocated * 100) / rtems_malloc_stats.space_available,           (unsigned int) rtems_malloc_stats.max_depth / 1024,           (rtems_malloc_stats.max_depth * 100) / rtems_malloc_stats.space_available,           (unsigned64) rtems_malloc_stats.lifetime_allocated / 1024,           (unsigned64) rtems_malloc_stats.lifetime_freed / 1024);    printf("  Call counts:   malloc:%d   free:%d   realloc:%d   calloc:%d\n",           rtems_malloc_stats.malloc_calls,           rtems_malloc_stats.free_calls,           rtems_malloc_stats.realloc_calls,           rtems_malloc_stats.calloc_calls);}void malloc_walk(size_t source, size_t printf_enabled){   register Region_Control *the_region;   Objects_Locations        location;   _RTEMS_Lock_allocator();                      /* to prevent deletion */   the_region = _Region_Get( RTEMS_Malloc_Heap, &location );   if ( location == OBJECTS_LOCAL )   {      _Heap_Walk( &the_region->Memory, source, printf_enabled );   }  _RTEMS_Unlock_allocator();}#elsevoid malloc_dump(void){   return;} void malloc_walk(size_t source, size_t printf_enabled){   return;}#endif/* *  "Reentrant" versions of the above routines implemented above. */#ifdef RTEMS_NEWLIBvoid *_malloc_r(  struct _reent *ignored,  size_t  size){  return malloc( size );}void *_calloc_r(  struct _reent *ignored,  size_t nelem,  size_t elsize){  return calloc( nelem, elsize );}void *_realloc_r(  struct _reent *ignored,  void *ptr,  size_t size){  return realloc( ptr, size );}void _free_r(  struct _reent *ignored,  void *ptr){  free( ptr );}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -