[PATCH 1/2] score: Freechain handler API changes

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Jun 30 13:29:35 UTC 2015


Replace the extend function with an allocator since this fits better
to the current use case.
---
 cpukit/posix/include/rtems/posix/keyimpl.h         |   6 +-
 cpukit/posix/src/key.c                             |  53 ++-----
 cpukit/score/include/rtems/score/freechain.h       |  54 +++----
 cpukit/score/src/freechain.c                       |  53 +++++--
 testsuites/sptests/spfreechain01/init.c            | 161 ++-------------------
 testsuites/sptests/spfreechain01/spfreechain01.scn |  10 +-
 6 files changed, 104 insertions(+), 233 deletions(-)

diff --git a/cpukit/posix/include/rtems/posix/keyimpl.h b/cpukit/posix/include/rtems/posix/keyimpl.h
index a5c80d6..6fd4d13 100644
--- a/cpukit/posix/include/rtems/posix/keyimpl.h
+++ b/cpukit/posix/include/rtems/posix/keyimpl.h
@@ -156,11 +156,7 @@ RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get (
     _Objects_Get( &_POSIX_Keys_Information, (Objects_Id) id, location );
 }
 
-RTEMS_INLINE_ROUTINE POSIX_Keys_Key_value_pair *
-_POSIX_Keys_Key_value_pair_allocate( void )
-{
-  return (POSIX_Keys_Key_value_pair *) _Freechain_Get( &_POSIX_Keys_Keypool );
-}
+POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void );
 
 RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_pair_free(
   POSIX_Keys_Key_value_pair *key_value_pair
diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c
index 6753d57..55c65900 100644
--- a/cpukit/posix/src/key.c
+++ b/cpukit/posix/src/key.c
@@ -92,49 +92,24 @@ static uint32_t _POSIX_Keys_Get_initial_keypool_size( void )
   return _Objects_Maximum_per_allocation( max );
 }
 
-static bool _POSIX_Keys_Keypool_extend( Freechain_Control *keypool )
+static void _POSIX_Keys_Initialize_keypool( void )
 {
-  size_t bump_count = _POSIX_Keys_Get_keypool_bump_count();
-  bool ok = bump_count > 0;
-
-  if ( ok ) {
-    size_t size = bump_count * sizeof( POSIX_Keys_Key_value_pair );
-    POSIX_Keys_Key_value_pair *nodes = _Workspace_Allocate( size );
-
-    ok = nodes != NULL;
-
-    if ( ok ) {
-      _Chain_Initialize(
-        &keypool->Freechain,
-        nodes,
-        bump_count,
-        sizeof( *nodes )
-      );
-    }
-  }
-
-  return ok;
+  _Freechain_Initialize(
+    &_POSIX_Keys_Keypool,
+    _Workspace_Allocate_or_fatal_error,
+    _POSIX_Keys_Get_initial_keypool_size(),
+    sizeof( POSIX_Keys_Key_value_pair )
+  );
 }
 
-static void _POSIX_Keys_Initialize_keypool( void )
+POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void )
 {
-  Freechain_Control *keypool = &_POSIX_Keys_Keypool;
-  size_t initial_count = _POSIX_Keys_Get_initial_keypool_size();
-
-  _Freechain_Initialize( keypool, _POSIX_Keys_Keypool_extend );
-
-  if ( initial_count > 0 ) {
-    size_t size = initial_count * sizeof( POSIX_Keys_Key_value_pair );
-    POSIX_Keys_Key_value_pair *nodes =
-      _Workspace_Allocate_or_fatal_error( size );
-
-    _Chain_Initialize(
-      &keypool->Freechain,
-      nodes,
-      initial_count,
-      sizeof( *nodes )
-    );
-  }
+  return (POSIX_Keys_Key_value_pair *) _Freechain_Get(
+    &_POSIX_Keys_Keypool,
+    _Workspace_Allocate,
+    _POSIX_Keys_Get_keypool_bump_count(),
+    sizeof( POSIX_Keys_Key_value_pair )
+  );
 }
 
 /**
diff --git a/cpukit/score/include/rtems/score/freechain.h b/cpukit/score/include/rtems/score/freechain.h
index d68a1f7..7fa580a 100644
--- a/cpukit/score/include/rtems/score/freechain.h
+++ b/cpukit/score/include/rtems/score/freechain.h
@@ -16,8 +16,7 @@
 #ifndef _RTEMS_SCORE_FREECHAIN_H
 #define _RTEMS_SCORE_FREECHAIN_H
 
-#include <stdbool.h>
-
+#include <rtems/score/basedefs.h>
 #include <rtems/score/chain.h>
 
 #ifdef __cplusplus
@@ -36,27 +35,20 @@ extern "C" {
  * @{
  */
 
-typedef struct Freechain_Control Freechain_Control;
-
 /**
- * @brief Extends the freechain.
- *
- * @param[in] freechain The freechain control.
- *
- * @retval true The freechain contains now at least one node.
- * @retval false Otherwise.
+ * @brief Allocator function.
  */
-typedef bool ( *Freechain_Extend )( Freechain_Control *freechain );
+typedef void *( *Freechain_Allocator )( size_t size );
 
 /**
- * @typedef Freechain_Control
- *
- * This is used to manage freechain's nodes.
+ * @brief The freechain control.
  */
-struct Freechain_Control {
-  Chain_Control     Freechain;
-  Freechain_Extend  extend;
-};
+typedef struct {
+  /**
+   * @brief Chain of free nodes.
+   */
+  Chain_Control Free;
+} Freechain_Control;
 
 /**
  * @brief Initializes a freechain.
@@ -65,32 +57,42 @@ struct Freechain_Control {
  * of nodes.  In case the freechain is empty the extend handler is called to
  * get more nodes.
  *
- * @param[in,out] freechain The freechain control to initialize.
- * @param[in] extend The extend handler.  It is called by _Freechain_Get() in
- * case the freechain is empty.
+ * @param[in] freechain The freechain control to initialize.
+ * @param[in] allocator The allocator function.
+ * @param[in] number_nodes The initial number of nodes.
+ * @param[in] node_size The node size.
  */
 void _Freechain_Initialize(
-  Freechain_Control *freechain,
-  Freechain_Extend   extend
+  Freechain_Control   *freechain,
+  Freechain_Allocator  allocator,
+  size_t               number_nodes,
+  size_t               node_size
 );
 
 /**
  * @brief Gets a node from the freechain.
  *
- * @param[in,out] freechain The freechain control.
+ * @param[in] freechain The freechain control.
+ * @param[in] allocator The allocator function.
+ * @param[in] number_nodes_to_extend The number of nodes in case an extend is
+ *   necessary due to an empty freechain.
+ * @param[in] node_size The node size.
  *
  * @retval NULL The freechain is empty and the extend operation failed.
  * @retval otherwise Pointer to a node.  The node ownership passes to the
  * caller.
  */
 void *_Freechain_Get(
-  Freechain_Control *freechain
+  Freechain_Control   *freechain,
+  Freechain_Allocator  allocator,
+  size_t               number_nodes_to_extend,
+  size_t               node_size
 );
 
 /**
  * @brief Puts a node back onto the freechain.
  *
- * @param[in,out] freechain The freechain control.
+ * @param[in] freechain The freechain control.
  * @param[in] node The node to put back.
  */
 void _Freechain_Put(
diff --git a/cpukit/score/src/freechain.c b/cpukit/score/src/freechain.c
index 58935fa..84b4c63 100644
--- a/cpukit/score/src/freechain.c
+++ b/cpukit/score/src/freechain.c
@@ -19,29 +19,60 @@
 #endif
 
 #include <rtems/score/freechain.h>
+#include <rtems/score/assert.h>
 #include <rtems/score/chainimpl.h>
 
 void _Freechain_Initialize(
-    Freechain_Control *freechain,
-    Freechain_Extend   extend
+  Freechain_Control   *freechain,
+  Freechain_Allocator  allocator,
+  size_t               number_nodes,
+  size_t               node_size
 )
 {
-  _Chain_Initialize_empty( &freechain->Freechain );
-  freechain->extend = extend;
+  void *starting_address;
+
+  if ( number_nodes > 0 ) {
+    starting_address = ( *allocator )( number_nodes * node_size );
+    number_nodes *= ( starting_address != NULL );
+  } else {
+    starting_address = NULL;
+  }
+
+  _Chain_Initialize(
+    &freechain->Free,
+    starting_address,
+    number_nodes,
+    node_size
+  );
 }
 
-void *_Freechain_Get(Freechain_Control *freechain)
+void *_Freechain_Get(
+  Freechain_Control   *freechain,
+  Freechain_Allocator  allocator,
+  size_t               number_nodes_to_extend,
+  size_t               node_size
+)
 {
-  if ( _Chain_Is_empty( &freechain->Freechain ) ) {
-    if ( !( *freechain->extend )( freechain ) ) {
-      return NULL;
-    }
+  _Assert( node_size >= sizeof( Chain_Node ) );
+
+  if ( _Chain_Is_empty( &freechain->Free ) && number_nodes_to_extend > 0 ) {
+    void *starting_address;
+
+    starting_address = ( *allocator )( number_nodes_to_extend * node_size );
+    number_nodes_to_extend *= ( starting_address != NULL );
+
+    _Chain_Initialize(
+      &freechain->Free,
+      starting_address,
+      number_nodes_to_extend,
+      node_size
+    );
   }
 
-  return _Chain_Get_first_unprotected( &freechain->Freechain );
+  return _Chain_Get_unprotected( &freechain->Free );
 }
 
 void _Freechain_Put( Freechain_Control *freechain, void *node )
 {
-  _Chain_Prepend_unprotected( &freechain->Freechain, node );
+  _Chain_Prepend_unprotected( &freechain->Free, node );
 }
diff --git a/testsuites/sptests/spfreechain01/init.c b/testsuites/sptests/spfreechain01/init.c
index 8f5e10f..8963752 100644
--- a/testsuites/sptests/spfreechain01/init.c
+++ b/testsuites/sptests/spfreechain01/init.c
@@ -13,171 +13,43 @@
 #include <tmacros.h>
 #include <rtems/score/chainimpl.h>
 #include <rtems/score/freechain.h>
-#include <rtems/score/wkspace.h>
-#include <rtems/malloc.h>
 
 const char rtems_test_name[] = "SPFREECHAIN 1";
 
-/* forward declarations to avoid warnings */
-rtems_task Init(rtems_task_argument argument);
-bool my_freechain_extend_with_nothing( Freechain_Control *freechain );
-bool my_freechain_extend_heap( Freechain_Control *freechain );
-bool my_freechain_extend_workspace( Freechain_Control *freechain );
-void my_freechain_init_heap( Freechain_Control *freechain );
-void my_freechain_init_workspace( Freechain_Control *freechain );
-
-typedef struct {
-  Freechain_Control super_fc;
-  size_t bump_count;
-} MyFreechain;
-
 typedef struct {
-  Chain_Node ch_node;
+  Chain_Node Node;
   int x;
 } test_node;
 
-bool my_freechain_extend_with_nothing( Freechain_Control *freechain )
-{
-    return NULL;
-}
-
-/* user defined extend handle, it allocates memory on heap. */
-bool my_freechain_extend_heap( Freechain_Control *freechain )
+static rtems_task Init(rtems_task_argument ignored)
 {
-  MyFreechain *self = (MyFreechain *)freechain;
-  size_t node_size = sizeof(test_node);
-  size_t size = self->bump_count * node_size;
-  int i;
-  test_node *nodes = malloc(size);
-
-  if (!nodes) {
-    printf( "INIT - Unable to allocate free chain of size: %zd\n", size );
-    return NULL;
-  }
-
-  puts( "INIT - Allocate node from heap in user defined freechain extend"
-        " - OK" );
-  for ( i = 0; i < self->bump_count; i++ ) {
-      _Freechain_Put(freechain,
-                          nodes + i);
-  }
-  return true;
-}
+    Freechain_Control fc;
+    test_node *node;
 
-/* user defined extend handle, it allocates memory on workspace. */
-bool my_freechain_extend_workspace( Freechain_Control *freechain )
-{
-  MyFreechain *self = (MyFreechain *)freechain;
-  size_t node_size = sizeof(test_node);
-  size_t size = self->bump_count * node_size;
-  int i;
-  test_node *nodes = _Workspace_Allocate(size);
-
-  if (!nodes) {
-    printf( "INIT - Unable to allocate free chain of size: %zd\n", size );
-    return NULL;
-  }
-
-  puts( "INIT - Allocate node from workspace in user defined freechain extend"
-        " - OK" );
-
-  for ( i = 0; i < self->bump_count; i++ ) {
-      _Freechain_Put(freechain,
-                          nodes + i);
-  }
-  return true;
-}
+    TEST_BEGIN();
 
-void my_freechain_init_heap( Freechain_Control *freechain )
-{
-  MyFreechain *self = (MyFreechain *)freechain;
-  self->bump_count = 5;
-  size_t size = self->bump_count * sizeof(test_node);
-  test_node *nodes = malloc(size);
-
-  _Chain_Initialize(
-    &freechain->Freechain,
-    nodes,
-    self->bump_count,
-    sizeof(test_node)
-    );
-}
+    _Freechain_Initialize(&fc, NULL, 0, sizeof(test_node));
+    rtems_test_assert(_Chain_Is_empty(&fc.Free));
 
-void my_freechain_init_workspace( Freechain_Control *freechain )
-{
-  MyFreechain *self = (MyFreechain *)freechain;
-  self->bump_count = 7;
-  size_t size = self->bump_count * sizeof(test_node);
-  test_node *nodes = _Workspace_Allocate(size);
-
-  _Chain_Initialize(
-    &freechain->Freechain,
-    nodes,
-    self->bump_count,
-    sizeof(test_node)
-    );
-}
+    _Freechain_Initialize(&fc, malloc, 1, SIZE_MAX);
+    rtems_test_assert(_Chain_Is_empty(&fc.Free));
 
-rtems_task Init(
-  rtems_task_argument ignored
-                )
-{
-    TEST_BEGIN();
+    rtems_test_assert(_Freechain_Get(&fc, NULL, 0, sizeof(test_node)) == NULL);
 
-    test_node *test_node_p;
-    MyFreechain myfc;
-    Freechain_Control *fc_p = (Freechain_Control *)&myfc;
-    int i;
+    rtems_test_assert(_Freechain_Get(&fc, malloc, 1, SIZE_MAX) == NULL);
 
     /* check whether freechain put and get works correctly*/
-    _Freechain_Initialize(fc_p,
-                          &my_freechain_extend_with_nothing);
-    my_freechain_init_heap(fc_p);
 
     puts( "INIT - Get node from freechain - OK" );
-    test_node_p = (test_node *)_Freechain_Get(fc_p);
-    test_node_p->x = 1;
+    node = _Freechain_Get(&fc, malloc, 1, sizeof(test_node));
+    node->x = 1;
 
     puts( "INIT - Put node back to freechain - OK" );
-    _Freechain_Put(fc_p, (void *)test_node_p);
+    _Freechain_Put(&fc, node);
 
     puts( "INIT - Verify freechain node put and get - OK" );
-    test_node_p = (test_node *)_Freechain_Get(fc_p);
-    if(test_node_p->x != 1) {
-      puts( "INIT - ERROR ON FREECHAIN GET AND PUT" );
-      rtems_test_exit(0);
-    }
-
-    /* check whether freechain extend handle on heap works correctly */
-    _Freechain_Initialize(fc_p,
-                          &my_freechain_extend_heap);
-    my_freechain_init_heap(fc_p);
-
-    puts( "INIT - Get more than intialized nodes from freechain on heap - OK" );
-
-    for ( i = 0; i < myfc.bump_count * 2; i++ ) {
-        test_node_p = (test_node *)_Freechain_Get(fc_p);
-        if (!test_node_p) {
-            puts( "INIT - Get node from freechain failed - FAILED" );
-            rtems_test_exit(0);
-        }
-    }
-
-    /* check whether freechain extend handle in workspace works correctly */
-    _Freechain_Initialize(fc_p,
-                          &my_freechain_extend_workspace);
-    my_freechain_init_workspace(fc_p);
-
-    puts( "INIT - Get more than intialized nodes from freechain in workspace"
-          " - OK" );
-
-    for ( i = 0; i < myfc.bump_count * 2; i++ ) {
-        test_node_p = (test_node *)_Freechain_Get(fc_p);
-        if (!test_node_p) {
-            puts( "INIT - Get node from freechain failed - FAILED" );
-            rtems_test_exit(0);
-        }
-    }
+    node = _Freechain_Get(&fc, NULL, 0, sizeof(test_node));
+    rtems_test_assert(node->x == 1);
 
     TEST_END();
     rtems_test_exit(0);
@@ -188,7 +60,6 @@ rtems_task Init(
 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
 #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
 
-#define CONFIGURE_MEMORY_OVERHEAD sizeof(test_node)
 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
 
 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
diff --git a/testsuites/sptests/spfreechain01/spfreechain01.scn b/testsuites/sptests/spfreechain01/spfreechain01.scn
index e65e90a..d6e82c8 100644
--- a/testsuites/sptests/spfreechain01/spfreechain01.scn
+++ b/testsuites/sptests/spfreechain01/spfreechain01.scn
@@ -1,9 +1,5 @@
-*** START OF RTEMS FREECHAIN API TEST ***
+*** BEGIN OF TEST SPFREECHAIN 1 ***
 INIT - Get node from freechain - OK
-INIT - Put node to freechain - OK
+INIT - Put node back to freechain - OK
 INIT - Verify freechain node put and get - OK
-INIT - Get more than intialized nodes from freechain on heap - OK
-INIT - Allocate node from heap in user defined freechain extend - OK
-INIT - Get more than intialized nodes from freechain in workspace - OK
-INIT - Allocate node from workspace in user defined freechain extend - OK
-*** END OF RTEMS FREECHAIN API TEST ***
\ No newline at end of file
+*** END OF TEST SPFREECHAIN 1 ***
-- 
1.8.4.5



More information about the devel mailing list