forked from Imagelibrary/rtems
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:
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ***
|
||||
|
||||
Reference in New Issue
Block a user