source: rtems/cpukit/score/src/objectextendinformation.c @ e6f7f81

4.115
Last change on this file since e6f7f81 was 6e93dc4a, checked in by Sebastian Huber <sebastian.huber@…>, on 07/22/13 at 08:49:19

score: Create chain implementation header

Move implementation specific parts of chain.h and chain.inl into new
header file chainimpl.h. The chain.h contains now only the application
visible API.

  • Property mode set to 100644
File size: 7.7 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.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/system.h>
22#include <rtems/score/address.h>
23#include <rtems/score/chainimpl.h>
24#include <rtems/score/object.h>
25#if defined(RTEMS_MULTIPROCESSING)
26#include <rtems/score/objectmp.h>
27#endif
28#include <rtems/score/thread.h>
29#include <rtems/score/wkspace.h>
30#include <rtems/score/sysstate.h>
31#include <rtems/score/isr.h>
32
33#include <string.h>  /* for memcpy() */
34
35/*
36 *  _Objects_Extend_information
37 *
38 *  This routine extends all object information related data structures.
39 *
40 *  Input parameters:
41 *    information     - object information table
42 *
43 *  Output parameters:  NONE
44 */
45
46void _Objects_Extend_information(
47  Objects_Information *information
48)
49{
50  Objects_Control  *the_object;
51  Chain_Control     Inactive;
52  uint32_t          block_count;
53  uint32_t          block;
54  uint32_t          index_base;
55  uint32_t          minimum_index;
56  uint32_t          index;
57  uint32_t          maximum;
58  size_t            block_size;
59  void             *new_object_block;
60  bool              do_extend;
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  minimum_index = _Objects_Get_index( information->minimum_id );
68  index_base    = minimum_index;
69  block         = 0;
70
71  /* if ( information->maximum < minimum_index ) */
72  if ( information->object_blocks == NULL )
73    block_count = 0;
74  else {
75    block_count = information->maximum / information->allocation_size;
76
77    for ( ; block < block_count; block++ ) {
78      if ( information->object_blocks[ block ] == NULL ) {
79        do_extend = false;
80        break;
81      } else
82        index_base += information->allocation_size;
83    }
84  }
85
86  maximum = (uint32_t) information->maximum + information->allocation_size;
87
88  /*
89   *  We need to limit the number of objects to the maximum number
90   *  representable in the index portion of the object Id.  In the
91   *  case of 16-bit Ids, this is only 256 object instances.
92   */
93  if ( maximum > OBJECTS_ID_FINAL_INDEX ) {
94    return;
95  }
96
97  /*
98   * Allocate the name table, and the objects and if it fails either return or
99   * generate a fatal error depending on auto-extending being active.
100   */
101  block_size = information->allocation_size * information->size;
102  if ( information->auto_extend ) {
103    new_object_block = _Workspace_Allocate( block_size );
104    if ( !new_object_block )
105      return;
106  } else {
107    new_object_block = _Workspace_Allocate_or_fatal_error( block_size );
108  }
109
110  /*
111   *  Do we need to grow the tables?
112   */
113  if ( do_extend ) {
114    ISR_Level         level;
115    void            **object_blocks;
116    uint32_t         *inactive_per_block;
117    Objects_Control **local_table;
118    void             *old_tables;
119    size_t            block_size;
120    uintptr_t         object_blocks_size;
121    uintptr_t         inactive_per_block_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     *      void            *objects[block_count];
133     *      uint32_t         inactive_count[block_count];
134     *      Objects_Control *local_table[maximum];
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. The tables are:
147     *      1. object_blocks        : void*
148     *      2. inactive_per_blocks : uint32_t
149     *      3. local_table         : Objects_Name*
150     */
151    object_blocks_size = (uintptr_t)_Addresses_Align_up(
152        (void*)(block_count * sizeof(void*)),
153        CPU_ALIGNMENT
154    );
155    inactive_per_block_size =
156        (uintptr_t)_Addresses_Align_up(
157            (void*)(block_count * sizeof(uint32_t)),
158            CPU_ALIGNMENT
159        );
160    block_size = object_blocks_size + inactive_per_block_size +
161        ((maximum + minimum_index) * sizeof(Objects_Control *));
162    if ( information->auto_extend ) {
163      object_blocks = _Workspace_Allocate( block_size );
164      if ( !object_blocks ) {
165        _Workspace_Free( new_object_block );
166        return;
167      }
168    } else {
169      object_blocks = _Workspace_Allocate_or_fatal_error( block_size );
170    }
171
172    /*
173     *  Break the block into the various sections.
174     */
175    inactive_per_block = (uint32_t *) _Addresses_Add_offset(
176        object_blocks,
177        object_blocks_size
178    );
179    local_table = (Objects_Control **) _Addresses_Add_offset(
180        inactive_per_block,
181        inactive_per_block_size
182    );
183
184    /*
185     *  Take the block count down. Saves all the (block_count - 1)
186     *  in the copies.
187     */
188    block_count--;
189
190    if ( information->maximum > minimum_index ) {
191
192      /*
193       *  Copy each section of the table over. This has to be performed as
194       *  separate parts as size of each block has changed.
195       */
196
197      memcpy( object_blocks,
198              information->object_blocks,
199              block_count * sizeof(void*) );
200      memcpy( inactive_per_block,
201              information->inactive_per_block,
202              block_count * sizeof(uint32_t) );
203      memcpy( local_table,
204              information->local_table,
205              (information->maximum + minimum_index) * sizeof(Objects_Control *) );
206    } else {
207
208      /*
209       *  Deal with the special case of the 0 to minimum_index
210       */
211      for ( index = 0; index < minimum_index; index++ ) {
212        local_table[ index ] = NULL;
213      }
214    }
215
216    /*
217     *  Initialise the new entries in the table.
218     */
219    object_blocks[block_count] = NULL;
220    inactive_per_block[block_count] = 0;
221
222    for ( index=index_base ;
223          index < ( information->allocation_size + index_base );
224          index++ ) {
225      local_table[ index ] = NULL;
226    }
227
228    _ISR_Disable( level );
229
230    old_tables = information->object_blocks;
231
232    information->object_blocks = object_blocks;
233    information->inactive_per_block = inactive_per_block;
234    information->local_table = local_table;
235    information->maximum = (Objects_Maximum) maximum;
236    information->maximum_id = _Objects_Build_id(
237        information->the_api,
238        information->the_class,
239        _Objects_Local_node,
240        information->maximum
241      );
242
243    _ISR_Enable( level );
244
245    _Workspace_Free( old_tables );
246
247    block_count++;
248  }
249
250  /*
251   *  Assign the new object block to the object block table.
252   */
253  information->object_blocks[ block ] = new_object_block;
254
255  /*
256   *  Initialize objects .. add to a local chain first.
257   */
258  _Chain_Initialize(
259    &Inactive,
260    information->object_blocks[ block ],
261    information->allocation_size,
262    information->size
263  );
264
265  /*
266   *  Move from the local chain, initialise, then append to the inactive chain
267   */
268  index = index_base;
269
270  while ((the_object = (Objects_Control *) _Chain_Get( &Inactive )) != NULL ) {
271
272    the_object->id = _Objects_Build_id(
273        information->the_api,
274        information->the_class,
275        _Objects_Local_node,
276        index
277      );
278
279    _Chain_Append( &information->Inactive, &the_object->Node );
280
281    index++;
282  }
283
284  information->inactive_per_block[ block ] = information->allocation_size;
285  information->inactive =
286    (Objects_Maximum)(information->inactive + information->allocation_size);
287}
Note: See TracBrowser for help on using the repository browser.