rtems_status_code rtems_region_return_segment( rtems_id id, void *segment ) { Objects_Locations location; rtems_status_code return_status; #ifdef RTEMS_REGION_FREE_SHRED_PATTERN uint32_t size; #endif int status; register Region_Control *the_region; _RTEMS_Lock_allocator(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Region_Debug_Walk( the_region, 3 ); #ifdef RTEMS_REGION_FREE_SHRED_PATTERN if ( !_Heap_Size_of_alloc_area( &the_region->Memory, segment, &size ) ) return_status = RTEMS_INVALID_ADDRESS; else { memset( segment, (RTEMS_REGION_FREE_SHRED_PATTERN & 0xFF), size ); #endif status = _Region_Free_segment( the_region, segment ); _Region_Debug_Walk( the_region, 4 ); if ( !status ) return_status = RTEMS_INVALID_ADDRESS; else { the_region->number_of_used_blocks -= 1; _Region_Process_queue(the_region); /* unlocks allocator */ return RTEMS_SUCCESSFUL; } #ifdef RTEMS_REGION_FREE_SHRED_PATTERN } #endif break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_extend( rtems_id id, void *starting_address, uintptr_t length ) { uintptr_t amount_extended; Objects_Locations location; rtems_status_code return_status; Region_Control *the_region; if ( !starting_address ) return RTEMS_INVALID_ADDRESS; _RTEMS_Lock_allocator(); /* to prevent deletion */ the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: amount_extended = _Heap_Extend( &the_region->Memory, starting_address, length, 0 ); if ( amount_extended > 0 ) { the_region->length += amount_extended; the_region->maximum_segment_size += amount_extended; return_status = RTEMS_SUCCESSFUL; } else { return_status = RTEMS_INVALID_ADDRESS; } break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_get_free_information( rtems_id id, Heap_Information_block *the_info ) { Objects_Locations location; rtems_status_code return_status; Region_Control *the_region; if ( !the_info ) return RTEMS_INVALID_ADDRESS; _RTEMS_Lock_allocator(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: the_info->Used.number = 0; the_info->Used.total = 0; the_info->Used.largest = 0; _Heap_Get_free_information( &the_region->Memory, &the_info->Free ); return_status = RTEMS_SUCCESSFUL; break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_get_segment_size( rtems_id id, void *segment, uintptr_t *size ) { Objects_Locations location; rtems_status_code return_status = RTEMS_SUCCESSFUL; register Region_Control *the_region; if ( !segment ) return RTEMS_INVALID_ADDRESS; if ( !size ) return RTEMS_INVALID_ADDRESS; _RTEMS_Lock_allocator(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( !_Heap_Size_of_alloc_area( &the_region->Memory, segment, size ) ) return_status = RTEMS_INVALID_ADDRESS; break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_delete( rtems_id id ) { Objects_Locations location; rtems_status_code return_status; Region_Control *the_region; _RTEMS_Lock_allocator(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Region_Debug_Walk( the_region, 5 ); if ( the_region->number_of_used_blocks != 0 ) return_status = RTEMS_RESOURCE_IN_USE; else { _Objects_Close( &_Region_Information, &the_region->Object ); _Region_Free( the_region ); return_status = RTEMS_SUCCESSFUL; } break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_get_segment( rtems_id id, uintptr_t size, rtems_option option_set, rtems_interval timeout, void **segment ) { Thread_Control *executing; Objects_Locations location; rtems_status_code return_status; Region_Control *the_region; void *the_segment; if ( !segment ) return RTEMS_INVALID_ADDRESS; *segment = NULL; if ( size == 0 ) return RTEMS_INVALID_SIZE; _RTEMS_Lock_allocator(); executing = _Thread_Get_executing(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: if ( size > the_region->maximum_segment_size ) return_status = RTEMS_INVALID_SIZE; else { _Region_Debug_Walk( the_region, 1 ); the_segment = _Region_Allocate_segment( the_region, size ); _Region_Debug_Walk( the_region, 2 ); if ( the_segment ) { the_region->number_of_used_blocks += 1; *segment = the_segment; return_status = RTEMS_SUCCESSFUL; } else if ( _Options_Is_no_wait( option_set ) ) { return_status = RTEMS_UNSATISFIED; } else { /* * Switch from using the memory allocation mutex to using a * dispatching disabled critical section. We have to do this * because this thread is going to block. */ /* FIXME: Lock order reversal */ _Thread_Disable_dispatch(); _RTEMS_Unlock_allocator(); executing->Wait.queue = &the_region->Wait_queue; executing->Wait.id = id; executing->Wait.count = size; executing->Wait.return_argument = segment; _Thread_queue_Enter_critical_section( &the_region->Wait_queue ); _Thread_queue_Enqueue( &the_region->Wait_queue, executing, timeout ); _Objects_Put( &the_region->Object ); return (rtems_status_code) executing->Wait.return_code; } } break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_resize_segment( rtems_id id, void *segment, uintptr_t size, uintptr_t *old_size ) { uintptr_t avail_size; Objects_Locations location; uintptr_t osize; rtems_status_code return_status; Heap_Resize_status status; register Region_Control *the_region; if ( !old_size ) return RTEMS_INVALID_ADDRESS; _RTEMS_Lock_allocator(); the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_LOCAL: _Region_Debug_Walk( the_region, 7 ); status = _Heap_Resize_block( &the_region->Memory, segment, (uint32_t) size, &osize, &avail_size ); *old_size = (uint32_t) osize; _Region_Debug_Walk( the_region, 8 ); if ( status == HEAP_RESIZE_SUCCESSFUL ) _Region_Process_queue( the_region ); /* unlocks allocator */ else _RTEMS_Unlock_allocator(); if (status == HEAP_RESIZE_SUCCESSFUL) return RTEMS_SUCCESSFUL; if (status == HEAP_RESIZE_UNSATISFIED) return RTEMS_UNSATISFIED; return RTEMS_INVALID_ADDRESS; break; #if defined(RTEMS_MULTIPROCESSING) case OBJECTS_REMOTE: /* this error cannot be returned */ break; #endif case OBJECTS_ERROR: default: return_status = RTEMS_INVALID_ID; break; } _RTEMS_Unlock_allocator(); return return_status; }
rtems_status_code rtems_region_get_segment( Objects_Id id, uint32_t size, rtems_option option_set, rtems_interval timeout, void **segment ) { register Region_Control *the_region; Objects_Locations location; Thread_Control *executing; void *the_segment; if ( !segment ) return RTEMS_INVALID_ADDRESS; *segment = NULL; if ( size == 0 ) return RTEMS_INVALID_SIZE; _RTEMS_Lock_allocator(); executing = _Thread_Executing; the_region = _Region_Get( id, &location ); switch ( location ) { case OBJECTS_REMOTE: /* this error cannot be returned */ _RTEMS_Unlock_allocator(); return RTEMS_INTERNAL_ERROR; case OBJECTS_ERROR: _RTEMS_Unlock_allocator(); return RTEMS_INVALID_ID; case OBJECTS_LOCAL: if ( size > the_region->maximum_segment_size ) { _RTEMS_Unlock_allocator(); return RTEMS_INVALID_SIZE; } _Region_Debug_Walk( the_region, 1 ); the_segment = _Region_Allocate_segment( the_region, size ); _Region_Debug_Walk( the_region, 2 ); if ( the_segment ) { the_region->number_of_used_blocks += 1; _RTEMS_Unlock_allocator(); *segment = the_segment; return RTEMS_SUCCESSFUL; } if ( _Options_Is_no_wait( option_set ) ) { _RTEMS_Unlock_allocator(); return RTEMS_UNSATISFIED; } /* * Switch from using the memory allocation mutex to using a * dispatching disabled critical section. We have to do this * because this thread is going to block. */ _Thread_Disable_dispatch(); _RTEMS_Unlock_allocator(); executing->Wait.queue = &the_region->Wait_queue; executing->Wait.id = id; executing->Wait.count = size; executing->Wait.return_argument = segment; _Thread_queue_Enter_critical_section( &the_region->Wait_queue ); _Thread_queue_Enqueue( &the_region->Wait_queue, timeout ); _Thread_Enable_dispatch(); return (rtems_status_code) executing->Wait.return_code; } return RTEMS_INTERNAL_ERROR; /* unreached - only to remove warnings */ }