rtems: Avoid Giant lock for partitions

Use an ISR lock to protect the partition state changes.

Update #2555.
This commit is contained in:
Sebastian Huber
2016-04-06 09:08:22 +02:00
parent 84f5c0a91b
commit 3570ec684f
6 changed files with 97 additions and 67 deletions
+3
View File
@@ -34,6 +34,7 @@
#include <rtems/rtems/attr.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/types.h>
#include <rtems/score/isrlock.h>
#ifdef __cplusplus
extern "C" {
@@ -55,6 +56,8 @@ extern "C" {
typedef struct {
/** This field is the object management portion of a Partition instance. */
Objects_Control Object;
/** This field is the lock of the Partition. */
ISR_LOCK_MEMBER( Lock )
/** This field is the physical starting address of the Partition. */
void *starting_address;
/** This field is the size of the Partition in bytes. */
+57 -16
View File
@@ -50,7 +50,7 @@ RTEMS_INLINE_ROUTINE void *_Partition_Allocate_buffer (
Partition_Control *the_partition
)
{
return _Chain_Get( &the_partition->Memory );
return _Chain_Get_unprotected( &the_partition->Memory );
}
/**
@@ -63,7 +63,7 @@ RTEMS_INLINE_ROUTINE void _Partition_Free_buffer (
Chain_Node *the_buffer
)
{
_Chain_Append( &the_partition->Memory, the_buffer );
_Chain_Append_unprotected( &the_partition->Memory, the_buffer );
}
/**
@@ -136,6 +136,37 @@ RTEMS_INLINE_ROUTINE Partition_Control *_Partition_Allocate ( void )
return (Partition_Control *) _Objects_Allocate( &_Partition_Information );
}
RTEMS_INLINE_ROUTINE void _Partition_Initialize(
Partition_Control *the_partition,
void *starting_address,
uint32_t length,
uint32_t buffer_size,
rtems_attribute attribute_set
)
{
the_partition->starting_address = starting_address;
the_partition->length = length;
the_partition->buffer_size = buffer_size;
the_partition->attribute_set = attribute_set;
the_partition->number_of_used_blocks = 0;
_Chain_Initialize(
&the_partition->Memory,
starting_address,
length / buffer_size,
buffer_size
);
_ISR_lock_Initialize( &the_partition->Lock, "Partition" );
}
RTEMS_INLINE_ROUTINE void _Partition_Destroy(
Partition_Control *the_partition
)
{
_ISR_lock_Destroy( &the_partition->Lock );
}
/**
* @brief Frees a partition control block to the
* inactive chain of free partition control blocks.
@@ -150,24 +181,34 @@ RTEMS_INLINE_ROUTINE void _Partition_Free (
_Objects_Free( &_Partition_Information, &the_partition->Object );
}
/**
* @brief Maps partition IDs to partition control blocks.
*
* This function maps partition IDs to partition control blocks.
* If ID corresponds to a local partition, then it returns
* the_partition control pointer which maps to ID and location
* is set to OBJECTS_LOCAL. If the partition ID is global and
* resides on a remote node, then location is set to OBJECTS_REMOTE,
* and the_partition is undefined. Otherwise, location is set
* to OBJECTS_ERROR and the_partition is undefined.
*/
RTEMS_INLINE_ROUTINE Partition_Control *_Partition_Get (
Objects_Id id,
Objects_Locations *location
Objects_Locations *location,
ISR_lock_Context *lock_context
)
{
return (Partition_Control *)
_Objects_Get( &_Partition_Information, id, location );
return (Partition_Control *) _Objects_Get_isr_disable(
&_Partition_Information,
id,
location,
lock_context
);
}
RTEMS_INLINE_ROUTINE void _Partition_Acquire_critical(
Partition_Control *the_partition,
ISR_lock_Context *lock_context
)
{
_ISR_lock_Acquire( &the_partition->Lock, lock_context );
}
RTEMS_INLINE_ROUTINE void _Partition_Release(
Partition_Control *the_partition,
ISR_lock_Context *lock_context
)
{
_ISR_lock_Release_and_ISR_enable( &the_partition->Lock, lock_context );
}
/**@}*/
+7 -8
View File
@@ -94,14 +94,13 @@ rtems_status_code rtems_partition_create(
}
#endif
the_partition->starting_address = starting_address;
the_partition->length = length;
the_partition->buffer_size = buffer_size;
the_partition->attribute_set = attribute_set;
the_partition->number_of_used_blocks = 0;
_Chain_Initialize( &the_partition->Memory, starting_address,
length / buffer_size, buffer_size );
_Partition_Initialize(
the_partition,
starting_address,
length,
buffer_size,
attribute_set
);
_Objects_Open(
&_Partition_Information,
+10 -6
View File
@@ -20,20 +20,22 @@
#include <rtems/rtems/partimpl.h>
#include <rtems/rtems/attrimpl.h>
#include <rtems/score/threaddispatch.h>
rtems_status_code rtems_partition_delete(
rtems_id id
)
{
Partition_Control *the_partition;
Objects_Locations location;
Partition_Control *the_partition;
Objects_Locations location;
ISR_lock_Context lock_context;
_Objects_Allocator_lock();
the_partition = _Partition_Get( id, &location );
the_partition = _Partition_Get( id, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
_Partition_Acquire_critical( the_partition, &lock_context );
if ( the_partition->number_of_used_blocks == 0 ) {
_Objects_Close( &_Partition_Information, &the_partition->Object );
#if defined(RTEMS_MULTIPROCESSING)
@@ -53,12 +55,14 @@ rtems_status_code rtems_partition_delete(
}
#endif
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
_Partition_Destroy( the_partition );
_Partition_Free( the_partition );
_Objects_Allocator_unlock();
return RTEMS_SUCCESSFUL;
}
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
_Objects_Allocator_unlock();
return RTEMS_RESOURCE_IN_USE;
+11 -12
View File
@@ -18,37 +18,36 @@
#include "config.h"
#endif
#include <rtems/system.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/support.h>
#include <rtems/score/address.h>
#include <rtems/rtems/partimpl.h>
#include <rtems/score/thread.h>
rtems_status_code rtems_partition_get_buffer(
rtems_id id,
void **buffer
)
{
Partition_Control *the_partition;
Objects_Locations location;
void *the_buffer;
Partition_Control *the_partition;
Objects_Locations location;
ISR_lock_Context lock_context;
void *the_buffer;
if ( !buffer )
return RTEMS_INVALID_ADDRESS;
the_partition = _Partition_Get( id, &location );
the_partition = _Partition_Get( id, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
_Partition_Acquire_critical( the_partition, &lock_context );
the_buffer = _Partition_Allocate_buffer( the_partition );
if ( the_buffer ) {
if ( the_buffer != NULL ) {
the_partition->number_of_used_blocks += 1;
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
*buffer = the_buffer;
return RTEMS_SUCCESSFUL;
}
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
return RTEMS_UNSATISFIED;
#if defined(RTEMS_MULTIPROCESSING)
+9 -25
View File
@@ -14,47 +14,31 @@
#include "config.h"
#endif
#include <rtems/system.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/support.h>
#include <rtems/score/address.h>
#include <rtems/rtems/partimpl.h>
#include <rtems/score/thread.h>
/*
* rtems_partition_return_buffer
*
* This directive will return the given buffer to the specified
* buffer partition.
*
* Input parameters:
* id - partition id
* buffer - pointer to buffer address
*
* Output parameters:
* RTEMS_SUCCESSFUL - if successful
* error code - if unsuccessful
*/
rtems_status_code rtems_partition_return_buffer(
rtems_id id,
void *buffer
)
{
Partition_Control *the_partition;
Objects_Locations location;
Partition_Control *the_partition;
Objects_Locations location;
ISR_lock_Context lock_context;
the_partition = _Partition_Get( id, &location );
the_partition = _Partition_Get( id, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
_Partition_Acquire_critical( the_partition, &lock_context );
if ( _Partition_Is_buffer_valid( buffer, the_partition ) ) {
_Partition_Free_buffer( the_partition, buffer );
the_partition->number_of_used_blocks -= 1;
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
return RTEMS_SUCCESSFUL;
}
_Objects_Put( &the_partition->Object );
_Partition_Release( the_partition, &lock_context );
return RTEMS_INVALID_ADDRESS;
#if defined(RTEMS_MULTIPROCESSING)