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 );
}
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

View File

@@ -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 )
{
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 )
{
Freechain_Control *keypool = &_POSIX_Keys_Keypool;
size_t initial_count = _POSIX_Keys_Get_initial_keypool_size();
_Freechain_Initialize(
&_POSIX_Keys_Keypool,
_Workspace_Allocate_or_fatal_error,
_POSIX_Keys_Get_initial_keypool_size(),
sizeof( POSIX_Keys_Key_value_pair )
);
}
_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 )
);
}
POSIX_Keys_Key_value_pair * _POSIX_Keys_Key_value_pair_allocate( void )
{
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 )
);
}
/**

View File

@@ -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 Allocator function.
*/
typedef void *( *Freechain_Allocator )( size_t size );
/**
* @brief Extends the freechain.
*
* @param[in] freechain The freechain control.
*
* @retval true The freechain contains now at least one node.
* @retval false Otherwise.
* @brief The freechain control.
*/
typedef bool ( *Freechain_Extend )( Freechain_Control *freechain );
/**
* @typedef Freechain_Control
*
* This is used to manage freechain's nodes.
*/
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(

View File

@@ -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;
void *_Freechain_Get(Freechain_Control *freechain)
{
if ( _Chain_Is_empty( &freechain->Freechain ) ) {
if ( !( *freechain->extend )( freechain ) ) {
return NULL;
}
if ( number_nodes > 0 ) {
starting_address = ( *allocator )( number_nodes * node_size );
number_nodes *= ( starting_address != NULL );
} else {
starting_address = NULL;
}
return _Chain_Get_first_unprotected( &freechain->Freechain );
_Chain_Initialize(
&freechain->Free,
starting_address,
number_nodes,
node_size
);
}
void *_Freechain_Get(
Freechain_Control *freechain,
Freechain_Allocator allocator,
size_t number_nodes_to_extend,
size_t node_size
)
{
_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_unprotected( &freechain->Free );
}
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 <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 )
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_node *test_node_p;
MyFreechain myfc;
Freechain_Control *fc_p = (Freechain_Control *)&myfc;
int i;
_Freechain_Initialize(&fc, NULL, 0, sizeof(test_node));
rtems_test_assert(_Chain_Is_empty(&fc.Free));
_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*/
_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

View File

@@ -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 ***
*** END OF TEST SPFREECHAIN 1 ***