Beispiel #1
0
/*
 *  _Workspace_Handler_initialization
 */
void _Workspace_Handler_initialization(void)
{
  uintptr_t memory_available = 0;
  void *starting_address = rtems_configuration_get_work_space_start();
  uintptr_t size = rtems_configuration_get_work_space_size();

  if ( rtems_configuration_get_do_zero_of_workspace() )
    memset( starting_address, 0, size );

  memory_available = _Heap_Initialize(
    &_Workspace_Area,
    starting_address,
    size,
    CPU_HEAP_ALIGNMENT
  );

  if ( memory_available == 0 )
    _Internal_error_Occurred(
      INTERNAL_ERROR_CORE,
      true,
      INTERNAL_ERROR_TOO_LITTLE_WORKSPACE
    );
}
Beispiel #2
0
void _Workspace_Handler_initialization(
  Heap_Area *areas,
  size_t area_count,
  Heap_Initialization_or_extend_handler extend
)
{
  Heap_Initialization_or_extend_handler init_or_extend = _Heap_Initialize;
  uintptr_t remaining = rtems_configuration_get_work_space_size();
  bool do_zero = rtems_configuration_get_do_zero_of_workspace();
  bool unified = rtems_configuration_get_unified_work_area();
  uintptr_t page_size = CPU_HEAP_ALIGNMENT;
  uintptr_t overhead = _Heap_Area_overhead( page_size );
  uintptr_t tls_size = _TLS_Get_size();
  size_t i;

  /*
   * In case we have a non-zero TLS size, then we need a TLS area for each
   * thread.  These areas are allocated from the workspace.  Ensure that the
   * workspace is large enough to fulfill all requests known at configuration
   * time (so excluding the unlimited option).  It is not possible to estimate
   * the TLS size in the configuration at compile-time.  The TLS size is
   * determined at application link-time.
   */
  if ( tls_size > 0 ) {
    uintptr_t tls_align = _TLS_Heap_align_up( (uintptr_t) _TLS_Alignment );
    uintptr_t tls_alloc = _TLS_Get_allocation_size( tls_size, tls_align );

    /*
     * Memory allocated with an alignment constraint is allocated from the end
     * of a free block.  The last allocation may need one free block of minimum
     * size.
     */
    remaining += _Heap_Min_block_size( page_size );

    remaining += _Get_maximum_thread_count()
      * _Heap_Size_with_overhead( page_size, tls_alloc, tls_align );
  }

  for (i = 0; i < area_count; ++i) {
    Heap_Area *area = &areas [i];

    if ( do_zero ) {
      memset( area->begin, 0, area->size );
    }

    if ( area->size > overhead ) {
      uintptr_t space_available;
      uintptr_t size;

      if ( unified ) {
        size = area->size;
      } else {
        if ( remaining > 0 ) {
          size = remaining < area->size - overhead ?
            remaining + overhead : area->size;
        } else {
          size = 0;
        }
      }

      space_available = (*init_or_extend)(
        &_Workspace_Area,
        area->begin,
        size,
        page_size
      );

      area->begin = (char *) area->begin + size;
      area->size -= size;

      if ( space_available < remaining ) {
        remaining -= space_available;
      } else {
        remaining = 0;
      }

      init_or_extend = extend;
    }
  }

  if ( remaining > 0 ) {
    _Internal_error( INTERNAL_ERROR_TOO_LITTLE_WORKSPACE );
  }

  _Heap_Protection_set_delayed_free_fraction( &_Workspace_Area, 1 );
}
void RTEMS_Malloc_Initialize(
  void *heap_begin,
  uintptr_t heap_size,
  size_t sbrk_amount
)
{
  bool separate_areas = !rtems_configuration_get_unified_work_area();
  /*
   *  If configured, initialize the statistics support
   */
  if ( rtems_malloc_statistics_helpers != NULL ) {
    (*rtems_malloc_statistics_helpers->initialize)();
  }

  /*
   *  Initialize the garbage collection list to start with nothing on it.
   */
  malloc_deferred_frees_initialize();

  /*
   *  Initialize the optional sbrk support for extending the heap
   */
  if ( rtems_malloc_sbrk_helpers != NULL ) {
    void *new_heap_begin = (*rtems_malloc_sbrk_helpers->initialize)(
      heap_begin,
      sbrk_amount
    );

    heap_size -= (uintptr_t) new_heap_begin - (uintptr_t) heap_begin;
    heap_begin = new_heap_begin;
  }

  /*
   *  If this system is configured to use the same heap for
   *  the RTEMS Workspace and C Program Heap, then we need to
   *  be very very careful about destroying the initialization
   *  that has already been done.
   */

  /*
   *  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 ( separate_areas && rtems_configuration_get_do_zero_of_workspace() ) {
     memset( heap_begin, 0, heap_size );
  }

  /*
   *  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.
   */

  if ( separate_areas ) {
    uintptr_t status = _Protected_heap_Initialize(
      RTEMS_Malloc_Heap,
      heap_begin,
      heap_size,
      CPU_HEAP_ALIGNMENT
    );
    if ( status == 0 ) {
      rtems_fatal_error_occurred( RTEMS_NO_MEMORY );
    }
  }

  MSBUMP( space_available, _Protected_heap_Get_size(RTEMS_Malloc_Heap) );
}