From f4a8ee1c55788aeb053ede7571b07906a9847a45 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 17 Mar 1999 16:01:03 +0000 Subject: Unlimited objects patch from Chris Johns . Email follows: First, the unlimited patch. I have compiled the unlmited patch for the Linux posix BSP only and it seems to work cleanly. I would like a really major application run on this change before commiting as the changes are very core and significant. I am currently building all the tests to run. I have no targets suitable to test on at the moment. I have tested the patch for inline functions and macros. Turning macros on has found some core bugs. I have fixed these but have not run all the tests. Please review the patch for these changes. They are: 1) The conditional compilation for MP support broke the core messages code. You cannot embed a conditional macro in another macro. The Send and Urgent Send calls are macros. 2) User extensions handler initialisation now has two parameters. I have updated the macros to support the extra parameter. The patch also contains the gcc-target-default.cfg fix required to build the kernel. More of a by product than a fix for you. --- cpukit/rtems/src/msg.c | 32 +- cpukit/sapi/include/rtems/config.h | 14 + cpukit/score/include/rtems/score/object.h | 110 ++++-- cpukit/score/inline/rtems/score/coremsg.inl | 8 + cpukit/score/inline/rtems/score/object.inl | 56 ++- cpukit/score/macros/rtems/score/object.inl | 30 +- cpukit/score/macros/rtems/score/userext.inl | 16 +- cpukit/score/src/object.c | 564 ++++++++++++++++++++++++---- 8 files changed, 683 insertions(+), 147 deletions(-) (limited to 'cpukit') diff --git a/cpukit/rtems/src/msg.c b/cpukit/rtems/src/msg.c index 2768050d8f..b0222601f0 100644 --- a/cpukit/rtems/src/msg.c +++ b/cpukit/rtems/src/msg.c @@ -31,6 +31,20 @@ #include #include +/*PAGE + * + * _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT + * + * Condition support for the MP. Helps the macro build. + * + */ + +#if defined(RTEMS_MULTIPROCESSING) +#define _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT _Message_queue_Core_message_queue_mp_support +#else +#define _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT NULL +#endif + /*PAGE * * _Message_queue_Manager_initialization @@ -450,11 +464,7 @@ rtems_status_code rtems_message_queue_broadcast( buffer, size, id, -#if defined(RTEMS_MULTIPROCESSING) - _Message_queue_Core_message_queue_mp_support, -#else - NULL, -#endif + _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT, count ); @@ -718,11 +728,7 @@ rtems_status_code _Message_queue_Submit( buffer, size, id, -#if defined(RTEMS_MULTIPROCESSING) - _Message_queue_Core_message_queue_mp_support -#else - NULL -#endif + _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT ); break; case MESSAGE_QUEUE_URGENT_REQUEST: @@ -731,11 +737,7 @@ rtems_status_code _Message_queue_Submit( buffer, size, id, -#if defined(RTEMS_MULTIPROCESSING) - _Message_queue_Core_message_queue_mp_support -#else - NULL -#endif + _MESSAGE_QUEUE_CORE_MESSAGE_QUEUE_MP_SUPPORT ); break; default: diff --git a/cpukit/sapi/include/rtems/config.h b/cpukit/sapi/include/rtems/config.h index 5a01286059..ac2da06d97 100644 --- a/cpukit/sapi/include/rtems/config.h +++ b/cpukit/sapi/include/rtems/config.h @@ -21,6 +21,20 @@ extern "C" { #endif +/* + * Unlimited object support. Changes the configuration table entry for POSIX + * or RTEMS APIs to bounded only by the memory of the work-space. + * + * Use the macro to define the resource unlimited before placing in the configuration + * table. + */ + +#include +#define RTEMS_UNLIMITED_OBJECTS OBJECTS_UNLIMITED_OBJECTS + +#define rtems_resource_unlimited(resource) \ + ( resource | RTEMS_UNLIMITED_OBJECTS ) + /* * This is kind of kludgy but it allows targets to totally ignore the * POSIX API safely. diff --git a/cpukit/score/include/rtems/score/object.h b/cpukit/score/include/rtems/score/object.h index a0bf3707b6..7c72719679 100644 --- a/cpukit/score/include/rtems/score/object.h +++ b/cpukit/score/include/rtems/score/object.h @@ -25,6 +25,14 @@ extern "C" { #include +/* + * Mask to enable unlimited objects + * + * XXX - needs to be moved to the API some-where + */ + +#define OBJECTS_UNLIMITED_OBJECTS 0x80000000 + /* * The following type defines the control block used to manage * object names. @@ -121,9 +129,9 @@ typedef enum { */ typedef struct { - Chain_Node Node; - Objects_Id id; - Objects_Name name; + Chain_Node Node; + Objects_Id id; + Objects_Name name; } Objects_Control; /* @@ -132,18 +140,24 @@ typedef struct { */ typedef struct { - Objects_Classes the_class; /* Class of this object */ - Objects_Id minimum_id; /* minimum valid id of this type */ - Objects_Id maximum_id; /* maximum valid id of this type */ - unsigned32 maximum; /* maximum number of objects */ - Objects_Control **local_table; /* table of local object pointers */ - Objects_Name *name_table; /* table of local object names */ - Chain_Control *global_table; /* pointer to global table */ - Chain_Control Inactive; /* chain of inactive ctl blocks */ - boolean is_string; /* TRUE if names are strings */ - unsigned32 name_length; /* maximum length of names */ - boolean is_thread; /* TRUE if these are threads */ - /* irregardless of API */ + Objects_Classes the_class; /* Class of this object */ + Objects_Id minimum_id; /* minimum valid id of this type */ + Objects_Id maximum_id; /* maximum valid id of this type */ + unsigned32 maximum; /* maximum number of objects */ + boolean auto_extend; /* TRUE if unlimited objects */ + unsigned32 allocation_size; /* number of objects in a block */ + unsigned32 size; /* size of the objects */ + Objects_Control **local_table; + Objects_Name *name_table; + Chain_Control *global_table; /* pointer to global table */ + Chain_Control Inactive; /* chain of inactive ctl blocks */ + unsigned32 inactive; /* number of objects on the InActive list */ + unsigned32 *inactive_per_block; /* used to release a block */ + void **object_blocks; /* the object memory to remove */ + boolean is_string; /* TRUE if names are strings */ + unsigned32 name_length; /* maximum length of names */ + boolean is_thread; /* TRUE if these are threads */ + /* irregardless of API */ } Objects_Information; /* @@ -207,6 +221,30 @@ void _Objects_Handler_initialization( unsigned32 maximum_global_objects ); +/* + * _Objects_Extend_information + * + * DESCRIPTION: + * + * This function extends an object class information record. + */ + +void _Objects_Extend_information( + Objects_Information *information +); + +/* + * _Objects_Shrink_information + * + * DESCRIPTION: + * + * This function shrink an object class information record. + */ + +void _Objects_Shrink_information( + Objects_Information *information +); + /* * _Objects_Initialize_information * @@ -232,6 +270,35 @@ void _Objects_Initialize_information ( boolean is_task ); +/*PAGE + * + * _Objects_Allocate + * + * DESCRIPTION: + * + * This function allocates a object control block from + * the inactive chain of free object control blocks. + */ + +Objects_Control *_Objects_Allocate( + Objects_Information *information +); + +/*PAGE + * + * _Objects_Free + * + * DESCRIPTION: + * + * This function frees a object control block to the + * inactive chain of free object control blocks. + */ + +void _Objects_Free( + Objects_Information *information, + Objects_Control *the_object +); + /* * _Objects_Clear_name * @@ -369,19 +436,6 @@ Objects_Control *_Objects_Get_next( Objects_Id *next_id_p ); -/* - * _Objects_Get_information - * - * DESCRIPTION: - * - * Returns the information control block for the class of objects - * corresponding to this id. - */ - -Objects_Information *_Objects_Get_information( - Objects_Id id -); - /* * Pieces of object.inl are promoted out to the user */ diff --git a/cpukit/score/inline/rtems/score/coremsg.inl b/cpukit/score/inline/rtems/score/coremsg.inl index a43b0e7b06..d4dafd8fdc 100644 --- a/cpukit/score/inline/rtems/score/coremsg.inl +++ b/cpukit/score/inline/rtems/score/coremsg.inl @@ -41,7 +41,11 @@ RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Send( buffer, size, id, +#if defined(RTEMS_MULTIPROCESSING) api_message_queue_mp_support, +#else + NULL, +#endif CORE_MESSAGE_QUEUE_SEND_REQUEST ); } @@ -68,7 +72,11 @@ RTEMS_INLINE_ROUTINE CORE_message_queue_Status _CORE_message_queue_Urgent( buffer, size, id, +#if defined(RTEMS_MULTIPROCESSING) api_message_queue_mp_support, +#else + NULL, +#endif CORE_MESSAGE_QUEUE_URGENT_REQUEST ); } diff --git a/cpukit/score/inline/rtems/score/object.inl b/cpukit/score/inline/rtems/score/object.inl index 7e4d12aeec..ce149f33d8 100644 --- a/cpukit/score/inline/rtems/score/object.inl +++ b/cpukit/score/inline/rtems/score/object.inl @@ -158,37 +158,67 @@ RTEMS_INLINE_ROUTINE boolean _Objects_Are_ids_equal( /*PAGE * - * _Objects_Allocate + * _Objects_Get_local_object * * DESCRIPTION: * - * This function allocates a object control block from - * the inactive chain of free object control blocks. + * This function returns a pointer to the local_table object + * referenced by the index. */ -RTEMS_INLINE_ROUTINE Objects_Control *_Objects_Allocate( - Objects_Information *information +RTEMS_INLINE_ROUTINE Objects_Control *_Objects_Get_local_object( + Objects_Information *information, + unsigned32 index ) { - return (Objects_Control *) _Chain_Get( &information->Inactive ); + if ( index > information->maximum) + return NULL; + return ( information->local_table[ index ] ); } /*PAGE * - * _Objects_Free + * _Objects_Set_local_object * * DESCRIPTION: * - * This function frees a object control block to the - * inactive chain of free object control blocks. + * This function sets the pointer to the local_table object + * referenced by the index. */ -RTEMS_INLINE_ROUTINE void _Objects_Free( +RTEMS_INLINE_ROUTINE void _Objects_Set_local_object( Objects_Information *information, + unsigned32 index, Objects_Control *the_object ) { - _Chain_Append( &information->Inactive, &the_object->Node ); + if ( index <= information->maximum) + information->local_table[ index ] = the_object; +} + + +/*PAGE + * + * _Objects_Get_information + * + * DESCRIPTION: + * + * This function return the information structure given + * an id of an object. + */ + +RTEMS_INLINE_ROUTINE Objects_Information *_Objects_Get_information( + Objects_Id id +) +{ + Objects_Classes the_class; + + the_class = _Objects_Get_class( id ); + + if ( !_Objects_Is_class_valid( the_class ) ) + return NULL; + + return _Objects_Information_table[ the_class ]; } /*PAGE @@ -210,7 +240,7 @@ RTEMS_INLINE_ROUTINE void _Objects_Open( unsigned32 index; index = _Objects_Get_index( the_object->id ); - information->local_table[ index ] = the_object; + _Objects_Set_local_object( information, index, the_object ); if ( information->is_string ) _Objects_Copy_name_string( name, the_object->name ); @@ -236,7 +266,7 @@ RTEMS_INLINE_ROUTINE void _Objects_Close( unsigned32 index; index = _Objects_Get_index( the_object->id ); - information->local_table[ index ] = (Objects_Control *) NULL; + _Objects_Set_local_object( information, index, NULL ); _Objects_Clear_name( the_object->name, information->name_length ); } diff --git a/cpukit/score/macros/rtems/score/object.inl b/cpukit/score/macros/rtems/score/object.inl index cce2cbde9b..62994ee4e5 100644 --- a/cpukit/score/macros/rtems/score/object.inl +++ b/cpukit/score/macros/rtems/score/object.inl @@ -93,21 +93,39 @@ /*PAGE * - * _Objects_Allocate + * _Objects_Get_local_object * */ -#define _Objects_Allocate( _information ) \ - (Objects_Control *) _Chain_Get( &(_information)->Inactive ) +#define _Objects_Get_local_object( information, index ) \ + ( ( index > information->maximum) ? NULL : \ + information->local_table[ index ] ) /*PAGE * - * _Objects_Free + * _Objects_Set_local_object * */ -#define _Objects_Free( _information, _the_object ) \ - _Chain_Append( &(_information)->Inactive, &(_the_object)->Node ) +#define _Objects_Set_local_object( information, index, the_object ) \ + { \ + if ( index <= information->maximum) \ + information->local_table[ index ] = the_object; \ + } + + +/*PAGE + * + * _Objects_Get_information + * + */ + +#define _Objects_Get_information( id ) \ + ( \ + ( !_Objects_Is_class_valid( _Objects_Get_class( id ) ) ) ? \ + NULL : \ + _Objects_Information_table[ _Objects_Get_class( id ) ] \ + ) /*PAGE * diff --git a/cpukit/score/macros/rtems/score/userext.inl b/cpukit/score/macros/rtems/score/userext.inl index 37b0bf8d2a..69fd0de4b1 100644 --- a/cpukit/score/macros/rtems/score/userext.inl +++ b/cpukit/score/macros/rtems/score/userext.inl @@ -23,14 +23,22 @@ * */ -#define _User_extensions_Handler_initialization( _initial_extensions ) \ +#define _User_extensions_Handler_initialization( \ + number_of_extensions, _initial_extensions \ +) \ { \ + User_extensions_Control *extension; \ + unsigned32 i; \ _Chain_Initialize_empty( &_User_extensions_List ); \ \ if ( (_initial_extensions) ) { \ - _User_extensions_Initial.Callouts = *(_initial_extensions); \ - _Chain_Append( \ - &_User_extensions_List, &_User_extensions_Initial.Node ); \ + for (i=0 ; iCallouts = _initial_extensions[i]; \ + _Chain_Append( &_User_extensions_List, &extension->Node ); \ + } \ } \ } diff --git a/cpukit/score/src/object.c b/cpukit/score/src/object.c index 81bca89d7c..cbbe889a79 100644 --- a/cpukit/score/src/object.c +++ b/cpukit/score/src/object.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #if defined(RTEMS_MULTIPROCESSING) @@ -22,6 +23,7 @@ #include #include #include +#include /*PAGE * @@ -62,6 +64,352 @@ void _Objects_Handler_initialization( #endif } +/*PAGE + * + * _Objects_Extend_information + * + * This routine extends all object information related data structures. + * + * Input parameters: + * information - object information table + * + * Output parameters: NONE + */ + +void _Objects_Extend_information( + Objects_Information *information +) +{ + Objects_Control *the_object; + void *name_area; + Chain_Control Inactive; + unsigned32 block_count; + unsigned32 block; + unsigned32 index_base; + unsigned32 minimum_index; + unsigned32 index; + + /* + * Search for a free block of indexes. The block variable ends up set + * to block_count + 1 if the table needs to be extended. + */ + + minimum_index = _Objects_Get_index( information->minimum_id ); + index_base = minimum_index; + block = 0; + + if (information->maximum < minimum_index) + block_count = 0; + else { + block_count = information->maximum / information->allocation_size; + + for ( ; block < block_count; block++ ) { + if ( information->object_blocks[ block ] == NULL ) + break; + else + index_base += information->allocation_size; + } + } + + /* + * If the index_base is the maximum we need to grow the tables. + */ + + if (index_base >= information->maximum ) { + ISR_Level level; + void **object_blocks; + Objects_Name *name_table; + unsigned32 *inactive_per_block; + Objects_Control **local_table; + unsigned32 maximum; + void *old_tables; + + /* + * Growing the tables means allocating a new area, doing a copy and updating + * the information table. + * + * If the maximum is minimum we do not have a table to copy. First time through. + * + * The allocation has : + * + * void *objects[block_count]; + * unsiged32 inactive_count[block_count]; + * Objects_Name *name_table[block_count]; + * Objects_Control *local_table[maximum]; + * + * This is the order in memory. Watch changing the order. See the memcpy + * below. + */ + + /* + * Up the block count and maximum + */ + + block_count++; + + maximum = information->maximum + information->allocation_size; + + /* + * Allocate the tables and break it up. + */ + + if ( information->auto_extend ) { + object_blocks = (void**) + _Workspace_Allocate( + block_count * (sizeof(void *) + sizeof(unsigned32) + sizeof(Objects_Name *)) + + ((maximum + minimum_index) * sizeof(Objects_Control *)) + ); + + if ( !object_blocks ) + return; + } + else { + object_blocks = (void**) + _Workspace_Allocate_or_fatal_error( + block_count * (sizeof(void *) + sizeof(unsigned32) + sizeof(Objects_Name *)) + + ((maximum + minimum_index) * sizeof(Objects_Control *)) + ); + } + + /* + * Break the block into the various sections. + * + */ + + inactive_per_block = + (unsigned32 *) _Addresses_Add_offset( object_blocks, block_count * sizeof(void*) ); + name_table = + (Objects_Name *) _Addresses_Add_offset( inactive_per_block, + block_count * sizeof(unsigned32) ); + local_table = + (Objects_Control **) _Addresses_Add_offset( name_table, + block_count * sizeof(Objects_Name *) ); + + /* + * Take the block count down. Saves all the (block_count - 1) in the copies. + */ + + block_count--; + + if ( information->maximum > minimum_index ) { + + /* + * Copy each section of the table over. This has to be performed as + * separate parts as size of each block has changed. + */ + + memcpy( object_blocks, + information->object_blocks, + block_count * sizeof(void*) ); + memcpy( inactive_per_block, + information->inactive_per_block, + block_count * sizeof(unsigned32) ); + memcpy( name_table, + information->name_table, + block_count * sizeof(Objects_Name *) ); + memcpy( local_table, + information->local_table, + (information->maximum + minimum_index) * sizeof(Objects_Control *) ); + } + else { + + /* + * Deal with the special case of the 0 to minimum_index + */ + for ( index = 0; index < minimum_index; index++ ) { + local_table[ index ] = NULL; + } + } + + /* + * Initialise the new entries in the table. + */ + + object_blocks[block_count] = NULL; + inactive_per_block[block_count] = 0; + name_table[block_count] = NULL; + + for ( index=index_base ; + index < ( information->allocation_size + index_base ); + index++ ) { + local_table[ index ] = NULL; + } + + _ISR_Disable( level ); + + old_tables = information->object_blocks; + + information->object_blocks = object_blocks; + information->inactive_per_block = inactive_per_block; + information->name_table = name_table; + information->local_table = local_table; + information->maximum = maximum; + information->maximum_id = + _Objects_Build_id( + information->the_class, _Objects_Local_node, information->maximum + ); + + _ISR_Enable( level ); + + if ( old_tables ) + _Workspace_Free( old_tables ); + + block_count++; + } + + /* + * Allocate the name table, and the objects + */ + + if ( information->auto_extend ) { + information->object_blocks[ block ] = + _Workspace_Allocate( + (information->allocation_size * information->name_length) + + (information->allocation_size * information->size) + ); + + if ( !information->object_blocks[ block ] ) + return; + } + else { + information->object_blocks[ block ] = + _Workspace_Allocate_or_fatal_error( + (information->allocation_size * information->name_length) + + (information->allocation_size * information->size) + ); + } + + name_area = (Objects_Name *) information->object_blocks[ block ]; + information->name_table[ block ] = name_area; + + /* + * Initialize objects .. add to a local chain first. + */ + + _Chain_Initialize( + &Inactive, + _Addresses_Add_offset( information->object_blocks[ block ], + (information->allocation_size * information->name_length) ), + information->allocation_size, + information->size + ); + + /* + * Move from the local chain, initialise, then append to the inactive chain + */ + + index = index_base; + + while ( (the_object = (Objects_Control *) _Chain_Get( &Inactive ) ) != NULL ) { + + the_object->id = + _Objects_Build_id( + information->the_class, _Objects_Local_node, index + ); + + the_object->name = (void *) name_area; + + name_area = _Addresses_Add_offset( name_area, information->name_length ); + + _Chain_Append( &information->Inactive, &the_object->Node ); + + index++; + } + + information->inactive_per_block[ block ] = information->allocation_size; + information->inactive += information->allocation_size; +} + +/*PAGE + * + * _Objects_Shrink_information + * + * This routine shrinks object information related data structures. + * The object's name and object space are released. The local_table + * etc block does not shrink. The InActive list needs to be scanned + * to find the objects are remove them. + * Input parameters: + * information - object information table + * the_block - the block to remove + * + * Output parameters: NONE + */ + +void _Objects_Shrink_information( + Objects_Information *information +) +{ + Objects_Control *the_object; + Objects_Control *extract_me; + unsigned32 block_count; + unsigned32 block; + unsigned32 index_base; + unsigned32 index; + + /* + * Search the list to find block or chunnk with all objects inactive. + */ + + index_base = _Objects_Get_index( information->minimum_id ); + block_count = ( information->maximum - index_base ) / information->allocation_size; + + for ( block = 0; block < block_count; block++ ) { + if ( information->inactive_per_block[ block ] == information->allocation_size ) { + + /* + * XXX - Not to sure how to use a chain where you need to iterate and + * and remove elements. + */ + + the_object = (Objects_Control *) information->Inactive.first; + + /* + * Assume the Inactive chain is never empty at this point + */ + + do { + index = _Objects_Get_index( the_object->id ); + + if ((index >= index_base) && + (index < (index_base + information->allocation_size))) { + + /* + * Get the next node before the node is extracted + */ + + extract_me = the_object; + + if ( !_Chain_Is_last( &the_object->Node ) ) + the_object = (Objects_Control *) the_object->Node.next; + else + the_object = NULL; + + _Chain_Extract( &extract_me->Node ); + } + else { + the_object = (Objects_Control *) the_object->Node.next; + } + } + while ( the_object && !_Chain_Is_last( &the_object->Node ) ); + + /* + * Free the memory and reset the structures in the object' information + */ + + _Workspace_Free( information->object_blocks[ block ] ); + information->name_table[ block ] = NULL; + information->object_blocks[ block ] = NULL; + information->inactive_per_block[ block ] = 0; + + information->inactive -= information->allocation_size; + + return; + } + + index_base += information->allocation_size; + } +} + /*PAGE * * _Objects_Initialize_information @@ -93,15 +441,19 @@ void _Objects_Initialize_information( { unsigned32 minimum_index; unsigned32 index; - Objects_Control *the_object; unsigned32 name_length; - void *name_area; - - information->maximum = maximum; - information->the_class = the_class; - information->is_string = is_string; - information->is_thread = is_thread; + information->the_class = the_class; + information->is_string = is_string; + information->is_thread = is_thread; + + information->local_table = 0; + information->name_table = 0; + information->inactive_per_block = 0; + information->object_blocks = 0; + + information->inactive = 0; + /* * Set the entry in the object information table. */ @@ -109,29 +461,36 @@ void _Objects_Initialize_information( _Objects_Information_table[ the_class ] = information; /* - * Calculate minimum and maximum Id's + * Set the size of the object */ - if ( maximum == 0 ) minimum_index = 0; - else minimum_index = 1; + information->size = size; + + /* + * Are we operating in unlimited, or auto-extend mode + */ - information->minimum_id = - _Objects_Build_id( the_class, _Objects_Local_node, minimum_index ); + information->auto_extend = (maximum & OBJECTS_UNLIMITED_OBJECTS) ? TRUE : FALSE; + maximum &= ~OBJECTS_UNLIMITED_OBJECTS; + + /* + * The allocation unit is the maximum value + */ - information->maximum_id = - _Objects_Build_id( the_class, _Objects_Local_node, maximum ); + information->allocation_size = maximum; /* - * Allocate local pointer table + * Calculate minimum and maximum Id's */ - information->local_table = - (Objects_Control **) _Workspace_Allocate_or_fatal_error( - (maximum + 1) * sizeof(Objects_Control *) - ); + if ( maximum == 0 ) minimum_index = 0; + else minimum_index = 1; + + information->minimum_id = + _Objects_Build_id( the_class, _Objects_Local_node, minimum_index ); /* - * Allocate name table + * Calculate the maximum name length */ name_length = maximum_name_length; @@ -142,45 +501,29 @@ void _Objects_Initialize_information( information->name_length = name_length; - name_area = (Objects_Name *) - _Workspace_Allocate_or_fatal_error( (maximum + 1) * name_length ); - information->name_table = name_area; - - /* - * Initialize local pointer table - */ - - for ( index=0 ; index <= maximum ; index++ ) { - information->local_table[ index ] = NULL; - } - + _Chain_Initialize_empty( &information->Inactive ); + /* * Initialize objects .. if there are any */ - if ( maximum == 0 ) { - _Chain_Initialize_empty( &information->Inactive ); - } else { - - _Chain_Initialize( - &information->Inactive, - _Workspace_Allocate_or_fatal_error( maximum * size ), - maximum, - size - ); - - the_object = (Objects_Control *) information->Inactive.first; - for ( index=1; index <= maximum ; index++ ) { - the_object->id = - _Objects_Build_id( the_class, _Objects_Local_node, index ); - - the_object->name = (void *) name_area; - - name_area = _Addresses_Add_offset( name_area, name_length ); - - the_object = (Objects_Control *) the_object->Node.next; - } + if ( maximum ) { + /* + * Reset the maximum value. It will be updated when the information is + * extended. + */ + + information->maximum = 0; + + /* + * Always have the maximum size available so the current performance + * figures are create are met. If the user moves past the maximum + * number then a performance hit is taken. + */ + + _Objects_Extend_information( information ); + } /* @@ -201,6 +544,89 @@ void _Objects_Initialize_information( information->global_table = NULL; } +/*PAGE + * + * _Objects_Allocate + * + * DESCRIPTION: + * + * This function allocates a object control block from + * the inactive chain of free object control blocks. + */ + +Objects_Control *_Objects_Allocate( + Objects_Information *information +) +{ + Objects_Control *the_object = + (Objects_Control *) _Chain_Get( &information->Inactive ); + + if ( information->auto_extend ) { + /* + * If the list is empty then we are out of objects and need to + * extend information base. + */ + + if ( !the_object ) { + _Objects_Extend_information( information ); + the_object = (Objects_Control *) _Chain_Get( &information->Inactive ); + } + + if ( the_object ) { + unsigned32 block; + + block = + _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id ); + block /= information->allocation_size; + + information->inactive_per_block[ block ]--; + information->inactive--; + } + } + + return the_object; +} + +/*PAGE + * + * _Objects_Free + * + * DESCRIPTION: + * + * This function frees a object control block to the + * inactive chain of free object control blocks. + */ + +void _Objects_Free( + Objects_Information *information, + Objects_Control *the_object +) +{ + unsigned32 allocation_size = information->allocation_size; + + _Chain_Append( &information->Inactive, &the_object->Node ); + + if ( information->auto_extend ) { + unsigned32 block; + + block = + _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id ); + block /= information->allocation_size; + + information->inactive_per_block[ block ]++; + information->inactive++; + + /* + * Check if the threshold level has been met of + * 1.5 x allocation_size are free. + */ + + if ( information->inactive > ( allocation_size + ( allocation_size >> 1 ) ) ) { + _Objects_Shrink_information( information ); + } + } +} + /*PAGE * * _Objects_Clear_name @@ -341,7 +767,6 @@ Objects_Name_to_id_errors _Objects_Name_to_id( ) { boolean search_local_node; - Objects_Control **objects; Objects_Control *the_object; unsigned32 index; unsigned32 name_length; @@ -358,8 +783,6 @@ Objects_Name_to_id_errors _Objects_Name_to_id( search_local_node = TRUE; if ( search_local_node ) { - objects = information->local_table; - name_length = information->name_length; if ( information->is_string ) compare_them = _Objects_Compare_name_string; @@ -367,7 +790,7 @@ Objects_Name_to_id_errors _Objects_Name_to_id( for ( index = 1; index <= information->maximum; index++ ) { - the_object = objects[ index ]; + the_object = information->local_table[ index ]; if ( !the_object || !the_object->name ) continue; @@ -418,11 +841,11 @@ Objects_Control *_Objects_Get( Objects_Control *the_object; unsigned32 index; - index = id - information->minimum_id; + index = _Objects_Get_index( id ); if ( information->maximum >= index ) { _Thread_Disable_dispatch(); - if ( (the_object = information->local_table[index+1]) != NULL ) { + if ( (the_object = _Objects_Get_local_object( information, index )) != NULL ) { *location = OBJECTS_LOCAL; return( the_object ); } @@ -505,24 +928,3 @@ final: return 0; } -/*PAGE - * - * _Objects_Get_information - * - * XXX - */ - -Objects_Information *_Objects_Get_information( - Objects_Id id -) -{ - Objects_Classes the_class; - - the_class = _Objects_Get_class( id ); - - if ( !_Objects_Is_class_valid( the_class ) ) - return NULL; - - return _Objects_Information_table[ the_class ]; -} - -- cgit v1.2.3