[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