source: rtems/cpukit/score/src/object.c @ 5d36b344

4.104.114.84.95
Last change on this file since 5d36b344 was 5d36b344, checked in by Joel Sherrill <joel.sherrill@…>, on 11/02/99 at 16:01:52

Fixed bug which resulted in misaligned object control structures
being allocated. This bug manifested itself on the SPARC
since it uses ldd/std in its context save/restore routines.

  • 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 *) _Addresses_Add_offset(
285    information->object_blocks[ block ],
286    (information->allocation_size * information->size)
287  );
288  information->name_table[ block ] = name_area;
289
290  /*
291   *  Initialize objects .. add to a local chain first.
292   */
293
294  _Chain_Initialize(
295    &Inactive,
296    information->object_blocks[ block ],
297    information->allocation_size,
298    information->size
299  );
300
301  /*
302   *  Move from the local chain, initialise, then append to the inactive chain
303   */
304
305  index = index_base;
306 
307  while ( (the_object = (Objects_Control *) _Chain_Get( &Inactive ) ) != NULL ) {
308   
309    the_object->id =
310      _Objects_Build_id(
311        information->the_class, _Objects_Local_node, index
312      );
313     
314    the_object->name = (void *) name_area;
315
316    name_area = _Addresses_Add_offset( name_area, information->name_length );
317
318    _Chain_Append( &information->Inactive, &the_object->Node );
319
320    index++;
321  }
322 
323  information->inactive_per_block[ block ] = information->allocation_size;
324  information->inactive += information->allocation_size;
325}
326
327/*PAGE
328 *
329 *  _Objects_Shrink_information
330 *
331 *  This routine shrinks object information related data structures.
332 *  The object's name and object space are released. The local_table
333 *  etc block does not shrink. The InActive list needs to be scanned
334 *  to find the objects are remove them.
335 *  Input parameters:
336 *    information     - object information table
337 *    the_block       - the block to remove
338 *
339 *  Output parameters:  NONE
340 */
341
342void _Objects_Shrink_information(
343  Objects_Information *information
344)
345{
346  Objects_Control  *the_object;
347  Objects_Control  *extract_me;
348  unsigned32        block_count;
349  unsigned32        block;
350  unsigned32        index_base;
351  unsigned32        index;
352
353  /*
354   * Search the list to find block or chunnk with all objects inactive.
355   */
356
357  index_base = _Objects_Get_index( information->minimum_id );
358  block_count = ( information->maximum - index_base ) / information->allocation_size;
359 
360  for ( block = 0; block < block_count; block++ ) {
361    if ( information->inactive_per_block[ block ] == information->allocation_size ) {
362
363      /*
364       * XXX - Not to sure how to use a chain where you need to iterate and
365       *       and remove elements.
366       */
367     
368      the_object = (Objects_Control *) information->Inactive.first;
369
370      /*
371       *  Assume the Inactive chain is never empty at this point
372       */
373
374      do {
375        index = _Objects_Get_index( the_object->id );
376
377        if ((index >= index_base) &&
378            (index < (index_base + information->allocation_size))) {
379         
380          /*
381           *  Get the next node before the node is extracted
382           */
383         
384          extract_me = the_object;
385
386          if ( !_Chain_Is_last( &the_object->Node ) )
387            the_object = (Objects_Control *) the_object->Node.next;
388          else
389            the_object = NULL;
390         
391          _Chain_Extract( &extract_me->Node );
392        }
393        else {
394          the_object = (Objects_Control *) the_object->Node.next;
395        }
396      }
397      while ( the_object && !_Chain_Is_last( &the_object->Node ) );
398
399      /*
400       *  Free the memory and reset the structures in the object' information
401       */
402
403      _Workspace_Free( information->object_blocks[ block ] );
404      information->name_table[ block ] = NULL;
405      information->object_blocks[ block ] = NULL;
406      information->inactive_per_block[ block ] = 0;
407
408      information->inactive -= information->allocation_size;
409     
410      return;
411    }
412   
413    index_base += information->allocation_size;
414  }
415}
416
417/*PAGE
418 *
419 *  _Objects_Initialize_information
420 *
421 *  This routine initializes all object information related data structures.
422 *
423 *  Input parameters:
424 *    information         - object information table
425 *    the_class           - object class
426 *    supports_global     - TRUE if this is a global object class
427 *    maximum             - maximum objects of this class
428 *    size                - size of this object's control block
429 *    is_string           - TRUE if names for this object are strings
430 *    maximum_name_length - maximum length of each object's name
431 *    is_thread           - TRUE if this class is threads
432 *
433 *  Output parameters:  NONE
434 */
435
436void _Objects_Initialize_information(
437  Objects_Information *information,
438  Objects_Classes      the_class,
439  boolean              supports_global,
440  unsigned32           maximum,
441  unsigned32           size,
442  boolean              is_string,
443  unsigned32           maximum_name_length,
444  boolean              is_thread
445)
446{
447  static Objects_Control *null_local_table = NULL;
448 
449  unsigned32       minimum_index;
450  unsigned32       index;
451  unsigned32       name_length;
452
453  information->the_class          = the_class;
454  information->is_string          = is_string;
455  information->is_thread          = is_thread;
456 
457  information->local_table        = 0;
458  information->name_table         = 0;
459  information->inactive_per_block = 0;
460  information->object_blocks      = 0;
461 
462  information->inactive           = 0;
463 
464  /*
465   *  Set the entry in the object information table.
466   */
467
468  _Objects_Information_table[ the_class ] = information;
469
470  /*
471   *  Set the size of the object
472   */
473
474  information->size = size;
475 
476  /*
477   *  Are we operating in unlimited, or auto-extend mode
478   */
479
480  information->auto_extend = (maximum & OBJECTS_UNLIMITED_OBJECTS) ? TRUE : FALSE;
481  maximum                 &= ~OBJECTS_UNLIMITED_OBJECTS;
482 
483  /*
484   *  The allocation unit is the maximum value
485   */
486
487  information->allocation_size = maximum;
488
489  /*
490   *  Provide a null local table entry for the case of any empty table.
491   */
492
493  information->local_table = &null_local_table;
494
495  /*
496   *  Calculate minimum and maximum Id's
497   */
498
499  if ( maximum == 0 ) minimum_index = 0;
500  else                minimum_index = 1;
501
502  information->minimum_id =
503    _Objects_Build_id( the_class, _Objects_Local_node, minimum_index );
504
505  /*
506   *  Calculate the maximum name length
507   */
508
509  name_length = maximum_name_length;
510
511  if ( name_length & (OBJECTS_NAME_ALIGNMENT-1) )
512    name_length = (name_length + OBJECTS_NAME_ALIGNMENT) &
513                  ~(OBJECTS_NAME_ALIGNMENT-1);
514
515  information->name_length = name_length;
516
517  _Chain_Initialize_empty( &information->Inactive );
518   
519  /*
520   *  Initialize objects .. if there are any
521   */
522
523  if ( maximum ) {
524
525    /*
526     *  Reset the maximum value. It will be updated when the information is
527     *  extended.
528     */
529   
530    information->maximum = 0;
531   
532    /*
533     *  Always have the maximum size available so the current performance
534     *  figures are create are met.  If the user moves past the maximum
535     *  number then a performance hit is taken.
536     */
537   
538    _Objects_Extend_information( information );
539   
540  }
541
542  /*
543   *  Take care of multiprocessing
544   */
545
546  if ( supports_global == TRUE && _System_state_Is_multiprocessing ) {
547
548    information->global_table =
549      (Chain_Control *) _Workspace_Allocate_or_fatal_error(
550        (_Objects_Maximum_nodes + 1) * sizeof(Chain_Control)
551      );
552
553    for ( index=1; index <= _Objects_Maximum_nodes ; index++ )
554      _Chain_Initialize_empty( &information->global_table[ index ] );
555   }
556   else
557     information->global_table = NULL;
558}
559
560/*PAGE
561 *
562 *  _Objects_Allocate
563 *
564 *  DESCRIPTION:
565 *
566 *  This function allocates a object control block from
567 *  the inactive chain of free object control blocks.
568 */
569
570Objects_Control *_Objects_Allocate(
571  Objects_Information *information
572)
573{
574  Objects_Control *the_object = 
575    (Objects_Control *) _Chain_Get( &information->Inactive );
576
577  if ( information->auto_extend ) {
578    /*
579     *  If the list is empty then we are out of objects and need to
580     *  extend information base.
581     */
582 
583    if ( !the_object ) {
584      _Objects_Extend_information( information );
585      the_object =  (Objects_Control *) _Chain_Get( &information->Inactive );
586    }
587 
588    if ( the_object ) {
589      unsigned32 block;
590   
591      block = _Objects_Get_index( the_object->id ) -
592              _Objects_Get_index( information->minimum_id );
593      block /= information->allocation_size;
594     
595      information->inactive_per_block[ block ]--;
596      information->inactive--;
597    }
598  }
599 
600  return the_object;
601}
602
603/*PAGE
604 *
605 *  _Objects_Allocate_by_index
606 *
607 *  DESCRIPTION:
608 *
609 *  This function allocates the object control block
610 *  specified by the index from the inactive chain of
611 *  free object control blocks.
612 */
613
614Objects_Control *_Objects_Allocate_by_index(
615  Objects_Information *information,
616  unsigned32           index,
617  unsigned32           sizeof_control
618)
619{
620  Objects_Control *the_object;
621  void            *p;
622
623  if ( index && information->maximum >= index ) {
624    the_object = _Objects_Get_local_object( information, index );
625    if ( the_object )
626      return NULL;
627
628    /* XXX
629     *  This whole section of code needs to be addressed.
630     *    +  The 0 should be dealt with more properly so we can autoextend.
631     *    +  The pointer arithmetic is probably too expensive.
632     *    +  etc.
633     */
634   
635    p = _Addresses_Add_offset( information->object_blocks[ 0 ],
636        (information->allocation_size * information->name_length) ),
637
638    p = _Addresses_Add_offset( p, (sizeof_control * (index - 1)) );
639    the_object = (Objects_Control *)p;
640    _Chain_Extract( &the_object->Node );
641 
642    return the_object;   
643  }   
644
645  /*
646   *  Autoextend will have to be thought out as it applies
647   *  to user assigned indices.
648   */
649
650  return NULL;
651}
652
653
654
655/*PAGE
656 *
657 *  _Objects_Free
658 *
659 *  DESCRIPTION:
660 *
661 *  This function frees a object control block to the
662 *  inactive chain of free object control blocks.
663 */
664
665void _Objects_Free(
666  Objects_Information *information,
667  Objects_Control     *the_object
668)
669{
670  unsigned32  allocation_size = information->allocation_size;
671
672  _Chain_Append( &information->Inactive, &the_object->Node );
673
674  if ( information->auto_extend ) {
675    unsigned32  block;
676   
677    block =
678      _Objects_Get_index( the_object->id ) - _Objects_Get_index( information->minimum_id );
679    block /= information->allocation_size;
680     
681    information->inactive_per_block[ block ]++;
682    information->inactive++;
683 
684    /*
685     *  Check if the threshold level has been met of
686     *  1.5 x allocation_size are free.
687     */
688
689    if ( information->inactive > ( allocation_size + ( allocation_size >> 1 ) ) ) {
690      _Objects_Shrink_information( information );
691    }
692  }
693}
694
695/*PAGE
696 *
697 *  _Objects_Clear_name
698 *
699 *  XXX
700 */
701
702void _Objects_Clear_name(
703  void       *name,
704  unsigned32  length
705)
706{
707  unsigned32  index;
708  unsigned32  maximum = length / OBJECTS_NAME_ALIGNMENT;
709  unsigned32 *name_ptr = (unsigned32 *) name;
710
711  for ( index=0 ; index < maximum ; index++ )
712    *name_ptr++ = 0;
713}
714 
715/*PAGE
716 *
717 *  _Objects_Copy_name_string
718 *
719 *  XXX
720 */
721 
722void _Objects_Copy_name_string(
723  void       *source,
724  void       *destination
725)
726{
727  unsigned8 *source_p = (unsigned8 *) source;
728  unsigned8 *destination_p = (unsigned8 *) destination;
729 
730  do {
731    *destination_p++ = *source_p;
732  } while ( *source_p++ );
733}
734
735/*PAGE
736 *
737 *  _Objects_Copy_name_raw
738 *
739 *  XXX
740 */
741 
742void _Objects_Copy_name_raw(
743  void       *source,
744  void       *destination,
745  unsigned32  length
746)
747{
748  unsigned32 *source_p = (unsigned32 *) source;
749  unsigned32 *destination_p = (unsigned32 *) destination;
750  unsigned32  tmp_length = length / OBJECTS_NAME_ALIGNMENT;
751 
752  while ( tmp_length-- )
753    *destination_p++ = *source_p++;
754}
755
756/*PAGE
757 *
758 *  _Objects_Compare_name_string
759 *
760 *  XXX
761 */
762 
763boolean _Objects_Compare_name_string(
764  void       *name_1,
765  void       *name_2,
766  unsigned32  length
767)
768{
769  unsigned8 *name_1_p = (unsigned8 *) name_1;
770  unsigned8 *name_2_p = (unsigned8 *) name_2;
771  unsigned32 tmp_length = length;
772 
773  do {
774    if ( *name_1_p++ != *name_2_p++ )
775      return FALSE;
776    if ( !tmp_length-- )
777      return FALSE;
778  } while ( *name_1_p );
779
780  return TRUE;
781}
782 
783/*PAGE
784 *
785 *  _Objects_Compare_name_raw
786 *
787 *  XXX
788 */
789 
790boolean _Objects_Compare_name_raw(
791  void       *name_1,
792  void       *name_2,
793  unsigned32  length
794)
795{
796  unsigned32 *name_1_p = (unsigned32 *) name_1;
797  unsigned32 *name_2_p = (unsigned32 *) name_2;
798  unsigned32  tmp_length = length / OBJECTS_NAME_ALIGNMENT;
799 
800  while ( tmp_length-- )
801    if ( *name_1_p++ != *name_2_p++ )
802      return FALSE;
803
804  return TRUE;
805}
806
807
808/*PAGE
809 *
810 *  _Objects_Name_to_id
811 *
812 *  These kernel routines search the object table(s) for the given
813 *  object name and returns the associated object id.
814 *
815 *  Input parameters:
816 *    information - object information
817 *    name        - user defined object name
818 *    node        - node indentifier (0 indicates any node)
819 *    id          - address of return ID
820 *
821 *  Output parameters:
822 *    id                 - object id
823 *    OBJECTS_SUCCESSFUL - if successful
824 *    error code         - if unsuccessful
825 */
826
827Objects_Name_to_id_errors _Objects_Name_to_id(
828  Objects_Information *information,
829  Objects_Name         name,
830  unsigned32           node,
831  Objects_Id          *id
832)
833{
834  boolean                    search_local_node;
835  Objects_Control           *the_object;
836  unsigned32                 index;
837  unsigned32                 name_length;
838  Objects_Name_comparators   compare_them;
839
840  if ( name == 0 )
841    return OBJECTS_INVALID_NAME;
842
843  search_local_node = FALSE;
844
845  if ( information->maximum != 0 &&
846      (node == OBJECTS_SEARCH_ALL_NODES || node == OBJECTS_SEARCH_LOCAL_NODE ||
847      _Objects_Is_local_node( node ) ) )
848   search_local_node = TRUE;
849
850  if ( search_local_node ) {
851    name_length = information->name_length;
852
853    if ( information->is_string ) compare_them = _Objects_Compare_name_string;
854    else                          compare_them = _Objects_Compare_name_raw;
855
856    for ( index = 1; index <= information->maximum; index++ ) {
857
858      the_object = information->local_table[ index ];
859
860      if ( !the_object || !the_object->name )
861        continue;
862
863      if ( (*compare_them)( name, the_object->name, name_length ) ) {
864        *id = the_object->id;
865        return OBJECTS_SUCCESSFUL;
866      }
867    }
868  }
869
870  if ( _Objects_Is_local_node( node ) || node == OBJECTS_SEARCH_LOCAL_NODE )
871    return OBJECTS_INVALID_NAME;
872
873#if defined(RTEMS_MULTIPROCESSING)
874  return ( _Objects_MP_Global_name_search( information, name, node, id ) );
875#else
876  return OBJECTS_INVALID_NAME;
877#endif
878}
879
880/*PAGE
881 *
882 * _Objects_Get
883 *
884 * This routine sets the object pointer for the given
885 * object id based on the given object information structure.
886 *
887 * Input parameters:
888 *   information - pointer to entry in table for this class
889 *   id          - object id to search for
890 *   location    - address of where to store the location
891 *
892 * Output parameters:
893 *   returns  - address of object if local
894 *   location - one of the following:
895 *                  OBJECTS_ERROR  - invalid object ID
896 *                  OBJECTS_REMOTE - remote object
897 *                  OBJECTS_LOCAL  - local object
898 */
899
900Objects_Control *_Objects_Get(
901  Objects_Information *information,
902  Objects_Id           id,
903  Objects_Locations   *location
904)
905{
906  Objects_Control *the_object;
907  unsigned32       index;
908
909  index = _Objects_Get_index( id );
910
911  if ( information->maximum >= index ) {
912    _Thread_Disable_dispatch();
913    if ( (the_object = _Objects_Get_local_object( information, index )) != NULL ) {
914      *location = OBJECTS_LOCAL;
915      return( the_object );
916    }
917    _Thread_Enable_dispatch();
918    *location = OBJECTS_ERROR;
919    return( NULL );
920  }
921  *location = OBJECTS_ERROR;
922#if defined(RTEMS_MULTIPROCESSING)
923  _Objects_MP_Is_remote(
924    information,
925    _Objects_Build_id( information->the_class, _Objects_Local_node, index ),
926    location,
927    &the_object
928  );
929  return the_object;
930#else
931  return NULL;
932#endif
933}
934
935/*PAGE
936 *
937 * _Objects_Get_by_index
938 *
939 * This routine sets the object pointer for the given
940 * object id based on the given object information structure.
941 *
942 * Input parameters:
943 *   information - pointer to entry in table for this class
944 *   index       - object index to check for
945 *   location    - address of where to store the location
946 *
947 * Output parameters:
948 *   returns  - address of object if local
949 *   location - one of the following:
950 *                  OBJECTS_ERROR  - invalid object ID
951 *                  OBJECTS_REMOTE - remote object
952 *                  OBJECTS_LOCAL  - local object
953 */
954
955Objects_Control *_Objects_Get_by_index(
956  Objects_Information *information,
957  unsigned32           index,
958  Objects_Locations   *location
959)
960{
961  Objects_Control *the_object;
962
963  if ( information->maximum >= index ) {
964    _Thread_Disable_dispatch();
965    if ( (the_object = _Objects_Get_local_object( information, index )) != NULL ) {
966      *location = OBJECTS_LOCAL;
967      return( the_object );
968    }
969    _Thread_Enable_dispatch();
970    *location = OBJECTS_ERROR;
971    return( NULL );
972  }
973
974  /*
975   *  With just an index, you can't access a remote object.
976   */
977
978  _Thread_Enable_dispatch();
979  *location = OBJECTS_ERROR;
980  return NULL;
981}
982
983/*PAGE
984 *
985 * _Objects_Get_next
986 *
987 * Like _Objects_Get, but considers the 'id' as a "hint" and
988 * finds next valid one after that point.
989 * Mostly used for monitor and debug traversal of an object.
990 *
991 * Input parameters:
992 *   information - pointer to entry in table for this class
993 *   id          - object id to search for
994 *   location    - address of where to store the location
995 *   next_id     - address to store next id to try
996 *
997 * Output parameters:
998 *   returns     - address of object if local
999 *   location    - one of the following:
1000 *                  OBJECTS_ERROR  - invalid object ID
1001 *                  OBJECTS_REMOTE - remote object
1002 *                  OBJECTS_LOCAL  - local object
1003 *   next_id     - will contain a reasonable "next" id to continue traversal
1004 *
1005 * NOTE:
1006 *      assumes can add '1' to an id to get to next index.
1007 */
1008
1009Objects_Control *
1010_Objects_Get_next(
1011    Objects_Information *information,
1012    Objects_Id           id,
1013    Objects_Locations   *location_p,
1014    Objects_Id          *next_id_p
1015)
1016{
1017    Objects_Control *object;
1018    Objects_Id       next_id;
1019   
1020    if (_Objects_Get_index(id) == OBJECTS_ID_INITIAL_INDEX)
1021        next_id = information->minimum_id;
1022    else
1023        next_id = id;
1024
1025    do {
1026        /* walked off end of list? */
1027        if (_Objects_Get_index(next_id) > information->maximum)
1028        {
1029            *location_p = OBJECTS_ERROR;
1030            goto final;
1031        }
1032       
1033        /* try to grab one */
1034        object = _Objects_Get(information, next_id, location_p);
1035
1036        next_id++;
1037
1038    } while (*location_p != OBJECTS_LOCAL);
1039
1040    *next_id_p = next_id;
1041    return object;
1042
1043final:
1044    *next_id_p = OBJECTS_ID_FINAL;
1045    return 0;
1046}
1047
Note: See TracBrowser for help on using the repository browser.