void *malloc( size_t size ) { void *return_this; MSBUMP(malloc_calls, 1); /* * If some free's have been deferred, then do them now. */ malloc_deferred_frees_process(); /* * Validate the parameters */ if ( !size ) return (void *) 0; /* * Do not attempt to allocate memory if not in correct system state. */ if ( _System_state_Is_up(_System_state_Get()) && !malloc_is_system_state_OK() ) return NULL; /* * Try to give a segment in the current heap if there is not * enough space then try to grow the heap. * If this fails then return a NULL pointer. */ return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size ); if ( !return_this ) { return_this = (*rtems_malloc_extend_handler)( RTEMS_Malloc_Heap, size ); if ( !return_this ) { errno = ENOMEM; return (void *) 0; } } /* * If the user wants us to dirty the allocated memory, then do it. */ if ( rtems_malloc_dirty_helper ) (*rtems_malloc_dirty_helper)( return_this, size ); /* * If configured, update the statistics */ if ( rtems_malloc_statistics_helpers ) (*rtems_malloc_statistics_helpers->at_malloc)(return_this); return return_this; }
/* * If the pointer is not in the heap, then we won't be able to get its * size and thus we skip updating the statistics. */ static void rtems_malloc_statistics_at_free( void *pointer ) { uintptr_t size; if (_Protected_heap_Get_block_size(RTEMS_Malloc_Heap, pointer, &size) ) { MSBUMP(lifetime_freed, size); } }
void *calloc( size_t nelem, size_t elsize ) { register char *cptr; size_t length; MSBUMP(calloc_calls, 1); length = nelem * elsize; cptr = malloc( length ); if ( cptr ) memset( cptr, '\0', length ); MSBUMP(malloc_calls, (uint32_t) -1); /* subtract off the malloc */ return cptr; }
static void rtems_malloc_statistics_at_malloc( void *pointer ) { uintptr_t actual_size = 0; uint32_t current_depth; rtems_malloc_statistics_t *s = &rtems_malloc_statistics; if ( !pointer ) return; _Protected_heap_Get_block_size(RTEMS_Malloc_Heap, pointer, &actual_size); MSBUMP(lifetime_allocated, actual_size); current_depth = (uint32_t) (s->lifetime_allocated - s->lifetime_freed); if (current_depth > s->max_depth) s->max_depth = current_depth; }
void *malloc( size_t size ) { void *return_this; MSBUMP(malloc_calls, 1); /* * If some free's have been deferred, then do them now. */ malloc_deferred_frees_process(); /* * Validate the parameters */ if ( !size ) return (void *) 0; /* * Do not attempt to allocate memory if not in correct system state. */ if ( _System_state_Is_up(_System_state_Get()) && !malloc_is_system_state_OK() ) return NULL; /* * Walk the heap and verify its integrity */ #if defined(RTEMS_HEAP_DEBUG) _Protected_heap_Walk( RTEMS_Malloc_Heap, 0, false ); #endif #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) /* * If the support for a boundary area at the end of the heap * block allocated is turned on, then adjust the size. */ if (rtems_malloc_boundary_helpers) size += (*rtems_malloc_boundary_helpers->overhead)(); #endif /* * Try to give a segment in the current heap if there is not * enough space then try to grow the heap. * If this fails then return a NULL pointer. */ return_this = _Protected_heap_Allocate( RTEMS_Malloc_Heap, size ); if ( !return_this ) { if (rtems_malloc_sbrk_helpers) return_this = (*rtems_malloc_sbrk_helpers->extend)( size ); if ( !return_this ) { errno = ENOMEM; return (void *) 0; } } /* * If the user wants us to dirty the allocated memory, then do it. */ if ( rtems_malloc_dirty_helper ) (*rtems_malloc_dirty_helper)( return_this, size ); /* * If configured, update the statistics */ if ( rtems_malloc_statistics_helpers ) (*rtems_malloc_statistics_helpers->at_malloc)(return_this); #if defined(RTEMS_MALLOC_BOUNDARY_HELPERS) /* * If configured, set the boundary area */ if (rtems_malloc_boundary_helpers) (*rtems_malloc_boundary_helpers->at_malloc)(return_this, size); #endif return return_this; }
void *realloc( void *ptr, size_t size ) { uintptr_t old_size; 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_in_critical_section()) return (void *) 0; if (_ISR_Nest_level > 0) return (void *) 0; } /* * Continue with realloc(). */ if ( !ptr ) return malloc( size ); if ( !size ) { free( ptr ); return (void *) 0; } if ( !_Protected_heap_Get_block_size(RTEMS_Malloc_Heap, ptr, &old_size) ) { errno = EINVAL; return (void *) 0; } /* * Now resize it. */ if ( _Protected_heap_Resize_block( RTEMS_Malloc_Heap, ptr, size ) ) { return ptr; } /* * 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. */ new_area = malloc( size ); MSBUMP(malloc_calls, (uint32_t) -1); /* subtract off the malloc */ if ( !new_area ) { return (void *) 0; } memcpy( new_area, ptr, (size < old_size) ? size : old_size ); free( ptr ); return new_area; }
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) ); }