forked from Imagelibrary/rtems
419 lines
11 KiB
C
419 lines
11 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @ingroup RTEMSScoreObjectMP
|
|
*
|
|
* @brief This source file contains the definition of
|
|
* ::_Objects_Local_node, ::_Objects_Maximum_nodes,
|
|
* ::_Objects_MP_Maximum_global_objects and the implementation of
|
|
* _Objects_MP_Handler_early_initialization(),
|
|
* _Objects_MP_Handler_initialization(), _Objects_MP_Open(),
|
|
* _Objects_MP_Allocate_and_open(), _Objects_MP_Close(),
|
|
* _Objects_MP_Global_name_search(), _Objects_MP_Is_remote(),
|
|
* _Objects_MP_Allocate_global_object(), and
|
|
* _Objects_MP_Free_global_object().
|
|
*/
|
|
|
|
/*
|
|
* COPYRIGHT (c) 1989-1999.
|
|
* On-Line Applications Research Corporation (OAR).
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <rtems/score/objectimpl.h>
|
|
#include <rtems/score/interr.h>
|
|
#include <rtems/score/isrlock.h>
|
|
#include <rtems/config.h>
|
|
|
|
#define OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( node ) \
|
|
RTEMS_CONTAINER_OF( node, Objects_MP_Control, Nodes.Active.Id_lookup )
|
|
|
|
#define OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( node ) \
|
|
RTEMS_CONTAINER_OF( node, Objects_MP_Control, Nodes.Active.Name_lookup )
|
|
|
|
typedef struct {
|
|
uint32_t name;
|
|
uint32_t node;
|
|
} Objects_MP_Name_and_node;
|
|
|
|
uint16_t _Objects_Local_node;
|
|
|
|
uint16_t _Objects_Maximum_nodes;
|
|
|
|
uint32_t _Objects_MP_Maximum_global_objects;
|
|
|
|
static CHAIN_DEFINE_EMPTY( _Objects_MP_Inactive_global_objects );
|
|
|
|
ISR_LOCK_DEFINE( static, _Objects_MP_Global_lock, "MP Objects" )
|
|
|
|
static void _Objects_MP_Global_acquire( ISR_lock_Context *lock_context )
|
|
{
|
|
_ISR_lock_ISR_disable_and_acquire( &_Objects_MP_Global_lock, lock_context );
|
|
}
|
|
|
|
static void _Objects_MP_Global_release( ISR_lock_Context *lock_context )
|
|
{
|
|
_ISR_lock_Release_and_ISR_enable( &_Objects_MP_Global_lock, lock_context );
|
|
}
|
|
|
|
static bool _Objects_MP_Id_equal(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const Objects_Id *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( right );
|
|
|
|
return *the_left == the_right->id;
|
|
}
|
|
|
|
static bool _Objects_MP_Id_less(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const Objects_Id *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( right );
|
|
|
|
return *the_left < the_right->id;
|
|
}
|
|
|
|
static void *_Objects_MP_Id_map( RBTree_Node *node )
|
|
{
|
|
return OBJECTS_MP_CONTROL_OF_ID_LOOKUP_NODE( node );
|
|
}
|
|
|
|
static bool _Objects_MP_Name_equal(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const uint32_t *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
|
|
|
|
return *the_left == the_right->name;
|
|
}
|
|
|
|
static bool _Objects_MP_Name_less(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const uint32_t *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
|
|
|
|
return *the_left < the_right->name;
|
|
}
|
|
|
|
static void *_Objects_MP_Name_map( RBTree_Node *node )
|
|
{
|
|
return OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( node );
|
|
}
|
|
|
|
static bool _Objects_MP_Name_and_node_equal(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const Objects_MP_Name_and_node *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
|
|
|
|
return the_left->name == the_right->name
|
|
&& the_left->node == _Objects_Get_node( the_right->id );
|
|
}
|
|
|
|
static bool _Objects_MP_Name_and_node_less(
|
|
const void *left,
|
|
const RBTree_Node *right
|
|
)
|
|
{
|
|
const Objects_MP_Name_and_node *the_left;
|
|
const Objects_MP_Control *the_right;
|
|
|
|
the_left = left;
|
|
the_right = OBJECTS_MP_CONTROL_OF_NAME_LOOKUP_NODE( right );
|
|
|
|
/*
|
|
* Use > for the node to find smaller numbered nodes first in case of equal
|
|
* names.
|
|
*/
|
|
return the_left->name < the_right->name
|
|
|| ( the_left->name == the_right->name
|
|
&& the_left->node > _Objects_Get_node( the_right->id ) );
|
|
}
|
|
|
|
void _Objects_MP_Handler_early_initialization(void)
|
|
{
|
|
uint32_t node;
|
|
uint32_t maximum_nodes;
|
|
|
|
node = _MPCI_Configuration.node;
|
|
maximum_nodes = _MPCI_Configuration.maximum_nodes;
|
|
|
|
if ( node < 1 || node > maximum_nodes )
|
|
_Internal_error( INTERNAL_ERROR_INVALID_NODE );
|
|
|
|
_Objects_Local_node = node;
|
|
_Objects_Maximum_nodes = maximum_nodes;
|
|
}
|
|
|
|
void _Objects_MP_Handler_initialization( void )
|
|
{
|
|
uint32_t maximum_global_objects;
|
|
|
|
maximum_global_objects = _MPCI_Configuration.maximum_global_objects;
|
|
|
|
_Objects_MP_Maximum_global_objects = maximum_global_objects;
|
|
|
|
if ( maximum_global_objects == 0 ) {
|
|
return;
|
|
}
|
|
|
|
_Chain_Initialize(
|
|
&_Objects_MP_Inactive_global_objects,
|
|
&_Objects_MP_Controls[ 0 ],
|
|
maximum_global_objects,
|
|
sizeof( _Objects_MP_Controls[ 0 ] )
|
|
);
|
|
}
|
|
|
|
void _Objects_MP_Open (
|
|
Objects_Information *information,
|
|
Objects_MP_Control *the_global_object,
|
|
uint32_t the_name, /* XXX -- wrong for variable */
|
|
Objects_Id the_id
|
|
)
|
|
{
|
|
Objects_MP_Name_and_node name_and_node;
|
|
ISR_lock_Context lock_context;
|
|
|
|
the_global_object->id = the_id;
|
|
the_global_object->name = the_name;
|
|
|
|
name_and_node.name = the_name;
|
|
name_and_node.node = _Objects_Get_node( the_id );
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
_RBTree_Insert_inline(
|
|
&information->Global_by_id,
|
|
&the_global_object->Nodes.Active.Id_lookup,
|
|
&the_id,
|
|
_Objects_MP_Id_less
|
|
);
|
|
_RBTree_Insert_inline(
|
|
&information->Global_by_name,
|
|
&the_global_object->Nodes.Active.Name_lookup,
|
|
&name_and_node,
|
|
_Objects_MP_Name_and_node_less
|
|
);
|
|
|
|
_Objects_MP_Global_release( &lock_context );
|
|
}
|
|
|
|
bool _Objects_MP_Allocate_and_open (
|
|
Objects_Information *information,
|
|
uint32_t the_name, /* XXX -- wrong for variable */
|
|
Objects_Id the_id,
|
|
bool is_fatal_error
|
|
)
|
|
{
|
|
Objects_MP_Control *the_global_object;
|
|
|
|
the_global_object = _Objects_MP_Allocate_global_object();
|
|
|
|
if ( the_global_object == NULL ) {
|
|
if ( !is_fatal_error ) {
|
|
return false;
|
|
}
|
|
|
|
_Internal_error( INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS );
|
|
}
|
|
|
|
_Objects_MP_Open( information, the_global_object, the_name, the_id );
|
|
|
|
return true;
|
|
}
|
|
|
|
void _Objects_MP_Close (
|
|
Objects_Information *information,
|
|
Objects_Id the_id
|
|
)
|
|
{
|
|
Objects_MP_Control *the_global_object;
|
|
ISR_lock_Context lock_context;
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
the_global_object = _RBTree_Find_inline(
|
|
&information->Global_by_id,
|
|
&the_id,
|
|
_Objects_MP_Id_equal,
|
|
_Objects_MP_Id_less,
|
|
_Objects_MP_Id_map
|
|
);
|
|
|
|
if ( the_global_object != NULL ) {
|
|
_RBTree_Extract(
|
|
&information->Global_by_id,
|
|
&the_global_object->Nodes.Active.Id_lookup
|
|
);
|
|
_RBTree_Extract(
|
|
&information->Global_by_name,
|
|
&the_global_object->Nodes.Active.Name_lookup
|
|
);
|
|
_Objects_MP_Free_global_object( the_global_object );
|
|
_Objects_MP_Global_release( &lock_context );
|
|
} else {
|
|
_Objects_MP_Global_release( &lock_context );
|
|
|
|
_Internal_error( INTERNAL_ERROR_INVALID_GLOBAL_ID );
|
|
}
|
|
}
|
|
|
|
Status_Control _Objects_MP_Global_name_search(
|
|
const Objects_Information *information,
|
|
Objects_Name the_name,
|
|
uint32_t nodes_to_search,
|
|
Objects_Id *the_id
|
|
)
|
|
{
|
|
Status_Control status;
|
|
Objects_MP_Control *the_global_object;
|
|
ISR_lock_Context lock_context;
|
|
|
|
if ( nodes_to_search > _Objects_Maximum_nodes ) {
|
|
return STATUS_INVALID_NODE;
|
|
}
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
if ( nodes_to_search == OBJECTS_SEARCH_ALL_NODES ) {
|
|
the_global_object = _RBTree_Find_inline(
|
|
&information->Global_by_name,
|
|
&the_name.name_u32,
|
|
_Objects_MP_Name_equal,
|
|
_Objects_MP_Name_less,
|
|
_Objects_MP_Name_map
|
|
);
|
|
} else {
|
|
Objects_MP_Name_and_node name_and_node;
|
|
|
|
name_and_node.name = the_name.name_u32;
|
|
name_and_node.node = nodes_to_search;
|
|
|
|
the_global_object = _RBTree_Find_inline(
|
|
&information->Global_by_name,
|
|
&name_and_node,
|
|
_Objects_MP_Name_and_node_equal,
|
|
_Objects_MP_Name_and_node_less,
|
|
_Objects_MP_Name_map
|
|
);
|
|
}
|
|
|
|
if ( the_global_object != NULL ) {
|
|
*the_id = the_global_object->id;
|
|
_Assert( the_global_object->name != 0 );
|
|
status = STATUS_SUCCESSFUL;
|
|
} else {
|
|
status = STATUS_INVALID_NAME;
|
|
}
|
|
|
|
_Objects_MP_Global_release( &lock_context );
|
|
|
|
return status;
|
|
}
|
|
|
|
bool _Objects_MP_Is_remote(
|
|
Objects_Id the_id,
|
|
const Objects_Information *information
|
|
)
|
|
{
|
|
Objects_MP_Control *the_global_object;
|
|
ISR_lock_Context lock_context;
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
the_global_object = _RBTree_Find_inline(
|
|
&information->Global_by_id,
|
|
&the_id,
|
|
_Objects_MP_Id_equal,
|
|
_Objects_MP_Id_less,
|
|
_Objects_MP_Id_map
|
|
);
|
|
|
|
_Objects_MP_Global_release( &lock_context );
|
|
|
|
return the_global_object != NULL;
|
|
}
|
|
|
|
Objects_MP_Control *_Objects_MP_Allocate_global_object( void )
|
|
{
|
|
Objects_MP_Control *the_global_object;
|
|
ISR_lock_Context lock_context;
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
the_global_object = (Objects_MP_Control *)
|
|
_Chain_Get_unprotected( &_Objects_MP_Inactive_global_objects );
|
|
|
|
_Objects_MP_Global_release( &lock_context );
|
|
return the_global_object;
|
|
}
|
|
|
|
void _Objects_MP_Free_global_object( Objects_MP_Control *the_global_object )
|
|
{
|
|
ISR_lock_Context lock_context;
|
|
|
|
_Objects_MP_Global_acquire( &lock_context );
|
|
|
|
_Chain_Initialize_node( &the_global_object->Nodes.Inactive );
|
|
_Chain_Append_unprotected(
|
|
&_Objects_MP_Inactive_global_objects,
|
|
&the_global_object->Nodes.Inactive
|
|
);
|
|
|
|
_Objects_MP_Global_release( &lock_context );
|
|
}
|