score: Freechain handler API changes

Replace the extend function with an allocator since this fits better
to the current use case.
This commit is contained in:
Sebastian Huber
2015-06-24 14:00:08 +02:00
parent cb2b8f02dd
commit fdb45d6b26
6 changed files with 111 additions and 240 deletions

View File

@@ -156,11 +156,7 @@ RTEMS_INLINE_ROUTINE POSIX_Keys_Control *_POSIX_Keys_Get (
_Objects_Get( &_POSIX_Keys_Information, (Objects_Id) id, location ); _Objects_Get( &_POSIX_Keys_Information, (Objects_Id) id, location );
} }
RTEMS_INLINE_ROUTINE POSIX_Keys_Key_value_pair * POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void );
_POSIX_Keys_Key_value_pair_allocate( void )
{
return (POSIX_Keys_Key_value_pair *) _Freechain_Get( &_POSIX_Keys_Keypool );
}
RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_pair_free( RTEMS_INLINE_ROUTINE void _POSIX_Keys_Key_value_pair_free(
POSIX_Keys_Key_value_pair *key_value_pair POSIX_Keys_Key_value_pair *key_value_pair

View File

@@ -92,49 +92,24 @@ static uint32_t _POSIX_Keys_Get_initial_keypool_size( void )
return _Objects_Maximum_per_allocation( max ); return _Objects_Maximum_per_allocation( max );
} }
static bool _POSIX_Keys_Keypool_extend( Freechain_Control *keypool )
{
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;
}
static void _POSIX_Keys_Initialize_keypool( void ) static void _POSIX_Keys_Initialize_keypool( void )
{ {
Freechain_Control *keypool = &_POSIX_Keys_Keypool; _Freechain_Initialize(
size_t initial_count = _POSIX_Keys_Get_initial_keypool_size(); &_POSIX_Keys_Keypool,
_Workspace_Allocate_or_fatal_error,
_Freechain_Initialize( keypool, _POSIX_Keys_Keypool_extend ); _POSIX_Keys_Get_initial_keypool_size(),
sizeof( POSIX_Keys_Key_value_pair )
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 ); POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void )
{
_Chain_Initialize( return (POSIX_Keys_Key_value_pair *) _Freechain_Get(
&keypool->Freechain, &_POSIX_Keys_Keypool,
nodes, _Workspace_Allocate,
initial_count, _POSIX_Keys_Get_keypool_bump_count(),
sizeof( *nodes ) sizeof( POSIX_Keys_Key_value_pair )
); );
}
} }
/** /**

View File

@@ -16,8 +16,7 @@
#ifndef _RTEMS_SCORE_FREECHAIN_H #ifndef _RTEMS_SCORE_FREECHAIN_H
#define _RTEMS_SCORE_FREECHAIN_H #define _RTEMS_SCORE_FREECHAIN_H
#include <stdbool.h> #include <rtems/score/basedefs.h>
#include <rtems/score/chain.h> #include <rtems/score/chain.h>
#ifdef __cplusplus #ifdef __cplusplus
@@ -36,27 +35,20 @@ extern "C" {
* @{ * @{
*/ */
typedef struct Freechain_Control Freechain_Control; /**
* @brief Allocator function.
*/
typedef void *( *Freechain_Allocator )( size_t size );
/** /**
* @brief Extends the freechain. * @brief The freechain control.
*
* @param[in] freechain The freechain control.
*
* @retval true The freechain contains now at least one node.
* @retval false Otherwise.
*/ */
typedef bool ( *Freechain_Extend )( Freechain_Control *freechain ); typedef struct {
/**
/** * @brief Chain of free nodes.
* @typedef Freechain_Control
*
* This is used to manage freechain's nodes.
*/ */
struct Freechain_Control { Chain_Control Free;
Chain_Control Freechain; } Freechain_Control;
Freechain_Extend extend;
};
/** /**
* @brief Initializes a freechain. * @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 * of nodes. In case the freechain is empty the extend handler is called to
* get more nodes. * get more nodes.
* *
* @param[in,out] freechain The freechain control to initialize. * @param[in] freechain The freechain control to initialize.
* @param[in] extend The extend handler. It is called by _Freechain_Get() in * @param[in] allocator The allocator function.
* case the freechain is empty. * @param[in] number_nodes The initial number of nodes.
* @param[in] node_size The node size.
*/ */
void _Freechain_Initialize( void _Freechain_Initialize(
Freechain_Control *freechain, Freechain_Control *freechain,
Freechain_Extend extend Freechain_Allocator allocator,
size_t number_nodes,
size_t node_size
); );
/** /**
* @brief Gets a node from the freechain. * @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 NULL The freechain is empty and the extend operation failed.
* @retval otherwise Pointer to a node. The node ownership passes to the * @retval otherwise Pointer to a node. The node ownership passes to the
* caller. * caller.
*/ */
void *_Freechain_Get( 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. * @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. * @param[in] node The node to put back.
*/ */
void _Freechain_Put( void _Freechain_Put(

View File

@@ -19,29 +19,60 @@
#endif #endif
#include <rtems/score/freechain.h> #include <rtems/score/freechain.h>
#include <rtems/score/assert.h>
#include <rtems/score/chainimpl.h> #include <rtems/score/chainimpl.h>
void _Freechain_Initialize( void _Freechain_Initialize(
Freechain_Control *freechain, Freechain_Control *freechain,
Freechain_Extend extend Freechain_Allocator allocator,
size_t number_nodes,
size_t node_size
) )
{ {
_Chain_Initialize_empty( &freechain->Freechain ); void *starting_address;
freechain->extend = extend;
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 ) ) { _Assert( node_size >= sizeof( Chain_Node ) );
if ( !( *freechain->extend )( freechain ) ) {
return NULL; 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 ) void _Freechain_Put( Freechain_Control *freechain, void *node )
{ {
_Chain_Prepend_unprotected( &freechain->Freechain, node ); _Chain_Prepend_unprotected( &freechain->Free, node );
} }

View File

@@ -13,171 +13,43 @@
#include <tmacros.h> #include <tmacros.h>
#include <rtems/score/chainimpl.h> #include <rtems/score/chainimpl.h>
#include <rtems/score/freechain.h> #include <rtems/score/freechain.h>
#include <rtems/score/wkspace.h>
#include <rtems/malloc.h>
const char rtems_test_name[] = "SPFREECHAIN 1"; 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 { typedef struct {
Freechain_Control super_fc; Chain_Node Node;
size_t bump_count;
} MyFreechain;
typedef struct {
Chain_Node ch_node;
int x; int x;
} test_node; } test_node;
bool my_freechain_extend_with_nothing( Freechain_Control *freechain ) static rtems_task Init(rtems_task_argument ignored)
{ {
return NULL; Freechain_Control fc;
} test_node *node;
/* user defined extend handle, it allocates memory on heap. */
bool my_freechain_extend_heap( 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 = 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;
}
/* 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;
}
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)
);
}
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)
);
}
rtems_task Init(
rtems_task_argument ignored
)
{
TEST_BEGIN(); TEST_BEGIN();
test_node *test_node_p; _Freechain_Initialize(&fc, NULL, 0, sizeof(test_node));
MyFreechain myfc; rtems_test_assert(_Chain_Is_empty(&fc.Free));
Freechain_Control *fc_p = (Freechain_Control *)&myfc;
int i; _Freechain_Initialize(&fc, malloc, 1, SIZE_MAX);
rtems_test_assert(_Chain_Is_empty(&fc.Free));
rtems_test_assert(_Freechain_Get(&fc, NULL, 0, sizeof(test_node)) == NULL);
rtems_test_assert(_Freechain_Get(&fc, malloc, 1, SIZE_MAX) == NULL);
/* check whether freechain put and get works correctly*/ /* 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" ); puts( "INIT - Get node from freechain - OK" );
test_node_p = (test_node *)_Freechain_Get(fc_p); node = _Freechain_Get(&fc, malloc, 1, sizeof(test_node));
test_node_p->x = 1; node->x = 1;
puts( "INIT - Put node back to freechain - OK" ); 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" ); puts( "INIT - Verify freechain node put and get - OK" );
test_node_p = (test_node *)_Freechain_Get(fc_p); node = _Freechain_Get(&fc, NULL, 0, sizeof(test_node));
if(test_node_p->x != 1) { rtems_test_assert(node->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);
}
}
TEST_END(); TEST_END();
rtems_test_exit(0); rtems_test_exit(0);
@@ -188,7 +60,6 @@ rtems_task Init(
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_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_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE #define CONFIGURE_RTEMS_INIT_TASKS_TABLE

View File

@@ -1,9 +1,5 @@
*** START OF RTEMS FREECHAIN API TEST *** *** BEGIN OF TEST SPFREECHAIN 1 ***
INIT - Get node from freechain - OK 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 - Verify freechain node put and get - OK
INIT - Get more than intialized nodes from freechain on heap - OK *** END OF TEST SPFREECHAIN 1 ***
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 ***