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 );
|
_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
|
||||||
|
|||||||
@@ -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 );
|
|
||||||
|
|
||||||
_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
|
#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 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Freechain_Control
|
* @brief Chain of free nodes.
|
||||||
*
|
|
||||||
* 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(
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_Freechain_Get(Freechain_Control *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
|
||||||
|
)
|
||||||
{
|
{
|
||||||
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 );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 ***
|
|
||||||
|
|||||||
Reference in New Issue
Block a user