source: rtems/cpukit/rtems/src/region.c @ 7f6a24ab

4.104.114.84.95
Last change on this file since 7f6a24ab was 7f6a24ab, checked in by Joel Sherrill <joel.sherrill@…>, on 08/28/95 at 15:30:29

Added unused priority ceiling parameter to rtems_semaphore_create.

Rearranged code to created thread handler routines to initialize,
start, restart, and "close/delete" a thread.

Made internal threads their own object class. This now uses the
thread support routines for starting and initializing a thread.

Insured deleted tasks are freed to the Inactive pool associated with the
correct Information block.

Added an RTEMS API specific data area to the thread control block.

Beginnings of removing the word "rtems" from the core.

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