source: rtems/c/src/exec/rtems/src/region.c @ b1b5a7cb

4.104.114.84.95
Last change on this file since b1b5a7cb was ffe316d, checked in by Joel Sherrill <joel.sherrill@…>, on 12/02/96 at 22:50:33

Suggested changes from Mark Jordan which eliminate warnings and errors
he received using the Microtec C++ compiler. Most of these are
either missing casts from/to (void *), heavy handed use of enumerated
types, or simply assumed conversions. There is at least one actual
bug in an error path in thread.c in which the wrong argument was
passed to _Thread_Stack_Free and was not being caught by gcc.

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