source: rtems/c/src/exec/score/src/object.c @ 2cd5444

4.104.114.84.9
Last change on this file since 2cd5444 was 2cd5444, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 2, 1999 at 3:58:39 PM

Added code to allocate by index. This is the object ID style used
by ITRON.

Corrected spacing.

  • Property mode set to 100644
File size: 25.6 KB
Line 
1/*
2 *  Object Handler
3 *
4 *
5 *  COPYRIGHT (c) 1989-1998.
6 *  On-Line Applications Research Corporation (OAR).
7 *  Copyright assigned to U.S. Government, 1994.
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.OARcorp.com/rtems/license.html.
12 *
13 *  $Id$
14 */
15
16#include <rtems/system.h>
17#include <rtems/score/address.h>
18#include <rtems/score/chain.h>
19#include <rtems/score/object.h>
20#if defined(RTEMS_MULTIPROCESSING)
21#include <rtems/score/objectmp.h>
22#endif
23#include <rtems/score/thread.h>
24#include <rtems/score/wkspace.h>
25#include <rtems/score/sysstate.h>
26#include <rtems/score/isr.h>
27
28/*PAGE
29 *
30 *  _Objects_Handler_initialization
31 *
32 *  This routine initializes the object handler.
33 *
34 *  Input parameters:
35 *    node                   - local node
36 *    maximum_nodes          - number of nodes in the system
37 *    maximum_global_objects - number of configured global objects
38 *
39 *  Output parameters:  NONE
40 */
41
42void _Objects_Handler_initialization(
43  unsigned32 node,
44  unsigned32 maximum_nodes,
45  unsigned32 maximum_global_objects
46)
47{
48  if ( node < 1 || node > maximum_nodes )
49    _Internal_error_Occurred(
50      INTERNAL_ERROR_CORE,
51      TRUE,
52      INTERNAL_ERROR_INVALID_NODE
53    );
54
55  _Objects_Local_node    = node;
56  _Objects_Maximum_nodes = maximum_nodes;
57
58#if defined(RTEMS_MULTIPROCESSING)
59  _Objects_MP_Handler_initialization(
60    node,
61    maximum_nodes,
62    maximum_global_objects
63  );
64#endif
65}
66
67/*PAGE
68 *
69 *  _Objects_Extend_information
70 *
71 *  This routine extends all object information related data structures.
72 *
73 *  Input parameters:
74 *    information     - object information table
75 *
76 *  Output parameters:  NONE
77 */
78
79void _Objects_Extend_information(
80  Objects_Information *information
81)
82{
83  Objects_Control  *the_object;
84  void             *name_area;
85  Chain_Control     Inactive;
86  unsigned32        block_count;
87  unsigned32        block;
88  unsigned32        index_base;
89  unsigned32        minimum_index;
90  unsigned32        index;
91
92  /*
93   *  Search for a free block of indexes. The block variable ends up set
94   *  to block_count + 1 if the table needs to be extended.
95   */
96
97  minimum_index = _Objects_Get_index( information->minimum_id );
98  index_base    = minimum_index;
99  block         = 0;
100 
101  if ( information->maximum < minimum_index )
102    block_count = 0;
103  else {
104    block_count = information->maximum / information->allocation_size;
105 
106    for ( ; block < block_count; block++ ) {
107      if ( information->object_blocks[ block ] == NULL )
108        break;
109      else
110        index_base += information->allocation_size;
111    }
112  }
113
114  /*
115   *  If the index_base is the maximum we need to grow the tables.
116   */
117
118  if (index_base >= information->maximum ) {
119    ISR_Level         level;
120    void            **object_blocks;
121    Objects_Name     *name_table;
122    unsigned32       *inactive_per_block;
123    Objects_Control **local_table;
124    unsigned32        maximum;
125    void             *old_tables;   
126   
127    /*
128     *  Growing the tables means allocating a new area, doing a copy and
129     *  updating the information table.
130     *
131     *  If the maximum is minimum we do not have a table to copy. First
132     *  time through.
133     *
134     *  The allocation has :
135     *
136     *      void            *objects[block_count];
137     *      unsigned32       inactive_count[block_count];
138     *      Objects_Name    *name_table[block_count];
139     *      Objects_Control *local_table[maximum];
140     *
141     *  This is the order in memory. Watch changing the order. See the memcpy
142     *  below.
143     */
144
145    /*
146     *  Up the block count and maximum
147     */
148
149    block_count++;
150   
151    maximum = information->maximum + information->allocation_size;
152
153    /*
154     *  Allocate the tables and break it up.
155     */
156   
157    if ( information->auto_extend ) {
158      object_blocks = (void**)
159        _Workspace_Allocate(
160          block_count *
161             (sizeof(void *) + sizeof(unsigned32) + sizeof(Objects_Name *)) +
162          ((maximum + minimum_index) * sizeof(Objects_Control *))
163          );
164
165      if ( !object_blocks )
166        return;
167    }
168    else {
169      object_blocks = (void**)
170        _Workspace_Allocate_or_fatal_error(
171          block_count * 
172             (sizeof(void *) + sizeof(unsigned32) + sizeof(Objects_Name *)) +
173          ((maximum + minimum_index) * sizeof(Objects_Control *))
174        );
175    }
176
177    /*
178     *  Break the block into the various sections.
179     *
180     */
181     
182    inactive_per_block = (unsigned32 *) _Addresses_Add_offset(
183        object_blocks, block_count * sizeof(void*) );
184    name_table = (Objects_Name *) _Addresses_Add_offset(
185        inactive_per_block, block_count * sizeof(unsigned32) );
186    local_table = (Objects_Control **) _Addresses_Add_offset(
187        name_table, block_count * sizeof(Objects_Name *) );
188   
189    /*
190     *  Take the block count down. Saves all the (block_count - 1)
191     *  in the copies.
192     */
193
194    block_count--;
195   
196    if ( information->maximum > minimum_index ) {
197     
198      /*
199       *  Copy each section of the table over. This has to be performed as
200       *  separate parts as size of each block has changed.
201       */
202   
203      memcpy( object_blocks,
204              information->object_blocks,
205              block_count * sizeof(void*) );
206      memcpy( inactive_per_block,
207              information->inactive_per_block,
208              block_count * sizeof(unsigned32) );
209      memcpy( name_table,
210              information->name_table,
211              block_count * sizeof(Objects_Name *) );
212      memcpy( local_table,
213              information->local_table,
214              (information->maximum + minimum_index) * sizeof(Objects_Control *) );
215    }
216    else {
217
218      /*
219       *  Deal with the special case of the 0 to minimum_index
220       */
221      for ( index = 0; index < minimum_index; index++ ) {
222        local_table[ index ] = NULL;
223      }
224    }
225   
226    /*
227     *  Initialise the new entries in the table.
228     */
229   
230    object_blocks[block_count] = NULL;
231    inactive_per_block[block_count] = 0;
232    name_table[block_count] = NULL;
233
234    for ( index=index_base ;
235          index < ( information->allocation_size + index_base );
236          index++ ) {
237      local_table[ index ] = NULL;
238    }
239   
240    _ISR_Disable( level );
241
242    old_tables = information->object_blocks;
243   
244    information->object_blocks = object_blocks;
245    information->inactive_per_block = inactive_per_block;
246    information->name_table = name_table;
247    information->local_table = local_table;
248    information->maximum = maximum;
249    information->maximum_id =
250      _Objects_Build_id(
251        information->the_class, _Objects_Local_node, information->maximum
252      );
253
254    _ISR_Enable( level );
255
256    if ( old_tables )
257      _Workspace_Free( old_tables );
258   
259    block_count++;
260  }
261           
262  /*
263   *  Allocate the name table, and the objects
264   */
265
266  if ( information->auto_extend ) {
267    information->object_blocks[ block ] = 
268      _Workspace_Allocate(
269        (information->allocation_size * information->name_length) +
270        (information->allocation_size * information->size)
271      );
272
273    if ( !information->object_blocks[ block ] )
274      return;
275  }
276  else {
277    information->object_blocks[ block ] = 
278      _Workspace_Allocate_or_fatal_error(
279        (information->allocation_size * information->name_length) +
280        (information->allocation_size * information->size)
281      );
282  }
283 
284  name_area = (Objects_Name *) information->object_blocks[ block ];
285  information->name_table[ block ] = name_area;
286
287  /*
288   *  Initialize objects .. add to a local chain first.
289   */
290
291  _Chain_Initialize(
292    &Inactive,
293    _Addresses_Add_offset( information->object_blocks[ block ],
294                           (information->allocation_size * information->name_length) ),
295    information->allocation_size,
296    information->size
297  );
298
299  /*
300   *  Move from the local chain, initialise, then append to the inactive chain
301   */
302
303  index = index_base;
304 
305  while ( (the_object = (Objects_Control *) _Chain_Get( &Inactive ) ) != NULL ) {
306   
307    the_object->id = 
308      _Objects_Build_id(
309        information->the_class, _Objects_Local_node, index
310      );
311     
312    the_object->name = (void *) name_area;
313
314    name_area = _Addresses_Add_offset( name_area, information->name_length );
315
316    _Chain_Append( &information->Inactive, &the_object->Node );
317
318    index++;
319  }
320 
321  information->inactive_per_block[ block ] = information->allocation_size;
322  information->inactive += information->allocation_size;
323}
324
325/*PAGE
326 *
327 *  _Objects_Shrink_information
328 *
329 *  This routine shrinks object information related data structures.
330 *  The object's name and object space are released. The local_table
331 *  etc block does not shrink. The InActive list needs to be scanned
332 *  to find the objects are remove them.
333 *  Input parameters:
334 *    information     - object information table
335 *    the_block       - the block to remove
336 *
337 *  Output parameters:  NONE
338 */
339
340void _Objects_Shrink_information(
341  Objects_Information *information
342)
343{
344  Objects_Control  *the_object;
345  Objects_Control  *extract_me;
346  unsigned32        block_count;
347  unsigned32        block;
348  unsigned32        index_base;
349  unsigned32        index;
350
351  /*
352   * Search the list to find block or chunnk with all objects inactive.
353   */
354
355  index_base = _Objects_Get_index( information->minimum_id );
356  block_count = ( information->maximum - index_base ) / information->allocation_size;
357 
358  for ( block = 0; block < block_count; block++ ) {
359    if ( information->inactive_per_block[ block ] == information->allocation_size ) {
360
361      /*
362       * XXX - Not to sure how to use a chain where you need to iterate and
363       *       and remove elements.
364       */
365     
366      the_object = (Objects_Control *) information->Inactive.first;
367
368      /*
369       *  Assume the Inactive chain is never empty at this point
370       */
371
372      do {
373        index = _Objects_Get_index( the_object->id );
374
375        if ((index >= index_base) &&
376            (index < (index_base + information->allocation_size))) {
377         
378          /*
379           *  Get the next node before the node is extracted
380           */
381         
382          extract_me = the_object;
383
384          if ( !_Chain_Is_last( &the_object->Node ) )
385            the_object = (Objects_Control *) the_object->Node.next;
386          else
387            the_object = NULL;
388         
389          _Chain_Extract( &extract_me->Node );
390        }
391        else {
392          the_object = (Objects_Control *) the_object->Node.next;
393        }
394      }
395      while ( the_object && !_Chain_Is_last( &the_object->Node ) );
396
397      /*
398       *  Free the memory and reset the structures in the object' information
399       */
400
401      _Workspace_Free( information->object_blocks[ block ] );
402      information->name_table[ block ] = NULL;
403      information->object_blocks[ block ] = NULL;
404      information->inactive_per_block[ block ] = 0;
405
406      information->inactive -= information->allocation_size;
407     
408      return;
409    }
410   
411    index_base += information->allocation_size;
412  }
413}
414
415/*PAGE
416 *
417 *  _Objects_Initialize_information
418 *
419 *  This routine initializes all object information related data structures.
420 *
421 *  Input parameters:
422 *    information         - object information table
423 *    the_class           - object class
424 *    supports_global     - TRUE if this is a global object class
425 *    maximum             - maximum objects of this class
426 *    size                - size of this object's control block
427 *    is_string           - TRUE if names for this object are strings
428 *    maximum_name_length - maximum length of each object's name
429 *    is_thread           - TRUE if this class is threads
430 *
431 *  Output parameters:  NONE
432 */
433
434void _Objects_Initialize_information(
435  Objects_Information *information,
436  Objects_Classes      the_class,
437  boolean              supports_global,
438  unsigned32           maximum,
439  unsigned32           size,
440  boolean              is_string,
441  unsigned32           maximum_name_length,
442  boolean              is_thread
443)
444{
445  static Objects_Control *null_local_table = NULL;
446 
447  unsigned32       minimum_index;
448  unsigned32       index;
449  unsigned32       name_length;
450
451  information->the_class          = the_class; 
452  information->is_string          = is_string; 
453  information->is_thread          = is_thread;
454 
455  information->local_table        = 0;
456  information->name_table         = 0;
457  information->inactive_per_block = 0;
458  information->object_blocks      = 0;
459 
460  information->inactive           = 0;
461 
462  /*
463   *  Set the entry in the object information table.
464   */
465
466  _Objects_Information_table[ the_class ] = information;
467
468  /*
469   *  Set the size of the object
470   */
471
472  information->size = size;
473 
474  /*
475   *  Are we operating in unlimited, or auto-extend mode
476   */
477
478  information->auto_extend = (maximum & OBJECTS_UNLIMITED_OBJECTS) ? TRUE : FALSE;
479  maximum                 &= ~OBJECTS_UNLIMITED_OBJECTS;
480 
481  /*
482   *  The allocation unit is the maximum value
483   */
484
485  information->allocation_size = maximum;
486
487  /*
488   *  Provide a null local table entry for the case of any empty table.
489   */
490
491  information->local_table = &null_local_table;
492
493  /*
494   *  Calculate minimum and maximum Id's
495   */
496
497  if ( maximum == 0 ) minimum_index = 0;
498  else                minimum_index = 1;
499
500  information->minimum_id =
501    _Objects_Build_id( the_class, _Objects_Local_node, minimum_index );
502
503  /*
504   *  Calculate the maximum name length
505   */
506
507  name_length = maximum_name_length;
508
509  if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) )
510    name_length = (name_length + OBJECTS_NAME_ALIGNMENT) & 
511                  ~(OBJECTS_NAME_ALIGNMENT-1);
512
513  information->name_length = name_length;
514
515  _Chain_Initialize_empty( &information->Inactive );
516   
517  /*
518   *  Initialize objects .. if there are any
519   */
520
521  if ( maximum ) {
522
523    /*
524     *  Reset the maximum value. It will be updated when the information is
525     *  extended.
526     */
527   
528    information->maximum = 0;
529   
530    /*
531     *  Always have the maximum size available so the current performance
532     *  figures are create are met.  If the user moves past the maximum
533     *  number then a performance hit is taken.
534     */
535   
536    _Objects_Extend_information( information );
537   
538  }
539
540  /*
541   *  Take care of multiprocessing
542   */
543
544  if ( supports_global == TRUE && _System_state_Is_multiprocessing ) {
545
546    information->global_table =
547      (Chain_Control *) _Workspace_Allocate_or_fatal_error(
548        (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control)
549      );
550
551    for ( index=1; index <= _Objects_Maximum_nodes ; index++ )
552      _Chain_Initialize_empty( &information->global_table[ index ] );
553   }
554   else
555     information->global_table = NULL;
556}
557
558/*PAGE
559 *
560 *  _Objects_Allocate
561 *
562 *  DESCRIPTION:
563 *
564 *  This function allocates a object control block from
565 *  the inactive chain of free object control blocks.
566 */
567
568Objects_Control *_Objects_Allocate(
569  Objects_Information *information
570)
571{
572  Objects_Control *the_object = 
573    (Objects_Control *) _Chain_Get( &information->Inactive );
574
575  if ( information->auto_extend ) {
576    /*
577     *  If the list is empty then we are out of objects and need to
578     *  extend information base.
579     */
580 
581    if ( !the_object ) {
582      _Objects_Extend_information( information );
583      the_object =  (Objects_Control *) _Chain_Get( &information->Inactive );
584    }
585 
586    if ( the_object ) {
587      unsigned32 block;
588   
589      block = _Objects_Get_index( the_object->id ) -
590              _Objects_Get_index( information->minimum_id );
591      block /= information->allocation_size;
592     
593      information->inactive_per_block[ block ]--;
594      information->inactive--;
595    }
596  }
597 
598  return the_object;
599}
600
601/*PAGE
602 *
603 *  _Objects_Allocate_by_index
604 *
605 *  DESCRIPTION:
606 *
607 *  This function allocates the object control block
608 *  specified by the index from the inactive chain of
609 *  free object control blocks.
610 */
611
612Objects_Control *_Objects_Allocate_by_index(
613  Objects_Information *information,
614  unsigned32           index,
615  unsigned32           sizeof_control
616)
617{
618  Objects_Control *the_object;
619  void            *p;
620
621  if ( index && information->maximum >= index ) {
622    the_object = _Objects_Get_local_object( information, index );
623    if ( the_object )
624      return NULL;
625
626    /* XXX
627     *  This whole section of code needs to be addressed.
628     *    +  The 0 should be dealt with more properly so we can autoextend.
629     *    +  The pointer arithmetic is probably too expensive.
630     *    +  etc.
631     */
632   
633    p = _Addresses_Add_offset( information->object_blocks[ 0 ],
634        (information->allocation_size * information->name_length) ),
635
636    p = _Addresses_Add_offset( p, (sizeof_control * (index - 1)) );
637    the_object = (Objects_Control *)p;
638    _Chain_Extract( &the_object->Node );
639 
640    return the_object;   
641  }   
642
643  /*
644   *  Autoextend will have to be thought out as it applies
645   *  to user assigned indices.
646   */
647
648  return NULL;
649}
650
651
652
653/*PAGE
654 *
655 *  _Objects_Free
656 *
657 *  DESCRIPTION:
658 *
659 *  This function frees a object control block to the
660 *  inactive chain of free object control blocks.
661 */
662
663void _Objects_Free(
664  Objects_Information *information,
665  Objects_Control     *the_object
666)
667{
668  unsigned32  allocation_size = information->allocation_size;
669
670  _Chain_Append( &information->Inactive, &the_object->Node );
671
672  if ( information->auto_extend ) {
673    unsigned32  block;
674   
675    block = 
676      _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id );
677    block /= information->allocation_size;
678     
679    information->inactive_per_block[ block ]++;
680    information->inactive++;
681 
682    /*
683     *  Check if the threshold level has been met of
684     *  1.5 x allocation_size are free.
685     */
686
687    if ( information->inactive > ( allocation_size + ( allocation_size >> 1 ) ) ) {
688      _Objects_Shrink_information( information );
689    }
690  }
691}
692
693/*PAGE
694 *
695 *  _Objects_Clear_name
696 *
697 *  XXX
698 */
699
700void _Objects_Clear_name(
701  void       *name,
702  unsigned32  length
703)
704{
705  unsigned32  index;
706  unsigned32  maximum = length / OBJECTS_NAME_ALIGNMENT;
707  unsigned32 *name_ptr = (unsigned32 *) name;
708
709  for ( index=0 ; index < maximum ; index++ ) 
710    *name_ptr++ = 0;
711}
712 
713/*PAGE
714 *
715 *  _Objects_Copy_name_string
716 *
717 *  XXX
718 */
719 
720void _Objects_Copy_name_string(
721  void       *source,
722  void       *destination
723)
724{
725  unsigned8 *source_p = (unsigned8 *) source;
726  unsigned8 *destination_p = (unsigned8 *) destination;
727 
728  do {
729    *destination_p++ = *source_p;
730  } while ( *source_p++ );
731}
732
733/*PAGE
734 *
735 *  _Objects_Copy_name_raw
736 *
737 *  XXX
738 */
739 
740void _Objects_Copy_name_raw(
741  void       *source,
742  void       *destination,
743  unsigned32  length
744)
745{
746  unsigned32 *source_p = (unsigned32 *) source;
747  unsigned32 *destination_p = (unsigned32 *) destination;
748  unsigned32  tmp_length = length / OBJECTS_NAME_ALIGNMENT;
749 
750  while ( tmp_length-- )
751    *destination_p++ = *source_p++;
752}
753
754/*PAGE
755 *
756 *  _Objects_Compare_name_string
757 *
758 *  XXX
759 */
760 
761boolean _Objects_Compare_name_string(
762  void       *name_1,
763  void       *name_2,
764  unsigned32  length
765)
766{
767  unsigned8 *name_1_p = (unsigned8 *) name_1;
768  unsigned8 *name_2_p = (unsigned8 *) name_2;
769  unsigned32 tmp_length = length;
770 
771  do {
772    if ( *name_1_p++ != *name_2_p++ )
773      return FALSE;
774    if ( !tmp_length-- )
775      return FALSE;
776  } while ( *name_1_p );
777
778  return TRUE;
779}
780 
781/*PAGE
782 *
783 *  _Objects_Compare_name_raw
784 *
785 *  XXX
786 */
787 
788boolean _Objects_Compare_name_raw(
789  void       *name_1,
790  void       *name_2,
791  unsigned32  length
792)
793{
794  unsigned32 *name_1_p = (unsigned32 *) name_1;
795  unsigned32 *name_2_p = (unsigned32 *) name_2;
796  unsigned32  tmp_length = length / OBJECTS_NAME_ALIGNMENT;
797 
798  while ( tmp_length-- )
799    if ( *name_1_p++ != *name_2_p++ )
800      return FALSE;
801
802  return TRUE;
803}
804
805
806/*PAGE
807 *
808 *  _Objects_Name_to_id
809 *
810 *  These kernel routines search the object table(s) for the given
811 *  object name and returns the associated object id.
812 *
813 *  Input parameters:
814 *    information - object information
815 *    name        - user defined object name
816 *    node        - node indentifier (0 indicates any node)
817 *    id          - address of return ID
818 *
819 *  Output parameters:
820 *    id                 - object id
821 *    OBJECTS_SUCCESSFUL - if successful
822 *    error code         - if unsuccessful
823 */
824
825Objects_Name_to_id_errors _Objects_Name_to_id(
826  Objects_Information *information,
827  Objects_Name         name,
828  unsigned32           node,
829  Objects_Id          *id
830)
831{
832  boolean                    search_local_node;
833  Objects_Control           *the_object;
834  unsigned32                 index;
835  unsigned32                 name_length;
836  Objects_Name_comparators   compare_them;
837
838  if ( name == 0 )
839    return OBJECTS_INVALID_NAME;
840
841  search_local_node = FALSE;
842
843  if ( information->maximum != 0 &&
844      (node == OBJECTS_SEARCH_ALL_NODES || node == OBJECTS_SEARCH_LOCAL_NODE ||
845      _Objects_Is_local_node( node ) ) )
846   search_local_node = TRUE;
847
848  if ( search_local_node ) {
849    name_length = information->name_length;
850
851    if ( information->is_string ) compare_them = _Objects_Compare_name_string;
852    else                          compare_them = _Objects_Compare_name_raw;
853
854    for ( index = 1; index <= information->maximum; index++ ) {
855
856      the_object = information->local_table[ index ];
857
858      if ( !the_object || !the_object->name )
859        continue;
860
861      if ( (*compare_them)( name, the_object->name, name_length ) ) {
862        *id = the_object->id;
863        return OBJECTS_SUCCESSFUL;
864      }
865    }
866  }
867
868  if ( _Objects_Is_local_node( node ) || node == OBJECTS_SEARCH_LOCAL_NODE )
869    return OBJECTS_INVALID_NAME;
870
871#if defined(RTEMS_MULTIPROCESSING)
872  return ( _Objects_MP_Global_name_search( information, name, node, id ) );
873#else
874  return OBJECTS_INVALID_NAME;
875#endif
876}
877
878/*PAGE
879 *
880 * _Objects_Get
881 *
882 * This routine sets the object pointer for the given
883 * object id based on the given object information structure.
884 *
885 * Input parameters:
886 *   information - pointer to entry in table for this class
887 *   id          - object id to search for
888 *   location    - address of where to store the location
889 *
890 * Output parameters:
891 *   returns  - address of object if local
892 *   location - one of the following:
893 *                  OBJECTS_ERROR  - invalid object ID
894 *                  OBJECTS_REMOTE - remote object
895 *                  OBJECTS_LOCAL  - local object
896 */
897
898Objects_Control *_Objects_Get(
899  Objects_Information *information,
900  Objects_Id           id,
901  Objects_Locations   *location
902)
903{
904  Objects_Control *the_object;
905  unsigned32       index;
906
907  index = _Objects_Get_index( id );
908
909  if ( information->maximum >= index ) {
910    _Thread_Disable_dispatch();
911    if ( (the_object = _Objects_Get_local_object( information, index )) != NULL ) {
912      *location = OBJECTS_LOCAL;
913      return( the_object );
914    }
915    _Thread_Enable_dispatch();
916    *location = OBJECTS_ERROR;
917    return( NULL );
918  }
919  *location = OBJECTS_ERROR;
920#if defined(RTEMS_MULTIPROCESSING)
921  _Objects_MP_Is_remote(
922    information,
923    _Objects_Build_id( information->the_class, _Objects_Local_node, index ),
924    location,
925    &the_object
926  );
927  return the_object;
928#else
929  return NULL;
930#endif
931}
932
933/*PAGE
934 *
935 * _Objects_Get_by_index
936 *
937 * This routine sets the object pointer for the given
938 * object id based on the given object information structure.
939 *
940 * Input parameters:
941 *   information - pointer to entry in table for this class
942 *   index       - object index to check for
943 *   location    - address of where to store the location
944 *
945 * Output parameters:
946 *   returns  - address of object if local
947 *   location - one of the following:
948 *                  OBJECTS_ERROR  - invalid object ID
949 *                  OBJECTS_REMOTE - remote object
950 *                  OBJECTS_LOCAL  - local object
951 */
952
953Objects_Control *_Objects_Get_by_index(
954  Objects_Information *information,
955  unsigned32           index,
956  Objects_Locations   *location
957)
958{
959  Objects_Control *the_object;
960
961  if ( information->maximum >= index ) {
962    _Thread_Disable_dispatch();
963    if ( (the_object = _Objects_Get_local_object( information, index )) != NULL ) {
964      *location = OBJECTS_LOCAL;
965      return( the_object );
966    }
967    _Thread_Enable_dispatch();
968    *location = OBJECTS_ERROR;
969    return( NULL );
970  }
971
972  /*
973   *  With just an index, you can't access a remote object.
974   */
975
976  _Thread_Enable_dispatch();
977  *location = OBJECTS_ERROR;
978  return NULL;
979}
980
981/*PAGE
982 *
983 * _Objects_Get_next
984 *
985 * Like _Objects_Get, but considers the 'id' as a "hint" and
986 * finds next valid one after that point.
987 * Mostly used for monitor and debug traversal of an object.
988 *
989 * Input parameters:
990 *   information - pointer to entry in table for this class
991 *   id          - object id to search for
992 *   location    - address of where to store the location
993 *   next_id     - address to store next id to try
994 *
995 * Output parameters:
996 *   returns     - address of object if local
997 *   location    - one of the following:
998 *                  OBJECTS_ERROR  - invalid object ID
999 *                  OBJECTS_REMOTE - remote object
1000 *                  OBJECTS_LOCAL  - local object
1001 *   next_id     - will contain a reasonable "next" id to continue traversal
1002 *
1003 * NOTE:
1004 *      assumes can add '1' to an id to get to next index.
1005 */
1006
1007Objects_Control *
1008_Objects_Get_next(
1009    Objects_Information *information,
1010    Objects_Id           id,
1011    Objects_Locations   *location_p,
1012    Objects_Id          *next_id_p
1013)
1014{
1015    Objects_Control *object;
1016    Objects_Id       next_id;
1017   
1018    if (_Objects_Get_index(id) == OBJECTS_ID_INITIAL_INDEX)
1019        next_id = information->minimum_id;
1020    else
1021        next_id = id;
1022
1023    do {
1024        /* walked off end of list? */
1025        if (_Objects_Get_index(next_id) > information->maximum)
1026        {
1027            *location_p = OBJECTS_ERROR;
1028            goto final;
1029        }
1030       
1031        /* try to grab one */
1032        object = _Objects_Get(information, next_id, location_p);
1033
1034        next_id++;
1035
1036    } while (*location_p != OBJECTS_LOCAL);
1037
1038    *next_id_p = next_id;
1039    return object;
1040
1041final:
1042    *next_id_p = OBJECTS_ID_FINAL;
1043    return 0;
1044}
1045
Note: See TracBrowser for help on using the repository browser.