source: rtems/cpukit/rtems/src/region.c @ 3a4ae6c

4.104.114.84.95
Last change on this file since 3a4ae6c was 3a4ae6c, checked in by Joel Sherrill <joel.sherrill@…>, on 09/11/95 at 19:35:39

The word "RTEMS" almost completely removed from the core.

Configuration Table Template file added and all tests
modified to use this. All gvar.h and conftbl.h files
removed from test directories.

Configuration parameter maximum_devices added.

Core semaphore and mutex handlers added and RTEMS API Semaphore
Manager updated to reflect this.

Initialization sequence changed to invoke API specific initialization
routines. Initialization tasks table now owned by RTEMS Tasks Manager.

Added user extension for post-switch.

Utilized user extensions to implement API specific functionality
like signal dispatching.

Added extensions to the System Initialization Thread so that an
API can register a function to be invoked while the system
is being initialized. These are largely equivalent to the
pre-driver and post-driver hooks.

Added the Modules file oar-go32_p5, modified oar-go32, and modified
the file make/custom/go32.cfg to look at an environment varable which
determines what CPU model is being used.

All BSPs updated to reflect named devices and clock driver's IOCTL
used by the Shared Memory Driver. Also merged clock isr into
main file and removed ckisr.c where possible.

Updated spsize to reflect new and moved variables.

Makefiles for the executive source and include files updated to show
break down of files into Core, RTEMS API, and Neither.

Header and inline files installed into subdirectory based on whether
logically in the Core or a part of the RTEMS API.

  • Property mode set to 100644
File size: 12.2 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/core/object.h>
20#include <rtems/rtems/options.h>
21#include <rtems/rtems/region.h>
22#include <rtems/core/states.h>
23#include <rtems/core/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  if ( size == 0 )
318    return RTEMS_INVALID_SIZE;
319
320  executing  = _Thread_Executing;
321  the_region = _Region_Get( id, &location );
322  switch ( location ) {
323    case OBJECTS_ERROR:
324      return RTEMS_INVALID_ID;
325    case OBJECTS_REMOTE:        /* this error cannot be returned */
326      return RTEMS_INTERNAL_ERROR;
327    case OBJECTS_LOCAL:
328      if ( size > the_region->maximum_segment_size ) {
329        _Thread_Enable_dispatch();
330        return RTEMS_INVALID_SIZE;
331      }
332
333      _Region_Debug_Walk( the_region, 1 );
334
335      the_segment = _Region_Allocate_segment( the_region, size );
336
337      _Region_Debug_Walk( the_region, 2 );
338
339      if ( the_segment ) {
340        the_region->number_of_used_blocks += 1;
341        _Thread_Enable_dispatch();
342        *segment = the_segment;
343        return RTEMS_SUCCESSFUL;
344      }
345
346      if ( _Options_Is_no_wait( option_set ) ) {
347        _Thread_Enable_dispatch();
348        return RTEMS_UNSATISFIED;
349      }
350
351      executing->Wait.queue           = &the_region->Wait_queue;
352      executing->Wait.id              = id;
353      executing->Wait.count           = size;
354      executing->Wait.return_argument = (unsigned32 *) segment;
355
356      the_region->Wait_queue.sync = TRUE;
357
358      _Thread_queue_Enqueue( &the_region->Wait_queue, timeout );
359
360      _Thread_Enable_dispatch();
361      return( executing->Wait.return_code );
362  }
363
364  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
365}
366/*PAGE
367 *
368 *  rtems_region_get_segment_size
369 *
370 *  This directive will return the size of the segment indicated
371 *
372 *  Input parameters:
373 *    id         - region id
374 *    segment    - segment address
375 *    size       - pointer to segment size in bytes
376 *
377 *  Output parameters:
378 *    size       - segment size in bytes filled in
379 *    RTEMS_SUCCESSFUL - if successful
380 *    error code - if unsuccessful
381 */
382
383rtems_status_code rtems_region_get_segment_size(
384  Objects_Id         id,
385  void              *segment,
386  unsigned32        *size
387)
388{
389  register Region_Control *the_region;
390  Objects_Locations        location;
391  Thread_Control          *executing;
392
393  executing  = _Thread_Executing;
394  the_region = _Region_Get( id, &location );
395  switch ( location ) {
396    case OBJECTS_ERROR:
397      return RTEMS_INVALID_ID;
398    case OBJECTS_REMOTE:        /* this error cannot be returned */
399      return RTEMS_INTERNAL_ERROR;
400    case OBJECTS_LOCAL:
401
402      if ( _Heap_Size_of_user_area( &the_region->Memory, segment, size ) ) {
403        _Thread_Enable_dispatch();
404        return RTEMS_SUCCESSFUL;
405      }
406      _Thread_Enable_dispatch();
407      return RTEMS_INVALID_ADDRESS;
408  }
409
410  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
411}
412
413/*PAGE
414 *
415 *  rtems_region_return_segment
416 *
417 *  This directive will return a segment to its region.
418 *
419 *  Input parameters:
420 *    id      - region id
421 *    segment - pointer to segment address
422 *
423 *  Output parameters:
424 *    RTEMS_SUCCESSFUL - if successful
425 *    error code        - if unsuccessful
426 */
427
428rtems_status_code rtems_region_return_segment(
429  Objects_Id  id,
430  void       *segment
431)
432{
433  register Region_Control *the_region;
434  Thread_Control          *the_thread;
435  Objects_Locations        location;
436  void                   **the_segment;
437  int                      status;
438
439  the_region = _Region_Get( id, &location );
440  switch ( location ) {
441    case OBJECTS_ERROR:
442      return RTEMS_INVALID_ID;
443    case OBJECTS_REMOTE:        /* this error cannot be returned */
444      return RTEMS_INTERNAL_ERROR;
445    case OBJECTS_LOCAL:
446
447      _Region_Debug_Walk( the_region, 3 );
448
449      status = _Region_Free_segment( the_region, segment );
450
451      _Region_Debug_Walk( the_region, 4 );
452
453      if ( !status ) {
454        _Thread_Enable_dispatch();
455        return RTEMS_INVALID_ADDRESS;
456      }
457
458      the_region->number_of_used_blocks -= 1;
459      for ( ; ; ) {
460        the_thread = _Thread_queue_First( &the_region->Wait_queue );
461
462        if ( the_thread == NULL )
463           break;
464
465        the_segment = _Region_Allocate_segment(
466           the_region,
467           the_thread->Wait.count
468        );
469
470        if ( the_segment == NULL )
471           break;
472
473        *(void **)the_thread->Wait.return_argument = the_segment;
474        the_region->number_of_used_blocks += 1;
475        _Thread_queue_Extract( &the_region->Wait_queue, the_thread );
476        the_thread->Wait.return_code = RTEMS_SUCCESSFUL;
477      }
478
479      _Thread_Enable_dispatch();
480      return RTEMS_SUCCESSFUL;
481  }
482
483  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
484}
Note: See TracBrowser for help on using the repository browser.