source: rtems/cpukit/score/src/objectextendinformation.c @ 3899bc1a

5
Last change on this file since 3899bc1a was 3899bc1a, checked in by Sebastian Huber <sebastian.huber@…>, on 11/24/18 at 10:51:28

score: Optimize object lookup

Use the maximum ID for the ID to object translation. Using the maximum
ID gets rid of an additional load from the object information in
_Objects_Get(). In addition, object lookups fail for every ID in case
the object information is cleared to zero. This makes it a bit more
robust during system startup (see new tests in spconfig02).

The local table no longer needs a NULL pointer entry at array index
zero. Adjust all the object iteration loops accordingly.

Remove Objects_Information::minimum_id since it contains only redundant
information. Add _Objects_Get_minimum_id() to get the minimum ID.

Update #3621.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/**
2 * @file
3 *
4 * @brief Extend Set of Objects
5 * @ingroup ScoreObject
6 */
7
8/*
9 *  COPYRIGHT (c) 1989-1999.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
14 *  http://www.rtems.org/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/score/objectimpl.h>
22#include <rtems/score/address.h>
23#include <rtems/score/assert.h>
24#include <rtems/score/chainimpl.h>
25#include <rtems/score/isrlevel.h>
26#include <rtems/score/sysstate.h>
27#include <rtems/score/wkspace.h>
28
29#include <string.h>  /* for memcpy() */
30
31/*
32 *  _Objects_Extend_information
33 *
34 *  This routine extends all object information related data structures.
35 *
36 *  Input parameters:
37 *    information     - object information table
38 *
39 *  Output parameters:  NONE
40 */
41
42void _Objects_Extend_information(
43  Objects_Information *information
44)
45{
46  Objects_Control  *the_object;
47  uint32_t          block_count;
48  uint32_t          block;
49  uint32_t          index_base;
50  uint32_t          index_end;
51  uint32_t          index;
52  uint32_t          maximum;
53  size_t            object_block_size;
54  Objects_Control  *new_object_block;
55  bool              do_extend;
56
57  _Assert(
58    _Objects_Allocator_is_owner()
59      || !_System_state_Is_up( _System_state_Get() )
60  );
61
62  /*
63   *  Search for a free block of indexes. If we do NOT need to allocate or
64   *  extend the block table, then we will change do_extend.
65   */
66  do_extend     = true;
67  index_base    = 0;
68  block         = 0;
69
70  if ( information->object_blocks == NULL )
71    block_count = 0;
72  else {
73    block_count = information->maximum / information->objects_per_block;
74
75    for ( ; block < block_count; block++ ) {
76      if ( information->object_blocks[ block ] == NULL ) {
77        do_extend = false;
78        break;
79      } else
80        index_base += information->objects_per_block;
81    }
82  }
83  index_end = index_base + information->objects_per_block;
84
85  maximum = (uint32_t) information->maximum + information->objects_per_block;
86
87  /*
88   *  We need to limit the number of objects to the maximum number
89   *  representable in the index portion of the object Id.  In the
90   *  case of 16-bit Ids, this is only 256 object instances.
91   */
92  if ( maximum > OBJECTS_ID_FINAL_INDEX ) {
93    return;
94  }
95
96  /*
97   * Allocate the name table, and the objects and if it fails either return or
98   * generate a fatal error depending on auto-extending being active.
99   */
100  object_block_size = information->objects_per_block
101    * information->object_size;
102  if ( information->auto_extend ) {
103    new_object_block = _Workspace_Allocate( object_block_size );
104    if ( !new_object_block )
105      return;
106  } else {
107    new_object_block = _Workspace_Allocate_or_fatal_error( object_block_size );
108  }
109
110  /*
111   *  Do we need to grow the tables?
112   */
113  if ( do_extend ) {
114    ISR_lock_Context  lock_context;
115    Objects_Control **object_blocks;
116    Objects_Control **local_table;
117    Objects_Maximum  *inactive_per_block;
118    void             *old_tables;
119    size_t            table_size;
120    uintptr_t         object_blocks_size;
121    uintptr_t         local_table_size;
122
123    /*
124     *  Growing the tables means allocating a new area, doing a copy and
125     *  updating the information table.
126     *
127     *  If the maximum is minimum we do not have a table to copy. First
128     *  time through.
129     *
130     *  The allocation has:
131     *
132     *      Objects_Control *object_blocks[ block_count ];
133     *      Objects_Control *local_table[ maximum ];
134     *      Objects_Maximum  inactive_count[ block_count ];
135     *
136     *  This is the order in memory. Watch changing the order. See the memcpy
137     *  below.
138     */
139
140    /*
141     *  Up the block count and maximum.
142     */
143    block_count++;
144
145    /*
146     *  Allocate the tables and break it up.
147     */
148    object_blocks_size = block_count * sizeof( *object_blocks );
149    local_table_size =  maximum * sizeof( *local_table );
150    table_size = object_blocks_size
151      + local_table_size
152      + block_count * sizeof( *inactive_per_block );
153    if ( information->auto_extend ) {
154      object_blocks = _Workspace_Allocate( table_size );
155      if ( !object_blocks ) {
156        _Workspace_Free( new_object_block );
157        return;
158      }
159    } else {
160      object_blocks = _Workspace_Allocate_or_fatal_error( table_size );
161    }
162
163    /*
164     *  Break the block into the various sections.
165     */
166    local_table = _Addresses_Add_offset(
167      object_blocks,
168      object_blocks_size
169    );
170    inactive_per_block = _Addresses_Add_offset(
171      local_table,
172      local_table_size
173    );
174
175    /*
176     *  Take the block count down. Saves all the (block_count - 1)
177     *  in the copies.
178     */
179    block_count--;
180
181    if ( information->maximum > 0 ) {
182      /*
183       *  Copy each section of the table over. This has to be performed as
184       *  separate parts as size of each block has changed.
185       */
186      memcpy(
187        object_blocks,
188        information->object_blocks,
189        block_count * sizeof( *object_blocks )
190      );
191      memcpy(
192        inactive_per_block,
193        information->inactive_per_block,
194        block_count * sizeof( *inactive_per_block )
195      );
196      memcpy(
197        local_table,
198        information->local_table,
199        information->maximum * sizeof( *local_table )
200      );
201    }
202
203    /*
204     *  Initialise the new entries in the table.
205     */
206    for ( index = index_base ; index < index_end ; ++index ) {
207      local_table[ index ] = NULL;
208    }
209
210    /* FIXME: https://devel.rtems.org/ticket/2280 */
211    _ISR_lock_ISR_disable( &lock_context );
212
213    old_tables = information->object_blocks;
214
215    information->object_blocks = object_blocks;
216    information->inactive_per_block = inactive_per_block;
217    information->local_table = local_table;
218    information->maximum = (Objects_Maximum) maximum;
219    information->maximum_id = _Objects_Build_id(
220      information->the_api,
221      information->the_class,
222      _Objects_Local_node,
223      information->maximum
224    );
225
226    _ISR_lock_ISR_enable( &lock_context );
227
228    _Workspace_Free( old_tables );
229
230    block_count++;
231  }
232
233  /*
234   *  Assign the new object block to the object block table.
235   */
236  information->object_blocks[ block ] = new_object_block;
237  information->inactive_per_block[ block ] = information->objects_per_block;
238  information->inactive += information->objects_per_block;
239
240  /*
241   *  Append to inactive chain.
242   */
243  the_object = new_object_block;
244  for ( index = index_base ; index < index_end ; ++index ) {
245    the_object->id = _Objects_Build_id(
246      information->the_api,
247      information->the_class,
248      _Objects_Local_node,
249      index + OBJECTS_INDEX_MINIMUM
250    );
251
252    _Chain_Initialize_node( &the_object->Node );
253    _Chain_Append_unprotected( &information->Inactive, &the_object->Node );
254
255    the_object = _Addresses_Add_offset( the_object, information->object_size );
256  }
257}
Note: See TracBrowser for help on using the repository browser.