source: rtems/cpukit/score/src/objectextendinformation.c @ 0daa8ab

5
Last change on this file since 0daa8ab was 059529e, checked in by Sebastian Huber <sebastian.huber@…>, on 07/21/16 at 08:15:02

score: Add debug support to chains

This helps to detect

  • double insert, append, prepend errors, and
  • get from empty chain errors.
  • Property mode set to 100644
File size: 7.6 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          minimum_index;
52  uint32_t          index;
53  uint32_t          maximum;
54  size_t            block_size;
55  void             *new_object_block;
56  bool              do_extend;
57
58  _Assert(
59    _Debug_Is_owner_of_allocator()
60      || !_System_state_Is_up( _System_state_Get() )
61  );
62
63  /*
64   *  Search for a free block of indexes. If we do NOT need to allocate or
65   *  extend the block table, then we will change do_extend.
66   */
67  do_extend     = true;
68  minimum_index = _Objects_Get_index( information->minimum_id );
69  index_base    = minimum_index;
70  block         = 0;
71
72  /* if ( information->maximum < minimum_index ) */
73  if ( information->object_blocks == NULL )
74    block_count = 0;
75  else {
76    block_count = information->maximum / information->allocation_size;
77
78    for ( ; block < block_count; block++ ) {
79      if ( information->object_blocks[ block ] == NULL ) {
80        do_extend = false;
81        break;
82      } else
83        index_base += information->allocation_size;
84    }
85  }
86  index_end = index_base + information->allocation_size;
87
88  maximum = (uint32_t) information->maximum + information->allocation_size;
89
90  /*
91   *  We need to limit the number of objects to the maximum number
92   *  representable in the index portion of the object Id.  In the
93   *  case of 16-bit Ids, this is only 256 object instances.
94   */
95  if ( maximum > OBJECTS_ID_FINAL_INDEX ) {
96    return;
97  }
98
99  /*
100   * Allocate the name table, and the objects and if it fails either return or
101   * generate a fatal error depending on auto-extending being active.
102   */
103  block_size = information->allocation_size * information->size;
104  if ( information->auto_extend ) {
105    new_object_block = _Workspace_Allocate( block_size );
106    if ( !new_object_block )
107      return;
108  } else {
109    new_object_block = _Workspace_Allocate_or_fatal_error( block_size );
110  }
111
112  /*
113   *  Do we need to grow the tables?
114   */
115  if ( do_extend ) {
116    ISR_lock_Context  lock_context;
117    void            **object_blocks;
118    uint32_t         *inactive_per_block;
119    Objects_Control **local_table;
120    void             *old_tables;
121    size_t            block_size;
122    uintptr_t         object_blocks_size;
123    uintptr_t         inactive_per_block_size;
124
125    /*
126     *  Growing the tables means allocating a new area, doing a copy and
127     *  updating the information table.
128     *
129     *  If the maximum is minimum we do not have a table to copy. First
130     *  time through.
131     *
132     *  The allocation has :
133     *
134     *      void            *objects[block_count];
135     *      uint32_t         inactive_count[block_count];
136     *      Objects_Control *local_table[maximum];
137     *
138     *  This is the order in memory. Watch changing the order. See the memcpy
139     *  below.
140     */
141
142    /*
143     *  Up the block count and maximum
144     */
145    block_count++;
146
147    /*
148     *  Allocate the tables and break it up. The tables are:
149     *      1. object_blocks        : void*
150     *      2. inactive_per_blocks : uint32_t
151     *      3. local_table         : Objects_Name*
152     */
153    object_blocks_size = (uintptr_t)_Addresses_Align_up(
154        (void*)(block_count * sizeof(void*)),
155        CPU_ALIGNMENT
156    );
157    inactive_per_block_size =
158        (uintptr_t)_Addresses_Align_up(
159            (void*)(block_count * sizeof(uint32_t)),
160            CPU_ALIGNMENT
161        );
162    block_size = object_blocks_size + inactive_per_block_size +
163        ((maximum + minimum_index) * sizeof(Objects_Control *));
164    if ( information->auto_extend ) {
165      object_blocks = _Workspace_Allocate( block_size );
166      if ( !object_blocks ) {
167        _Workspace_Free( new_object_block );
168        return;
169      }
170    } else {
171      object_blocks = _Workspace_Allocate_or_fatal_error( block_size );
172    }
173
174    /*
175     *  Break the block into the various sections.
176     */
177    inactive_per_block = (uint32_t *) _Addresses_Add_offset(
178        object_blocks,
179        object_blocks_size
180    );
181    local_table = (Objects_Control **) _Addresses_Add_offset(
182        inactive_per_block,
183        inactive_per_block_size
184    );
185
186    /*
187     *  Take the block count down. Saves all the (block_count - 1)
188     *  in the copies.
189     */
190    block_count--;
191
192    if ( information->maximum > minimum_index ) {
193
194      /*
195       *  Copy each section of the table over. This has to be performed as
196       *  separate parts as size of each block has changed.
197       */
198
199      memcpy( object_blocks,
200              information->object_blocks,
201              block_count * sizeof(void*) );
202      memcpy( inactive_per_block,
203              information->inactive_per_block,
204              block_count * sizeof(uint32_t) );
205      memcpy( local_table,
206              information->local_table,
207              (information->maximum + minimum_index) * sizeof(Objects_Control *) );
208    } else {
209
210      /*
211       *  Deal with the special case of the 0 to minimum_index
212       */
213      for ( index = 0; index < minimum_index; index++ ) {
214        local_table[ index ] = NULL;
215      }
216    }
217
218    /*
219     *  Initialise the new entries in the table.
220     */
221    object_blocks[block_count] = NULL;
222    inactive_per_block[block_count] = 0;
223
224    for ( index = index_base ; index < index_end ; ++index ) {
225      local_table[ index ] = NULL;
226    }
227
228    /* FIXME: https://devel.rtems.org/ticket/2280 */
229    _ISR_lock_ISR_disable( &lock_context );
230
231    old_tables = information->object_blocks;
232
233    information->object_blocks = object_blocks;
234    information->inactive_per_block = inactive_per_block;
235    information->local_table = local_table;
236    information->maximum = (Objects_Maximum) maximum;
237    information->maximum_id = _Objects_Build_id(
238        information->the_api,
239        information->the_class,
240        _Objects_Local_node,
241        information->maximum
242      );
243
244    _ISR_lock_ISR_enable( &lock_context );
245
246    _Workspace_Free( old_tables );
247
248    block_count++;
249  }
250
251  /*
252   *  Assign the new object block to the object block table.
253   */
254  information->object_blocks[ block ] = new_object_block;
255
256  /*
257   *  Append to inactive chain.
258   */
259  the_object = information->object_blocks[ block ];
260  for ( index = index_base ; index < index_end ; ++index ) {
261    the_object->id = _Objects_Build_id(
262      information->the_api,
263      information->the_class,
264      _Objects_Local_node,
265      index
266    );
267
268    _Chain_Initialize_node( &the_object->Node );
269    _Chain_Append_unprotected( &information->Inactive, &the_object->Node );
270
271    the_object = (Objects_Control *)
272      ( (char *) the_object + information->size );
273  }
274
275  information->inactive_per_block[ block ] = information->allocation_size;
276  information->inactive =
277    (Objects_Maximum)(information->inactive + information->allocation_size);
278}
Note: See TracBrowser for help on using the repository browser.