source: rtems/cpukit/rtems/src/region.c @ 88d594a

4.104.114.84.95
Last change on this file since 88d594a was ac7d5ef0, checked in by Joel Sherrill <joel.sherrill@…>, on 05/11/95 at 17:39:37

Initial revision

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