[PATCH 07/15] rtems: Avoid Giant lock for partitions
Sebastian Huber
sebastian.huber at embedded-brains.de
Tue Apr 5 13:09:52 UTC 2016
Use an ISR lock to protect the partition state changes.
Update #2555.
---
cpukit/rtems/include/rtems/rtems/part.h | 3 ++
cpukit/rtems/include/rtems/rtems/partimpl.h | 73 ++++++++++++++++++++++-------
cpukit/rtems/src/partcreate.c | 15 +++---
cpukit/rtems/src/partdelete.c | 16 ++++---
cpukit/rtems/src/partgetbuffer.c | 23 +++++----
cpukit/rtems/src/partreturnbuffer.c | 34 ++++----------
6 files changed, 97 insertions(+), 67 deletions(-)
diff --git a/cpukit/rtems/include/rtems/rtems/part.h b/cpukit/rtems/include/rtems/rtems/part.h
index 7dd90a9..5b840cc 100644
--- a/cpukit/rtems/include/rtems/rtems/part.h
+++ b/cpukit/rtems/include/rtems/rtems/part.h
@@ -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. */
diff --git a/cpukit/rtems/include/rtems/rtems/partimpl.h b/cpukit/rtems/include/rtems/rtems/partimpl.h
index 472e06f..0ce7622 100644
--- a/cpukit/rtems/include/rtems/rtems/partimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/partimpl.h
@@ -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_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
)
{
- return (Partition_Control *)
- _Objects_Get( &_Partition_Information, id, location );
+ _ISR_lock_Release_and_ISR_enable( &the_partition->Lock, lock_context );
}
/**@}*/
diff --git a/cpukit/rtems/src/partcreate.c b/cpukit/rtems/src/partcreate.c
index e3544e7..c058adf 100644
--- a/cpukit/rtems/src/partcreate.c
+++ b/cpukit/rtems/src/partcreate.c
@@ -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,
diff --git a/cpukit/rtems/src/partdelete.c b/cpukit/rtems/src/partdelete.c
index 032f73d..2df3893 100644
--- a/cpukit/rtems/src/partdelete.c
+++ b/cpukit/rtems/src/partdelete.c
@@ -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;
diff --git a/cpukit/rtems/src/partgetbuffer.c b/cpukit/rtems/src/partgetbuffer.c
index 3a7e8bf..39cac5e 100644
--- a/cpukit/rtems/src/partgetbuffer.c
+++ b/cpukit/rtems/src/partgetbuffer.c
@@ -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)
diff --git a/cpukit/rtems/src/partreturnbuffer.c b/cpukit/rtems/src/partreturnbuffer.c
index 2cccc3c..641abed 100644
--- a/cpukit/rtems/src/partreturnbuffer.c
+++ b/cpukit/rtems/src/partreturnbuffer.c
@@ -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)
--
1.8.4.5
More information about the devel
mailing list