source: rtems/cpukit/rtems/src/region.c @ 3235ad9

4.104.114.84.95
Last change on this file since 3235ad9 was 3235ad9, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 23, 1995 at 7:30:23 PM

Support for variable length names added to Object Handler. This supports
both fixed length "raw" names and strings from the API's point of view.

Both inline and macro implementations were tested.

  • Property mode set to 100644
File size: 11.8 KB
Line 
1/*
2 *  Region Manager
3 *
4 *
5 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
6 *  On-Line Applications Research Corporation (OAR).
7 *  All rights assigned to U.S. Government, 1994.
8 *
9 *  This material may be reproduced by or for the U.S. Government pursuant
10 *  to the copyright license under the clause at DFARS 252.227-7013.  This
11 *  notice must appear in all copies of this file and its derivatives.
12 *
13 *  $Id$
14 */
15
16#include <rtems/system.h>
17#include <rtems/support.h>
18#include <rtems/config.h>
19#include <rtems/object.h>
20#include <rtems/options.h>
21#include <rtems/region.h>
22#include <rtems/states.h>
23#include <rtems/thread.h>
24
25/*PAGE
26 *
27 *  _Region_Manager_initialization
28 *
29 *  This routine initializes all region manager related data structures.
30 *
31 *  Input parameters:
32 *    maximum_regions - number of regions to initialize
33 *
34 *  Output parameters:  NONE
35 */
36
37void _Region_Manager_initialization(
38  unsigned32 maximum_regions
39)
40{
41  _Objects_Initialize_information(
42    &_Region_Information,
43    OBJECTS_RTEMS_REGIONS,
44    FALSE,
45    maximum_regions,
46    sizeof( Region_Control ),
47    FALSE,
48    RTEMS_MAXIMUM_NAME_LENGTH
49  );
50}
51
52/*PAGE
53 *
54 *  rtems_region_create
55 *
56 *  This directive creates a region of physical contiguous memory area
57 *  from which variable sized segments can be allocated.
58 *
59 *  Input parameters:
60 *    name             - user defined region name
61 *    starting_address - physical start address of region
62 *    length           - physical length in bytes
63 *    page_size        - page size in bytes
64 *    attribute_set    - region attributes
65 *    id               - address of region id to set
66 *
67 *  Output parameters:
68 *    id       - region id
69 *    RTEMS_SUCCESSFUL - if successful
70 *    error code - if unsuccessful
71 */
72
73rtems_status_code rtems_region_create(
74  rtems_name          name,
75  void               *starting_address,
76  unsigned32          length,
77  unsigned32          page_size,
78  rtems_attribute  attribute_set,
79  Objects_Id         *id
80)
81{
82  Region_Control *the_region;
83
84  if ( !rtems_is_name_valid( name ) )
85    return ( RTEMS_INVALID_NAME );
86
87  if ( !_Addresses_Is_aligned( starting_address ) )
88    return( RTEMS_INVALID_ADDRESS );
89
90  _Thread_Disable_dispatch();             /* to prevent deletion */
91
92  the_region = _Region_Allocate();
93
94  if ( !the_region ) {
95    _Thread_Enable_dispatch();
96    return( RTEMS_TOO_MANY );
97  }
98
99  the_region->maximum_segment_size =
100    _Heap_Initialize(&the_region->Memory, starting_address, length, page_size);
101
102  if ( !the_region->maximum_segment_size ) {
103    _Region_Free( the_region );
104    _Thread_Enable_dispatch();
105    return( RTEMS_INVALID_SIZE );
106  }
107
108  the_region->starting_address      = starting_address;
109  the_region->length                = length;
110  the_region->page_size             = page_size;
111  the_region->attribute_set         = attribute_set;
112  the_region->number_of_used_blocks = 0;
113
114  _Thread_queue_Initialize(
115     &the_region->Wait_queue, attribute_set, STATES_WAITING_FOR_SEGMENT );
116
117  _Objects_Open( &_Region_Information, &the_region->Object, &name );
118
119  *id = the_region->Object.id;
120  _Thread_Enable_dispatch();
121  return( RTEMS_SUCCESSFUL );
122}
123
124/*PAGE
125 *
126 *  rtems_region_ident
127 *
128 *  This directive returns the system ID associated with
129 *  the region name.
130 *
131 *  Input parameters:
132 *    name - user defined region name
133 *    id   - pointer to region id
134 *
135 *  Output parameters:
136 *    *id      - region id
137 *    RTEMS_SUCCESSFUL - if successful
138 *    error code - if unsuccessful
139 */
140
141rtems_status_code rtems_region_ident(
142  rtems_name    name,
143  Objects_Id   *id
144)
145{
146  return _Objects_Name_to_id(
147      &_Region_Information,
148      &name,
149      RTEMS_SEARCH_LOCAL_NODE,
150      id
151    );
152}
153
154/*PAGE
155 *
156 *  rtems_region_delete
157 *
158 *  This directive allows a thread to delete a region specified by
159 *  the region identifier, provided that none of its segments are
160 *  still allocated.
161 *
162 *  Input parameters:
163 *    id - region id
164 *
165 *  Output parameters:
166 *    RTEMS_SUCCESSFUL - if successful
167 *    error code - if unsuccessful
168 */
169
170rtems_status_code rtems_region_delete(
171  Objects_Id id
172)
173{
174  register Region_Control *the_region;
175  Objects_Locations               location;
176
177  the_region = _Region_Get( id, &location );
178  switch ( location ) {
179    case OBJECTS_ERROR:
180      return( RTEMS_INVALID_ID );
181    case OBJECTS_REMOTE:        /* this error cannot be returned */
182      return( RTEMS_INTERNAL_ERROR );
183    case OBJECTS_LOCAL:
184      _Region_Debug_Walk( the_region, 5 );
185      if ( the_region->number_of_used_blocks == 0 ) {
186        _Objects_Close( &_Region_Information, &the_region->Object );
187        _Region_Free( the_region );
188        _Thread_Enable_dispatch();
189        return( RTEMS_SUCCESSFUL );
190      }
191      _Thread_Enable_dispatch();
192      return( RTEMS_RESOURCE_IN_USE );
193  }
194
195  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
196}
197
198/*PAGE
199 *
200 *  rtems_region_extend
201 *
202 *  This directive attempts to grow a region of physical contiguous memory area
203 *  from which variable sized segments can be allocated.
204 *
205 *  Input parameters:
206 *    id         - id of region to grow
207 *    start      - starting address of memory area for extension
208 *    length     - physical length in bytes to grow the region
209 *
210 *  Output parameters:
211 *    RTEMS_SUCCESSFUL - if successful
212 *    error code       - if unsuccessful
213 */
214
215rtems_status_code rtems_region_extend(
216  Objects_Id          id,
217  void               *starting_address,
218  unsigned32          length
219)
220{
221  Region_Control     *the_region;
222  Objects_Locations   location;
223  unsigned32          amount_extended;
224  Heap_Extend_status  heap_status;
225  rtems_status_code   status;
226
227  status = RTEMS_SUCCESSFUL;
228
229  the_region = _Region_Get( id, &location );
230  switch ( location ) {
231    case OBJECTS_ERROR:
232      return( RTEMS_INVALID_ID );
233    case OBJECTS_REMOTE:        /* this error cannot be returned */
234      return( RTEMS_INTERNAL_ERROR );
235    case OBJECTS_LOCAL:
236
237      heap_status = _Heap_Extend(
238        &the_region->Memory,
239        starting_address,
240        length,
241        &amount_extended
242      );
243
244      switch ( heap_status ) {
245        case HEAP_EXTEND_SUCCESSFUL:
246          the_region->length                += amount_extended;
247          the_region->maximum_segment_size  += amount_extended;
248          break;
249        case HEAP_EXTEND_ERROR:
250          status = RTEMS_INVALID_ADDRESS;
251          break;
252        case HEAP_EXTEND_NOT_IMPLEMENTED:
253          status = RTEMS_NOT_IMPLEMENTED;
254          break;
255      }
256      _Thread_Enable_dispatch();
257      return( status );
258  }
259
260  return( RTEMS_INTERNAL_ERROR );
261}
262
263/*PAGE
264 *
265 *  rtems_region_get_segment
266 *
267 *  This directive will obtain a segment from the given region.
268 *
269 *  Input parameters:
270 *    id         - region id
271 *    size       - segment size in bytes
272 *    option_set - wait option
273 *    timeout    - number of ticks to wait (0 means wait forever)
274 *    segment    - pointer to segment address
275 *
276 *  Output parameters:
277 *    segment    - pointer to segment address filled in
278 *    RTEMS_SUCCESSFUL - if successful
279 *    error code - if unsuccessful
280 */
281
282rtems_status_code rtems_region_get_segment(
283  Objects_Id         id,
284  unsigned32         size,
285  rtems_option    option_set,
286  rtems_interval  timeout,
287  void              **segment
288)
289{
290  register Region_Control *the_region;
291  Objects_Locations        location;
292  Thread_Control          *executing;
293  void                    *the_segment;
294
295  if ( size == 0 )
296    return( RTEMS_INVALID_SIZE );
297
298  executing  = _Thread_Executing;
299  the_region = _Region_Get( id, &location );
300  switch ( location ) {
301    case OBJECTS_ERROR:
302      return( RTEMS_INVALID_ID );
303    case OBJECTS_REMOTE:        /* this error cannot be returned */
304      return( RTEMS_INTERNAL_ERROR );
305    case OBJECTS_LOCAL:
306      if ( size > the_region->maximum_segment_size ) {
307        _Thread_Enable_dispatch();
308        return( RTEMS_INVALID_SIZE );
309      }
310
311      _Region_Debug_Walk( the_region, 1 );
312
313      the_segment = _Region_Allocate_segment( the_region, size );
314
315      _Region_Debug_Walk( the_region, 2 );
316
317      if ( the_segment ) {
318        the_region->number_of_used_blocks += 1;
319        _Thread_Enable_dispatch();
320        *segment = the_segment;
321        return( RTEMS_SUCCESSFUL );
322      }
323
324      if ( _Options_Is_no_wait( option_set ) ) {
325        _Thread_Enable_dispatch();
326        return( RTEMS_UNSATISFIED );
327      }
328
329      executing->Wait.queue              = &the_region->Wait_queue;
330      executing->Wait.id                 = id;
331      executing->Wait.Extra.segment_size = size;
332      executing->Wait.return_argument    = (unsigned32 *) segment;
333
334      the_region->Wait_queue.sync = TRUE;
335
336      _Thread_queue_Enqueue( &the_region->Wait_queue, timeout );
337
338      _Thread_Enable_dispatch();
339      return( executing->Wait.return_code );
340  }
341
342  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
343}
344/*PAGE
345 *
346 *  rtems_region_get_segment_size
347 *
348 *  This directive will return the size of the segment indicated
349 *
350 *  Input parameters:
351 *    id         - region id
352 *    segment    - segment address
353 *    size       - pointer to segment size in bytes
354 *
355 *  Output parameters:
356 *    size       - segment size in bytes filled in
357 *    RTEMS_SUCCESSFUL - if successful
358 *    error code - if unsuccessful
359 */
360
361rtems_status_code rtems_region_get_segment_size(
362  Objects_Id         id,
363  void              *segment,
364  unsigned32        *size
365)
366{
367  register Region_Control *the_region;
368  Objects_Locations        location;
369  Thread_Control          *executing;
370
371  executing  = _Thread_Executing;
372  the_region = _Region_Get( id, &location );
373  switch ( location ) {
374    case OBJECTS_ERROR:
375      return( RTEMS_INVALID_ID );
376    case OBJECTS_REMOTE:        /* this error cannot be returned */
377      return( RTEMS_INTERNAL_ERROR );
378    case OBJECTS_LOCAL:
379
380      if ( _Heap_Size_of_user_area( &the_region->Memory, segment, size ) ) {
381        _Thread_Enable_dispatch();
382        return( RTEMS_SUCCESSFUL );
383      }
384      _Thread_Enable_dispatch();
385      return( RTEMS_INVALID_ADDRESS );
386  }
387
388  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
389}
390
391/*PAGE
392 *
393 *  rtems_region_return_segment
394 *
395 *  This directive will return a segment to its region.
396 *
397 *  Input parameters:
398 *    id      - region id
399 *    segment - pointer to segment address
400 *
401 *  Output parameters:
402 *    RTEMS_SUCCESSFUL - if successful
403 *    error code        - if unsuccessful
404 */
405
406rtems_status_code rtems_region_return_segment(
407  Objects_Id  id,
408  void       *segment
409)
410{
411  register Region_Control *the_region;
412  Thread_Control          *the_thread;
413  Objects_Locations        location;
414  void                   **the_segment;
415  int                      status;
416
417  the_region = _Region_Get( id, &location );
418  switch ( location ) {
419    case OBJECTS_ERROR:
420      return( RTEMS_INVALID_ID );
421    case OBJECTS_REMOTE:        /* this error cannot be returned */
422      return( RTEMS_INTERNAL_ERROR );
423    case OBJECTS_LOCAL:
424
425      _Region_Debug_Walk( the_region, 3 );
426
427      status = _Region_Free_segment( the_region, segment );
428
429      _Region_Debug_Walk( the_region, 4 );
430
431      if ( !status ) {
432        _Thread_Enable_dispatch();
433        return( RTEMS_INVALID_ADDRESS );
434      }
435
436      the_region->number_of_used_blocks -= 1;
437      for ( ; ; ) {
438        the_thread = _Thread_queue_First( &the_region->Wait_queue );
439
440        if ( the_thread == NULL )
441           break;
442
443        the_segment = _Region_Allocate_segment(
444                        the_region, the_thread->Wait.Extra.segment_size );
445
446        if ( the_segment == NULL )
447           break;
448
449        *(void **)the_thread->Wait.return_argument = the_segment;
450        the_region->number_of_used_blocks += 1;
451        _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
452        the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
453      }
454
455      _Thread_Enable_dispatch();
456      return( RTEMS_SUCCESSFUL );
457  }
458
459  return( RTEMS_INTERNAL_ERROR );   /* unreached - only to remove warnings */
460}
Note: See TracBrowser for help on using the repository browser.