rtems: Add and use _Region_Get_and_lock()

Get region and lock allocator in _Region_Get_and_lock() in case the
region exists and unlock it in _Region_Unlock().
This commit is contained in:
Sebastian Huber
2016-04-08 06:56:46 +02:00
parent 572cb62429
commit 1142f5593a
10 changed files with 172 additions and 177 deletions

View File

@@ -19,7 +19,6 @@
#include <rtems/rtems/region.h> #include <rtems/rtems/region.h>
#include <rtems/score/apimutex.h> #include <rtems/score/apimutex.h>
#include <rtems/score/assert.h>
#include <rtems/score/heapimpl.h> #include <rtems/score/heapimpl.h>
#include <rtems/score/objectimpl.h> #include <rtems/score/objectimpl.h>
#include <rtems/score/threadqimpl.h> #include <rtems/score/threadqimpl.h>
@@ -67,11 +66,28 @@ RTEMS_INLINE_ROUTINE void _Region_Free (
_Objects_Free( &_Region_Information, &the_region->Object ); _Objects_Free( &_Region_Information, &the_region->Object );
} }
RTEMS_INLINE_ROUTINE Region_Control *_Region_Get( Objects_Id id ) RTEMS_INLINE_ROUTINE Region_Control *_Region_Get_and_lock( Objects_Id id )
{ {
_Assert( _RTEMS_Allocator_is_owner() ); Region_Control *the_region;
return (Region_Control *)
_RTEMS_Lock_allocator();
the_region = (Region_Control *)
_Objects_Get_no_protection( &_Region_Information, id ); _Objects_Get_no_protection( &_Region_Information, id );
if ( the_region != NULL ) {
/* Keep allocator lock */
return the_region;
}
_RTEMS_Unlock_allocator();
return NULL;
}
RTEMS_INLINE_ROUTINE void _Region_Unlock( Region_Control *the_region )
{
(void) the_region;
_RTEMS_Unlock_allocator();
} }
/** /**

View File

@@ -28,23 +28,23 @@ rtems_status_code rtems_region_delete(
Region_Control *the_region; Region_Control *the_region;
_Objects_Allocator_lock(); _Objects_Allocator_lock();
_RTEMS_Lock_allocator();
the_region = _Region_Get( id ); the_region = _Region_Get_and_lock( id );
if ( the_region != NULL ) { if ( the_region == NULL ) {
if ( the_region->number_of_used_blocks != 0 ) { _Objects_Allocator_unlock();
status = RTEMS_RESOURCE_IN_USE; return RTEMS_INVALID_ID;
} else {
_Objects_Close( &_Region_Information, &the_region->Object );
_Region_Free( the_region );
status = RTEMS_SUCCESSFUL;
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); if ( the_region->number_of_used_blocks != 0 ) {
status = RTEMS_RESOURCE_IN_USE;
} else {
_Objects_Close( &_Region_Information, &the_region->Object );
_Region_Free( the_region );
status = RTEMS_SUCCESSFUL;
}
_Region_Unlock( the_region );
_Objects_Allocator_unlock(); _Objects_Allocator_unlock();
return status; return status;
} }

View File

@@ -34,29 +34,27 @@ rtems_status_code rtems_region_extend(
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
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;
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ADDRESS;
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); 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;
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ADDRESS;
}
_Region_Unlock( the_region );
return status; return status;
} }

View File

@@ -27,25 +27,21 @@ rtems_status_code rtems_region_get_free_information(
Heap_Information_block *the_info Heap_Information_block *the_info
) )
{ {
rtems_status_code status; Region_Control *the_region;
Region_Control *the_region;
if ( the_info == NULL ) { if ( the_info == NULL ) {
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
memset( &the_info->Used, 0, sizeof( the_info->Used ) );
_Heap_Get_free_information( &the_region->Memory, &the_info->Free );
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); memset( &the_info->Used, 0, sizeof( the_info->Used ) );
return status; _Heap_Get_free_information( &the_region->Memory, &the_info->Free );
_Region_Unlock( the_region );
return RTEMS_SUCCESSFUL;
} }

View File

@@ -25,24 +25,20 @@ rtems_status_code rtems_region_get_information(
Heap_Information_block *the_info Heap_Information_block *the_info
) )
{ {
rtems_status_code status; Region_Control *the_region;
Region_Control *the_region;
if ( the_info == NULL ) { if ( the_info == NULL ) {
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
_Heap_Get_information( &the_region->Memory, the_info );
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); _Heap_Get_information( &the_region->Memory, the_info );
return status;
_Region_Unlock( the_region );
return RTEMS_SUCCESSFUL;
} }

View File

@@ -44,60 +44,58 @@ rtems_status_code rtems_region_get_segment(
return RTEMS_INVALID_SIZE; return RTEMS_INVALID_SIZE;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
if ( size > the_region->maximum_segment_size ) {
status = RTEMS_INVALID_SIZE;
} else {
void *the_segment;
the_segment = _Region_Allocate_segment( the_region, size );
if ( the_segment != NULL ) {
the_region->number_of_used_blocks += 1;
*segment = the_segment;
status = RTEMS_SUCCESSFUL;
} else if ( _Options_Is_no_wait( option_set ) ) {
status = RTEMS_UNSATISFIED;
} else {
Per_CPU_Control *cpu_self;
Thread_Control *executing;
/*
* 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: This is a home grown condition variable */
cpu_self = _Thread_Dispatch_disable();
_RTEMS_Unlock_allocator();
executing = _Per_CPU_Get_executing( cpu_self );
executing->Wait.count = size;
executing->Wait.return_argument = segment;
_Thread_queue_Enqueue(
&the_region->Wait_queue,
the_region->wait_operations,
executing,
STATES_WAITING_FOR_SEGMENT,
timeout,
RTEMS_TIMEOUT
);
_Thread_Dispatch_enable( cpu_self );
return (rtems_status_code) executing->Wait.return_code;
}
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); if ( size > the_region->maximum_segment_size ) {
status = RTEMS_INVALID_SIZE;
} else {
void *the_segment;
the_segment = _Region_Allocate_segment( the_region, size );
if ( the_segment != NULL ) {
the_region->number_of_used_blocks += 1;
*segment = the_segment;
status = RTEMS_SUCCESSFUL;
} else if ( _Options_Is_no_wait( option_set ) ) {
status = RTEMS_UNSATISFIED;
} else {
Per_CPU_Control *cpu_self;
Thread_Control *executing;
/*
* 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: This is a home grown condition variable */
cpu_self = _Thread_Dispatch_disable();
_Region_Unlock( the_region );
executing = _Per_CPU_Get_executing( cpu_self );
executing->Wait.count = size;
executing->Wait.return_argument = segment;
_Thread_queue_Enqueue(
&the_region->Wait_queue,
the_region->wait_operations,
executing,
STATES_WAITING_FOR_SEGMENT,
timeout,
RTEMS_TIMEOUT
);
_Thread_Dispatch_enable( cpu_self );
return (rtems_status_code) executing->Wait.return_code;
}
}
_Region_Unlock( the_region );
return status; return status;
} }

View File

@@ -37,20 +37,18 @@ rtems_status_code rtems_region_get_segment_size(
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
if ( _Heap_Size_of_alloc_area( &the_region->Memory, segment, size ) ) {
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ADDRESS;
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); if ( _Heap_Size_of_alloc_area( &the_region->Memory, segment, size ) ) {
status = RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ADDRESS;
}
_Region_Unlock( the_region );
return status; return status;
} }

View File

@@ -40,7 +40,7 @@ void _Region_Process_queue(
* switch could occur. * switch could occur.
*/ */
cpu_self = _Thread_Dispatch_disable(); cpu_self = _Thread_Dispatch_disable();
_RTEMS_Unlock_allocator(); _Region_Unlock( the_region );
/* /*
* NOTE: The following loop is O(n) where n is the number of * NOTE: The following loop is O(n) where n is the number of

View File

@@ -37,38 +37,36 @@ rtems_status_code rtems_region_resize_segment(
return RTEMS_INVALID_ADDRESS; return RTEMS_INVALID_ADDRESS;
} }
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
resize_status = _Heap_Resize_block(
&the_region->Memory,
segment,
(uint32_t) size,
&osize,
&avail_size
);
*old_size = (uint32_t) osize;
switch ( resize_status ) {
case HEAP_RESIZE_SUCCESSFUL:
/* Unlocks allocator */
_Region_Process_queue( the_region );
return RTEMS_SUCCESSFUL;
case HEAP_RESIZE_UNSATISFIED:
status = RTEMS_UNSATISFIED;
break;
default:
status = RTEMS_INVALID_ADDRESS;
break;
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); resize_status = _Heap_Resize_block(
&the_region->Memory,
segment,
(uint32_t) size,
&osize,
&avail_size
);
*old_size = (uint32_t) osize;
switch ( resize_status ) {
case HEAP_RESIZE_SUCCESSFUL:
/* Unlocks allocator */
_Region_Process_queue( the_region );
return RTEMS_SUCCESSFUL;
case HEAP_RESIZE_UNSATISFIED:
status = RTEMS_UNSATISFIED;
break;
default:
status = RTEMS_INVALID_ADDRESS;
break;
}
_Region_Unlock( the_region );
return status; return status;
} }

View File

@@ -25,27 +25,22 @@ rtems_status_code rtems_region_return_segment(
void *segment void *segment
) )
{ {
rtems_status_code status; Region_Control *the_region;
Region_Control *the_region;
_RTEMS_Lock_allocator(); the_region = _Region_Get_and_lock( id );
the_region = _Region_Get( id ); if ( the_region == NULL ) {
return RTEMS_INVALID_ID;
if ( the_region != NULL ) {
if ( _Region_Free_segment( the_region, segment ) ) {
the_region->number_of_used_blocks -= 1;
/* Unlocks allocator */
_Region_Process_queue( the_region );
return RTEMS_SUCCESSFUL;
} else {
status = RTEMS_INVALID_ADDRESS;
}
} else {
status = RTEMS_INVALID_ID;
} }
_RTEMS_Unlock_allocator(); if ( _Region_Free_segment( the_region, segment ) ) {
return status; the_region->number_of_used_blocks -= 1;
/* Unlocks allocator */
_Region_Process_queue( the_region );
return RTEMS_SUCCESSFUL;
}
_Region_Unlock( the_region );
return RTEMS_INVALID_ADDRESS;
} }