Changeset 7edb9281 in rtems


Ignore:
Timestamp:
Nov 5, 1999, 7:02:03 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
1c55d2e8
Parents:
0fab6dde
Message:

Following comments from Eric Norum <eric@…>, a fairly
substantial upgrade of newlibc.c occurred. Now the user extension
data area is used rather than notepads and as many routines as possible
were split into other files further reducing the minimum footprint
of an RTEMS executable.

Files:
6 added
4 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/libcsupport/src/newlibc.c

    r0fab6dde r7edb9281  
    4141#endif
    4242
     43static int extension_index;
     44
    4345/*
    4446 *  Private routines
    4547 */
    4648
    47 void MY_task_set_note(
    48   rtems_tcb        *tcb,
    49   rtems_unsigned32 notepad,
    50   rtems_unsigned32 note
    51 );
    52 
    53 rtems_unsigned32 MY_task_get_note(
    54   rtems_tcb        *tcb,
    55   rtems_unsigned32  notepad
    56 );
    57 
    58 
    59 #define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
    60 
     49#define set_newlib_extension( _the_thread, _value ) \
     50  (_the_thread)->extensions[ extension_index ] = (_value);
     51
     52#define get_newlib_extension( _the_thread ) \
     53  (_the_thread)->extensions[ extension_index ]
    6154
    6255int              libc_reentrant;        /* do we think we are reentrant? */
     
    7467#include <stdio.h>
    7568
    76 void
    77 libc_wrapup(void)
    78 {
    79     /*
    80      *  In case RTEMS is already down, don't do this.  It could be
    81      *  dangerous.
    82      */
    83 
    84     if (!_System_state_Is_up(_System_state_Get()))
    85        return;
    86 
    87     /*
    88      *  This was already done if the user called exit() directly .
    89 
    90     _wrapup_reent(0);
    91      */
    92     if (_REENT != &libc_global_reent)
    93     {
    94         _wrapup_reent(&libc_global_reent);
     69void libc_wrapup(void)
     70{
     71  /*
     72   *  In case RTEMS is already down, don't do this.  It could be
     73   *  dangerous.
     74   */
     75
     76  if (!_System_state_Is_up(_System_state_Get()))
     77     return;
     78
     79  /*
     80   *  This was already done if the user called exit() directly .
     81  _wrapup_reent(0);
     82   */
     83
     84  if (_REENT != &libc_global_reent) {
     85      _wrapup_reent(&libc_global_reent);
    9586#if 0
    96         /* don't reclaim this one, just in case we do printfs */
    97         /* on our way out to ROM */
    98         _reclaim_reent(&libc_global_reent);
    99 #endif
    100         _REENT = &libc_global_reent;
    101     }
    102    
    103     /*
    104      * Try to drain output buffers.
    105      *
    106      * Should this be changed to do *all* file streams?
    107      *  _fwalk (_REENT, fclose);
    108      */
    109     fclose (stdin);
    110     fclose (stdout);
    111     fclose (stderr);
    112 }
    113 
    114 
    115 rtems_boolean
    116 libc_create_hook(rtems_tcb *current_task,
    117                  rtems_tcb *creating_task)
    118 {
    119     MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
    120     return TRUE;
     87      /*  Don't reclaim this one, just in case we do printfs
     88       *  on the way out to ROM.
     89       */
     90      _reclaim_reent(&libc_global_reent);
     91#endif
     92      _REENT = &libc_global_reent;
     93  }
     94 
     95  /*
     96   * Try to drain output buffers.
     97   *
     98   * Should this be changed to do *all* file streams?
     99   *    _fwalk (_REENT, fclose);
     100   */
     101
     102  fclose (stdin);
     103  fclose (stdout);
     104  fclose (stderr);
     105}
     106
     107
     108rtems_boolean libc_create_hook(
     109  rtems_tcb *current_task,
     110  rtems_tcb *creating_task
     111)
     112{
     113  set_newlib_extension( creating_task, NULL );
     114  return TRUE;
    121115}
    122116
     
    125119 */
    126120
    127 rtems_extension
    128 libc_start_hook(rtems_tcb *current_task,
    129                 rtems_tcb *starting_task)
    130 {
    131     struct _reent *ptr;
    132 
    133     /* NOTE: our malloc is reentrant without a reent ptr since
    134      *  it is based on region manager
    135      */
    136 
    137     ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
    138 
    139     if (!ptr)
    140        rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
     121rtems_extension libc_start_hook(
     122  rtems_tcb *current_task,
     123  rtems_tcb *starting_task
     124)
     125{
     126  struct _reent *ptr;
     127
     128  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
     129   *        it is based on the Classic API Region Manager.
     130   */
     131
     132  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
     133
     134  if (!ptr)
     135     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
    141136 
    142137#ifdef __GNUC__
    143     /* GCC extension: structure constants */
    144     *ptr = (struct _reent) _REENT_INIT((*ptr));
     138  /* GCC extension: structure constants */
     139  *ptr = (struct _reent) _REENT_INIT((*ptr));
    145140#else
    146     /*
    147      *  Warning: THIS IS VERY DEPENDENT ON NEWLIB!!! WRITTEN FOR 1.7.0
    148      */
    149     ptr->_errno=0;
    150     ptr->_stdin=&ptr->__sf[0];
    151     ptr->_stdout=&ptr->__sf[1];
    152     ptr->_stderr=&ptr->__sf[2];
    153     ptr->_scanpoint=0;
    154     ptr->_asctime[0]=0;
    155     ptr->_next=1;
    156     ptr->__sdidinit=0;
    157 #endif
    158 
    159     MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
     141  /*
     142   *  WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
     143   *           Last visual check was against newlib 1.8.2 but last known
     144   *           use was against 1.7.0.  This is basically an exansion of
     145   *           REENT_INIT() in <sys/reent.h>.
     146   *  NOTE:    calloc() takes care of zeroing fields.
     147   */
     148  ptr->_stdin = &ptr->__sf[0];
     149  ptr->_stdout = &ptr->__sf[1];
     150  ptr->_stderr = &ptr->__sf[2];
     151  ptr->_current_locale = "C";
     152  ptr->_new._reent._rand_next = 1;
     153#endif
     154
     155  set_newlib_extension( starting_task, ptr );
    160156}
    161157
     
    165161 
    166162#ifdef NEED_SETVBUF
    167 rtems_extension
    168 libc_begin_hook(rtems_tcb *current_task)
     163rtems_extension libc_begin_hook(rtems_tcb *current_task)
    169164{
    170165  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
     
    172167#endif
    173168
    174 rtems_extension
    175 libc_switch_hook(rtems_tcb *current_task,
    176                  rtems_tcb *heir_task)
    177 {
    178     rtems_unsigned32 impure_value;
    179 
    180     /* XXX We can't use rtems_task_set_note() here since SYSI task has a
    181      * tid of 0, which is treated specially (optimized, actually)
    182      * by rtems_task_set_note
    183      *
    184      * NOTE:  The above comment is no longer true and we need to use
    185      *        the extension data areas added about the same time.
    186      */
    187 
    188     /*
    189      *  Don't touch the outgoing task if it has been deleted.
    190      */
    191 
    192     if ( !_States_Is_transient( current_task->current_state ) ) {
    193       impure_value = (rtems_unsigned32) _REENT;
    194       MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
    195     }
    196 
    197     _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
    198 
     169rtems_extension libc_switch_hook(
     170  rtems_tcb *current_task,
     171  rtems_tcb *heir_task
     172)
     173{
     174  /*
     175   *  Don't touch the outgoing task if it has been deleted.
     176   */
     177
     178  if ( !_States_Is_transient( current_task->current_state ) ) {
     179    set_newlib_extension( current_task, _REENT );
     180  }
     181
     182  _REENT = (struct _reent *) get_newlib_extension( heir_task );
    199183}
    200184
     
    223207 *
    224208 */
    225 rtems_extension
    226 libc_delete_hook(rtems_tcb *current_task,
    227                  rtems_tcb *deleted_task)
    228 {
    229     struct _reent *ptr;
    230 
    231     /*
    232      * The reentrancy structure was allocated by newlib using malloc()
    233      */
    234 
    235     if (current_task == deleted_task)
    236     {
    237       ptr = _REENT;
    238     }
    239     else
    240     {
    241       ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
    242     }
    243 
    244     /* if (ptr) */
    245     if (ptr && ptr != &libc_global_reent)
    246     {
    247       _wrapup_reent(ptr);
    248       _reclaim_reent(ptr);
    249       free(ptr);
    250     }
    251 
    252     MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
    253 
    254     /*
    255      * Require the switch back to another task to install its own
    256      */
    257 
    258     if (current_task == deleted_task)
    259     {
    260       _REENT = 0;
    261     }
     209
     210rtems_extension libc_delete_hook(
     211  rtems_tcb *current_task,
     212  rtems_tcb *deleted_task
     213)
     214{
     215  struct _reent *ptr;
     216
     217  /*
     218   * The reentrancy structure was allocated by newlib using malloc()
     219   */
     220
     221  if (current_task == deleted_task) {
     222    ptr = _REENT;
     223  } else {
     224    ptr = (struct _reent *) get_newlib_extension( deleted_task );
     225  }
     226
     227  /* if (ptr) */
     228  if (ptr && ptr != &libc_global_reent) {
     229    _wrapup_reent(ptr);
     230    _reclaim_reent(ptr);
     231    free(ptr);
     232  }
     233
     234  set_newlib_extension( deleted_task, NULL );
     235
     236  /*
     237   * Require the switch back to another task to install its own
     238   */
     239
     240  if ( current_task == deleted_task ) {
     241    _REENT = 0;
     242  }
    262243}
    263244
     
    295276libc_init(int reentrant)
    296277{
    297     rtems_extensions_table  libc_extension;
    298     rtems_id                extension_id;
    299     rtems_status_code       rc;
    300 
    301     libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
    302     _REENT = &libc_global_reent;
    303 
    304     if (reentrant)
    305     {
    306         memset(&libc_extension, 0, sizeof(libc_extension));
    307 
    308         libc_extension.thread_create  = libc_create_hook;
    309         libc_extension.thread_start   = libc_start_hook;
     278  rtems_extensions_table  libc_extension;
     279  rtems_status_code       rc;
     280  rtems_id                extension_id;
     281
     282  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
     283  _REENT = &libc_global_reent;
     284
     285  if (reentrant) {
     286    memset(&libc_extension, 0, sizeof(libc_extension));
     287
     288    libc_extension.thread_create  = libc_create_hook;
     289    libc_extension.thread_start   = libc_start_hook;
    310290#ifdef NEED_SETVBUF
    311         libc_extension.thread_begin   = libc_begin_hook;
    312 #endif
    313         libc_extension.thread_switch  = libc_switch_hook;
    314         libc_extension.thread_delete  = libc_delete_hook;
    315 
    316         rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
    317                               &libc_extension, &extension_id);
    318         if (rc != RTEMS_SUCCESSFUL)
    319             rtems_fatal_error_occurred( rc );
    320 
    321         libc_reentrant = reentrant;
    322     }
    323 }
    324 
    325 #if 0
    326 /*
    327  *  Routines required by the gnat runtime.
    328  */
    329 
    330 int get_errno()
    331 {
    332   return errno;
    333 }
    334 #endif
     291    libc_extension.thread_begin   = libc_begin_hook;
     292#endif
     293    libc_extension.thread_switch  = libc_switch_hook;
     294    libc_extension.thread_delete  = libc_delete_hook;
     295
     296    rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
     297                          &libc_extension, &extension_id);
     298    if (rc != RTEMS_SUCCESSFUL)
     299      rtems_fatal_error_occurred( rc );
     300
     301    libc_reentrant = reentrant;
     302    extension_index = rtems_get_index( extension_id );
     303  }
     304}
    335305
    336306/*
     
    367337void _exit(int status)
    368338{
    369     /*
    370      *  We need to do the exit processing on the global reentrancy structure.
    371      *  This has already been done on the per task reentrancy structure
    372      *  associated with this task.
    373      */
    374 
    375     libc_wrapup();
    376     rtems_shutdown_executive(status);
     339  /*
     340   *  We need to do the exit processing on the global reentrancy structure.
     341   *  This has already been done on the per task reentrancy structure
     342   *  associated with this task.
     343   */
     344
     345  libc_wrapup();
     346  rtems_shutdown_executive(status);
    377347}
    378348
     
    381351void exit(int status)
    382352{
    383     libc_wrapup();
    384     rtems_shutdown_executive(status);
    385 }
    386 #endif
    387 
    388 
    389 /*
    390  *  These are directly supported (and completely correct) in the posix api.
    391  */
    392 
    393 pid_t __getpid(void)
    394 {
    395   return getpid();
    396 }
    397 
    398 #if !defined(RTEMS_POSIX_API)
    399 pid_t getpid(void)
    400 {
    401   return 0;
    402 }
    403 
    404 pid_t _getpid_r(
    405   struct _reent *ptr
    406 )
    407 {
    408   return getpid();
    409 }
    410 #endif
    411 
    412 #if !defined(RTEMS_POSIX_API)
    413 int kill( pid_t pid, int sig )
    414 {
    415   return 0;
    416 }
    417 
    418 int _kill_r( pid_t pid, int sig )
    419 {
    420   return 0;
    421 }
    422 #endif
    423 
    424 int __kill( pid_t pid, int sig )
    425 {
    426   return 0;
    427 }
    428 
    429 #if !defined(RTEMS_POSIX_API)
    430 unsigned int sleep(
    431   unsigned int seconds
    432 )
    433 {
    434   rtems_status_code status;
    435   rtems_interval    ticks_per_second;
    436   rtems_interval    ticks;
    437  
    438   status = rtems_clock_get(
    439     RTEMS_CLOCK_GET_TICKS_PER_SECOND,
    440     &ticks_per_second
    441   );
    442  
    443   ticks = seconds * ticks_per_second;
    444  
    445   status = rtems_task_wake_after( ticks );
    446  
    447   /*
    448    *  Returns the "unslept" amount of time.  In RTEMS signals are not
    449    *  interruptable, so tasks really sleep all of the requested time.
    450    */
    451  
    452   return 0;
    453 }
    454 #endif
    455 
    456 
    457 /*
    458  *  Newlib Interface Support
    459  *
    460  *  Routines to Access Internal RTEMS Resources without violating
    461  *  kernel visibility.
    462  *
    463  */
    464 
    465 void MY_task_set_note(
    466   Thread_Control *the_thread,
    467   unsigned32      notepad,
    468   unsigned32      note
    469 )
    470 {
    471   RTEMS_API_Control    *api;
    472  
    473   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    474 
    475   if ( api )
    476     api->Notepads[ notepad ] = note;
    477 }
    478 
    479 
    480 unsigned32 MY_task_get_note(
    481   Thread_Control *the_thread,
    482   unsigned32      notepad
    483 )
    484 {
    485   RTEMS_API_Control    *api;
    486  
    487   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    488 
    489   return api->Notepads[ notepad ];
    490 }
    491 
    492 void *MY_CPU_Context_FP_start(
    493   void       *base,
    494   unsigned32  offset
    495 )
    496 {
    497   return _CPU_Context_Fp_start( base, offset );
    498 }
    499 #endif
     353  libc_wrapup();
     354  rtems_shutdown_executive(status);
     355}
     356#endif
     357
     358
     359#endif
  • c/src/lib/libc/Makefile.in

    r0fab6dde r7edb9281  
    4747PASSWORD_GROUP_C_PIECES = getpwent getgrent
    4848
    49 LIBC_GLUE_C_PIECES = __gettod __times truncate access stat lstat pathconf \
    50     newlibc no_libc
     49LIBC_GLUE_C_PIECES = __getpid __gettod __times truncate access stat \
     50    lstat pathconf newlibc no_posix no_libc
    5151
    5252UNIX_LIBC_C_PIECES = unixlibc hosterr
  • c/src/lib/libc/newlibc.c

    r0fab6dde r7edb9281  
    4141#endif
    4242
     43static int extension_index;
     44
    4345/*
    4446 *  Private routines
    4547 */
    4648
    47 void MY_task_set_note(
    48   rtems_tcb        *tcb,
    49   rtems_unsigned32 notepad,
    50   rtems_unsigned32 note
    51 );
    52 
    53 rtems_unsigned32 MY_task_get_note(
    54   rtems_tcb        *tcb,
    55   rtems_unsigned32  notepad
    56 );
    57 
    58 
    59 #define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
    60 
     49#define set_newlib_extension( _the_thread, _value ) \
     50  (_the_thread)->extensions[ extension_index ] = (_value);
     51
     52#define get_newlib_extension( _the_thread ) \
     53  (_the_thread)->extensions[ extension_index ]
    6154
    6255int              libc_reentrant;        /* do we think we are reentrant? */
     
    7467#include <stdio.h>
    7568
    76 void
    77 libc_wrapup(void)
    78 {
    79     /*
    80      *  In case RTEMS is already down, don't do this.  It could be
    81      *  dangerous.
    82      */
    83 
    84     if (!_System_state_Is_up(_System_state_Get()))
    85        return;
    86 
    87     /*
    88      *  This was already done if the user called exit() directly .
    89 
    90     _wrapup_reent(0);
    91      */
    92     if (_REENT != &libc_global_reent)
    93     {
    94         _wrapup_reent(&libc_global_reent);
     69void libc_wrapup(void)
     70{
     71  /*
     72   *  In case RTEMS is already down, don't do this.  It could be
     73   *  dangerous.
     74   */
     75
     76  if (!_System_state_Is_up(_System_state_Get()))
     77     return;
     78
     79  /*
     80   *  This was already done if the user called exit() directly .
     81  _wrapup_reent(0);
     82   */
     83
     84  if (_REENT != &libc_global_reent) {
     85      _wrapup_reent(&libc_global_reent);
    9586#if 0
    96         /* don't reclaim this one, just in case we do printfs */
    97         /* on our way out to ROM */
    98         _reclaim_reent(&libc_global_reent);
    99 #endif
    100         _REENT = &libc_global_reent;
    101     }
    102    
    103     /*
    104      * Try to drain output buffers.
    105      *
    106      * Should this be changed to do *all* file streams?
    107      *  _fwalk (_REENT, fclose);
    108      */
    109     fclose (stdin);
    110     fclose (stdout);
    111     fclose (stderr);
    112 }
    113 
    114 
    115 rtems_boolean
    116 libc_create_hook(rtems_tcb *current_task,
    117                  rtems_tcb *creating_task)
    118 {
    119     MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
    120     return TRUE;
     87      /*  Don't reclaim this one, just in case we do printfs
     88       *  on the way out to ROM.
     89       */
     90      _reclaim_reent(&libc_global_reent);
     91#endif
     92      _REENT = &libc_global_reent;
     93  }
     94 
     95  /*
     96   * Try to drain output buffers.
     97   *
     98   * Should this be changed to do *all* file streams?
     99   *    _fwalk (_REENT, fclose);
     100   */
     101
     102  fclose (stdin);
     103  fclose (stdout);
     104  fclose (stderr);
     105}
     106
     107
     108rtems_boolean libc_create_hook(
     109  rtems_tcb *current_task,
     110  rtems_tcb *creating_task
     111)
     112{
     113  set_newlib_extension( creating_task, NULL );
     114  return TRUE;
    121115}
    122116
     
    125119 */
    126120
    127 rtems_extension
    128 libc_start_hook(rtems_tcb *current_task,
    129                 rtems_tcb *starting_task)
    130 {
    131     struct _reent *ptr;
    132 
    133     /* NOTE: our malloc is reentrant without a reent ptr since
    134      *  it is based on region manager
    135      */
    136 
    137     ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
    138 
    139     if (!ptr)
    140        rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
     121rtems_extension libc_start_hook(
     122  rtems_tcb *current_task,
     123  rtems_tcb *starting_task
     124)
     125{
     126  struct _reent *ptr;
     127
     128  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
     129   *        it is based on the Classic API Region Manager.
     130   */
     131
     132  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
     133
     134  if (!ptr)
     135     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
    141136 
    142137#ifdef __GNUC__
    143     /* GCC extension: structure constants */
    144     *ptr = (struct _reent) _REENT_INIT((*ptr));
     138  /* GCC extension: structure constants */
     139  *ptr = (struct _reent) _REENT_INIT((*ptr));
    145140#else
    146     /*
    147      *  Warning: THIS IS VERY DEPENDENT ON NEWLIB!!! WRITTEN FOR 1.7.0
    148      */
    149     ptr->_errno=0;
    150     ptr->_stdin=&ptr->__sf[0];
    151     ptr->_stdout=&ptr->__sf[1];
    152     ptr->_stderr=&ptr->__sf[2];
    153     ptr->_scanpoint=0;
    154     ptr->_asctime[0]=0;
    155     ptr->_next=1;
    156     ptr->__sdidinit=0;
    157 #endif
    158 
    159     MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
     141  /*
     142   *  WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
     143   *           Last visual check was against newlib 1.8.2 but last known
     144   *           use was against 1.7.0.  This is basically an exansion of
     145   *           REENT_INIT() in <sys/reent.h>.
     146   *  NOTE:    calloc() takes care of zeroing fields.
     147   */
     148  ptr->_stdin = &ptr->__sf[0];
     149  ptr->_stdout = &ptr->__sf[1];
     150  ptr->_stderr = &ptr->__sf[2];
     151  ptr->_current_locale = "C";
     152  ptr->_new._reent._rand_next = 1;
     153#endif
     154
     155  set_newlib_extension( starting_task, ptr );
    160156}
    161157
     
    165161 
    166162#ifdef NEED_SETVBUF
    167 rtems_extension
    168 libc_begin_hook(rtems_tcb *current_task)
     163rtems_extension libc_begin_hook(rtems_tcb *current_task)
    169164{
    170165  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
     
    172167#endif
    173168
    174 rtems_extension
    175 libc_switch_hook(rtems_tcb *current_task,
    176                  rtems_tcb *heir_task)
    177 {
    178     rtems_unsigned32 impure_value;
    179 
    180     /* XXX We can't use rtems_task_set_note() here since SYSI task has a
    181      * tid of 0, which is treated specially (optimized, actually)
    182      * by rtems_task_set_note
    183      *
    184      * NOTE:  The above comment is no longer true and we need to use
    185      *        the extension data areas added about the same time.
    186      */
    187 
    188     /*
    189      *  Don't touch the outgoing task if it has been deleted.
    190      */
    191 
    192     if ( !_States_Is_transient( current_task->current_state ) ) {
    193       impure_value = (rtems_unsigned32) _REENT;
    194       MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
    195     }
    196 
    197     _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
    198 
     169rtems_extension libc_switch_hook(
     170  rtems_tcb *current_task,
     171  rtems_tcb *heir_task
     172)
     173{
     174  /*
     175   *  Don't touch the outgoing task if it has been deleted.
     176   */
     177
     178  if ( !_States_Is_transient( current_task->current_state ) ) {
     179    set_newlib_extension( current_task, _REENT );
     180  }
     181
     182  _REENT = (struct _reent *) get_newlib_extension( heir_task );
    199183}
    200184
     
    223207 *
    224208 */
    225 rtems_extension
    226 libc_delete_hook(rtems_tcb *current_task,
    227                  rtems_tcb *deleted_task)
    228 {
    229     struct _reent *ptr;
    230 
    231     /*
    232      * The reentrancy structure was allocated by newlib using malloc()
    233      */
    234 
    235     if (current_task == deleted_task)
    236     {
    237       ptr = _REENT;
    238     }
    239     else
    240     {
    241       ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
    242     }
    243 
    244     /* if (ptr) */
    245     if (ptr && ptr != &libc_global_reent)
    246     {
    247       _wrapup_reent(ptr);
    248       _reclaim_reent(ptr);
    249       free(ptr);
    250     }
    251 
    252     MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
    253 
    254     /*
    255      * Require the switch back to another task to install its own
    256      */
    257 
    258     if (current_task == deleted_task)
    259     {
    260       _REENT = 0;
    261     }
     209
     210rtems_extension libc_delete_hook(
     211  rtems_tcb *current_task,
     212  rtems_tcb *deleted_task
     213)
     214{
     215  struct _reent *ptr;
     216
     217  /*
     218   * The reentrancy structure was allocated by newlib using malloc()
     219   */
     220
     221  if (current_task == deleted_task) {
     222    ptr = _REENT;
     223  } else {
     224    ptr = (struct _reent *) get_newlib_extension( deleted_task );
     225  }
     226
     227  /* if (ptr) */
     228  if (ptr && ptr != &libc_global_reent) {
     229    _wrapup_reent(ptr);
     230    _reclaim_reent(ptr);
     231    free(ptr);
     232  }
     233
     234  set_newlib_extension( deleted_task, NULL );
     235
     236  /*
     237   * Require the switch back to another task to install its own
     238   */
     239
     240  if ( current_task == deleted_task ) {
     241    _REENT = 0;
     242  }
    262243}
    263244
     
    295276libc_init(int reentrant)
    296277{
    297     rtems_extensions_table  libc_extension;
    298     rtems_id                extension_id;
    299     rtems_status_code       rc;
    300 
    301     libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
    302     _REENT = &libc_global_reent;
    303 
    304     if (reentrant)
    305     {
    306         memset(&libc_extension, 0, sizeof(libc_extension));
    307 
    308         libc_extension.thread_create  = libc_create_hook;
    309         libc_extension.thread_start   = libc_start_hook;
     278  rtems_extensions_table  libc_extension;
     279  rtems_status_code       rc;
     280  rtems_id                extension_id;
     281
     282  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
     283  _REENT = &libc_global_reent;
     284
     285  if (reentrant) {
     286    memset(&libc_extension, 0, sizeof(libc_extension));
     287
     288    libc_extension.thread_create  = libc_create_hook;
     289    libc_extension.thread_start   = libc_start_hook;
    310290#ifdef NEED_SETVBUF
    311         libc_extension.thread_begin   = libc_begin_hook;
    312 #endif
    313         libc_extension.thread_switch  = libc_switch_hook;
    314         libc_extension.thread_delete  = libc_delete_hook;
    315 
    316         rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
    317                               &libc_extension, &extension_id);
    318         if (rc != RTEMS_SUCCESSFUL)
    319             rtems_fatal_error_occurred( rc );
    320 
    321         libc_reentrant = reentrant;
    322     }
    323 }
    324 
    325 #if 0
    326 /*
    327  *  Routines required by the gnat runtime.
    328  */
    329 
    330 int get_errno()
    331 {
    332   return errno;
    333 }
    334 #endif
     291    libc_extension.thread_begin   = libc_begin_hook;
     292#endif
     293    libc_extension.thread_switch  = libc_switch_hook;
     294    libc_extension.thread_delete  = libc_delete_hook;
     295
     296    rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
     297                          &libc_extension, &extension_id);
     298    if (rc != RTEMS_SUCCESSFUL)
     299      rtems_fatal_error_occurred( rc );
     300
     301    libc_reentrant = reentrant;
     302    extension_index = rtems_get_index( extension_id );
     303  }
     304}
    335305
    336306/*
     
    367337void _exit(int status)
    368338{
    369     /*
    370      *  We need to do the exit processing on the global reentrancy structure.
    371      *  This has already been done on the per task reentrancy structure
    372      *  associated with this task.
    373      */
    374 
    375     libc_wrapup();
    376     rtems_shutdown_executive(status);
     339  /*
     340   *  We need to do the exit processing on the global reentrancy structure.
     341   *  This has already been done on the per task reentrancy structure
     342   *  associated with this task.
     343   */
     344
     345  libc_wrapup();
     346  rtems_shutdown_executive(status);
    377347}
    378348
     
    381351void exit(int status)
    382352{
    383     libc_wrapup();
    384     rtems_shutdown_executive(status);
    385 }
    386 #endif
    387 
    388 
    389 /*
    390  *  These are directly supported (and completely correct) in the posix api.
    391  */
    392 
    393 pid_t __getpid(void)
    394 {
    395   return getpid();
    396 }
    397 
    398 #if !defined(RTEMS_POSIX_API)
    399 pid_t getpid(void)
    400 {
    401   return 0;
    402 }
    403 
    404 pid_t _getpid_r(
    405   struct _reent *ptr
    406 )
    407 {
    408   return getpid();
    409 }
    410 #endif
    411 
    412 #if !defined(RTEMS_POSIX_API)
    413 int kill( pid_t pid, int sig )
    414 {
    415   return 0;
    416 }
    417 
    418 int _kill_r( pid_t pid, int sig )
    419 {
    420   return 0;
    421 }
    422 #endif
    423 
    424 int __kill( pid_t pid, int sig )
    425 {
    426   return 0;
    427 }
    428 
    429 #if !defined(RTEMS_POSIX_API)
    430 unsigned int sleep(
    431   unsigned int seconds
    432 )
    433 {
    434   rtems_status_code status;
    435   rtems_interval    ticks_per_second;
    436   rtems_interval    ticks;
    437  
    438   status = rtems_clock_get(
    439     RTEMS_CLOCK_GET_TICKS_PER_SECOND,
    440     &ticks_per_second
    441   );
    442  
    443   ticks = seconds * ticks_per_second;
    444  
    445   status = rtems_task_wake_after( ticks );
    446  
    447   /*
    448    *  Returns the "unslept" amount of time.  In RTEMS signals are not
    449    *  interruptable, so tasks really sleep all of the requested time.
    450    */
    451  
    452   return 0;
    453 }
    454 #endif
    455 
    456 
    457 /*
    458  *  Newlib Interface Support
    459  *
    460  *  Routines to Access Internal RTEMS Resources without violating
    461  *  kernel visibility.
    462  *
    463  */
    464 
    465 void MY_task_set_note(
    466   Thread_Control *the_thread,
    467   unsigned32      notepad,
    468   unsigned32      note
    469 )
    470 {
    471   RTEMS_API_Control    *api;
    472  
    473   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    474 
    475   if ( api )
    476     api->Notepads[ notepad ] = note;
    477 }
    478 
    479 
    480 unsigned32 MY_task_get_note(
    481   Thread_Control *the_thread,
    482   unsigned32      notepad
    483 )
    484 {
    485   RTEMS_API_Control    *api;
    486  
    487   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    488 
    489   return api->Notepads[ notepad ];
    490 }
    491 
    492 void *MY_CPU_Context_FP_start(
    493   void       *base,
    494   unsigned32  offset
    495 )
    496 {
    497   return _CPU_Context_Fp_start( base, offset );
    498 }
    499 #endif
     353  libc_wrapup();
     354  rtems_shutdown_executive(status);
     355}
     356#endif
     357
     358
     359#endif
  • cpukit/libcsupport/src/newlibc.c

    r0fab6dde r7edb9281  
    4141#endif
    4242
     43static int extension_index;
     44
    4345/*
    4446 *  Private routines
    4547 */
    4648
    47 void MY_task_set_note(
    48   rtems_tcb        *tcb,
    49   rtems_unsigned32 notepad,
    50   rtems_unsigned32 note
    51 );
    52 
    53 rtems_unsigned32 MY_task_get_note(
    54   rtems_tcb        *tcb,
    55   rtems_unsigned32  notepad
    56 );
    57 
    58 
    59 #define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
    60 
     49#define set_newlib_extension( _the_thread, _value ) \
     50  (_the_thread)->extensions[ extension_index ] = (_value);
     51
     52#define get_newlib_extension( _the_thread ) \
     53  (_the_thread)->extensions[ extension_index ]
    6154
    6255int              libc_reentrant;        /* do we think we are reentrant? */
     
    7467#include <stdio.h>
    7568
    76 void
    77 libc_wrapup(void)
    78 {
    79     /*
    80      *  In case RTEMS is already down, don't do this.  It could be
    81      *  dangerous.
    82      */
    83 
    84     if (!_System_state_Is_up(_System_state_Get()))
    85        return;
    86 
    87     /*
    88      *  This was already done if the user called exit() directly .
    89 
    90     _wrapup_reent(0);
    91      */
    92     if (_REENT != &libc_global_reent)
    93     {
    94         _wrapup_reent(&libc_global_reent);
     69void libc_wrapup(void)
     70{
     71  /*
     72   *  In case RTEMS is already down, don't do this.  It could be
     73   *  dangerous.
     74   */
     75
     76  if (!_System_state_Is_up(_System_state_Get()))
     77     return;
     78
     79  /*
     80   *  This was already done if the user called exit() directly .
     81  _wrapup_reent(0);
     82   */
     83
     84  if (_REENT != &libc_global_reent) {
     85      _wrapup_reent(&libc_global_reent);
    9586#if 0
    96         /* don't reclaim this one, just in case we do printfs */
    97         /* on our way out to ROM */
    98         _reclaim_reent(&libc_global_reent);
    99 #endif
    100         _REENT = &libc_global_reent;
    101     }
    102    
    103     /*
    104      * Try to drain output buffers.
    105      *
    106      * Should this be changed to do *all* file streams?
    107      *  _fwalk (_REENT, fclose);
    108      */
    109     fclose (stdin);
    110     fclose (stdout);
    111     fclose (stderr);
    112 }
    113 
    114 
    115 rtems_boolean
    116 libc_create_hook(rtems_tcb *current_task,
    117                  rtems_tcb *creating_task)
    118 {
    119     MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
    120     return TRUE;
     87      /*  Don't reclaim this one, just in case we do printfs
     88       *  on the way out to ROM.
     89       */
     90      _reclaim_reent(&libc_global_reent);
     91#endif
     92      _REENT = &libc_global_reent;
     93  }
     94 
     95  /*
     96   * Try to drain output buffers.
     97   *
     98   * Should this be changed to do *all* file streams?
     99   *    _fwalk (_REENT, fclose);
     100   */
     101
     102  fclose (stdin);
     103  fclose (stdout);
     104  fclose (stderr);
     105}
     106
     107
     108rtems_boolean libc_create_hook(
     109  rtems_tcb *current_task,
     110  rtems_tcb *creating_task
     111)
     112{
     113  set_newlib_extension( creating_task, NULL );
     114  return TRUE;
    121115}
    122116
     
    125119 */
    126120
    127 rtems_extension
    128 libc_start_hook(rtems_tcb *current_task,
    129                 rtems_tcb *starting_task)
    130 {
    131     struct _reent *ptr;
    132 
    133     /* NOTE: our malloc is reentrant without a reent ptr since
    134      *  it is based on region manager
    135      */
    136 
    137     ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
    138 
    139     if (!ptr)
    140        rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
     121rtems_extension libc_start_hook(
     122  rtems_tcb *current_task,
     123  rtems_tcb *starting_task
     124)
     125{
     126  struct _reent *ptr;
     127
     128  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
     129   *        it is based on the Classic API Region Manager.
     130   */
     131
     132  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
     133
     134  if (!ptr)
     135     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
    141136 
    142137#ifdef __GNUC__
    143     /* GCC extension: structure constants */
    144     *ptr = (struct _reent) _REENT_INIT((*ptr));
     138  /* GCC extension: structure constants */
     139  *ptr = (struct _reent) _REENT_INIT((*ptr));
    145140#else
    146     /*
    147      *  Warning: THIS IS VERY DEPENDENT ON NEWLIB!!! WRITTEN FOR 1.7.0
    148      */
    149     ptr->_errno=0;
    150     ptr->_stdin=&ptr->__sf[0];
    151     ptr->_stdout=&ptr->__sf[1];
    152     ptr->_stderr=&ptr->__sf[2];
    153     ptr->_scanpoint=0;
    154     ptr->_asctime[0]=0;
    155     ptr->_next=1;
    156     ptr->__sdidinit=0;
    157 #endif
    158 
    159     MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
     141  /*
     142   *  WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
     143   *           Last visual check was against newlib 1.8.2 but last known
     144   *           use was against 1.7.0.  This is basically an exansion of
     145   *           REENT_INIT() in <sys/reent.h>.
     146   *  NOTE:    calloc() takes care of zeroing fields.
     147   */
     148  ptr->_stdin = &ptr->__sf[0];
     149  ptr->_stdout = &ptr->__sf[1];
     150  ptr->_stderr = &ptr->__sf[2];
     151  ptr->_current_locale = "C";
     152  ptr->_new._reent._rand_next = 1;
     153#endif
     154
     155  set_newlib_extension( starting_task, ptr );
    160156}
    161157
     
    165161 
    166162#ifdef NEED_SETVBUF
    167 rtems_extension
    168 libc_begin_hook(rtems_tcb *current_task)
     163rtems_extension libc_begin_hook(rtems_tcb *current_task)
    169164{
    170165  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
     
    172167#endif
    173168
    174 rtems_extension
    175 libc_switch_hook(rtems_tcb *current_task,
    176                  rtems_tcb *heir_task)
    177 {
    178     rtems_unsigned32 impure_value;
    179 
    180     /* XXX We can't use rtems_task_set_note() here since SYSI task has a
    181      * tid of 0, which is treated specially (optimized, actually)
    182      * by rtems_task_set_note
    183      *
    184      * NOTE:  The above comment is no longer true and we need to use
    185      *        the extension data areas added about the same time.
    186      */
    187 
    188     /*
    189      *  Don't touch the outgoing task if it has been deleted.
    190      */
    191 
    192     if ( !_States_Is_transient( current_task->current_state ) ) {
    193       impure_value = (rtems_unsigned32) _REENT;
    194       MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
    195     }
    196 
    197     _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
    198 
     169rtems_extension libc_switch_hook(
     170  rtems_tcb *current_task,
     171  rtems_tcb *heir_task
     172)
     173{
     174  /*
     175   *  Don't touch the outgoing task if it has been deleted.
     176   */
     177
     178  if ( !_States_Is_transient( current_task->current_state ) ) {
     179    set_newlib_extension( current_task, _REENT );
     180  }
     181
     182  _REENT = (struct _reent *) get_newlib_extension( heir_task );
    199183}
    200184
     
    223207 *
    224208 */
    225 rtems_extension
    226 libc_delete_hook(rtems_tcb *current_task,
    227                  rtems_tcb *deleted_task)
    228 {
    229     struct _reent *ptr;
    230 
    231     /*
    232      * The reentrancy structure was allocated by newlib using malloc()
    233      */
    234 
    235     if (current_task == deleted_task)
    236     {
    237       ptr = _REENT;
    238     }
    239     else
    240     {
    241       ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
    242     }
    243 
    244     /* if (ptr) */
    245     if (ptr && ptr != &libc_global_reent)
    246     {
    247       _wrapup_reent(ptr);
    248       _reclaim_reent(ptr);
    249       free(ptr);
    250     }
    251 
    252     MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
    253 
    254     /*
    255      * Require the switch back to another task to install its own
    256      */
    257 
    258     if (current_task == deleted_task)
    259     {
    260       _REENT = 0;
    261     }
     209
     210rtems_extension libc_delete_hook(
     211  rtems_tcb *current_task,
     212  rtems_tcb *deleted_task
     213)
     214{
     215  struct _reent *ptr;
     216
     217  /*
     218   * The reentrancy structure was allocated by newlib using malloc()
     219   */
     220
     221  if (current_task == deleted_task) {
     222    ptr = _REENT;
     223  } else {
     224    ptr = (struct _reent *) get_newlib_extension( deleted_task );
     225  }
     226
     227  /* if (ptr) */
     228  if (ptr && ptr != &libc_global_reent) {
     229    _wrapup_reent(ptr);
     230    _reclaim_reent(ptr);
     231    free(ptr);
     232  }
     233
     234  set_newlib_extension( deleted_task, NULL );
     235
     236  /*
     237   * Require the switch back to another task to install its own
     238   */
     239
     240  if ( current_task == deleted_task ) {
     241    _REENT = 0;
     242  }
    262243}
    263244
     
    295276libc_init(int reentrant)
    296277{
    297     rtems_extensions_table  libc_extension;
    298     rtems_id                extension_id;
    299     rtems_status_code       rc;
    300 
    301     libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
    302     _REENT = &libc_global_reent;
    303 
    304     if (reentrant)
    305     {
    306         memset(&libc_extension, 0, sizeof(libc_extension));
    307 
    308         libc_extension.thread_create  = libc_create_hook;
    309         libc_extension.thread_start   = libc_start_hook;
     278  rtems_extensions_table  libc_extension;
     279  rtems_status_code       rc;
     280  rtems_id                extension_id;
     281
     282  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
     283  _REENT = &libc_global_reent;
     284
     285  if (reentrant) {
     286    memset(&libc_extension, 0, sizeof(libc_extension));
     287
     288    libc_extension.thread_create  = libc_create_hook;
     289    libc_extension.thread_start   = libc_start_hook;
    310290#ifdef NEED_SETVBUF
    311         libc_extension.thread_begin   = libc_begin_hook;
    312 #endif
    313         libc_extension.thread_switch  = libc_switch_hook;
    314         libc_extension.thread_delete  = libc_delete_hook;
    315 
    316         rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
    317                               &libc_extension, &extension_id);
    318         if (rc != RTEMS_SUCCESSFUL)
    319             rtems_fatal_error_occurred( rc );
    320 
    321         libc_reentrant = reentrant;
    322     }
    323 }
    324 
    325 #if 0
    326 /*
    327  *  Routines required by the gnat runtime.
    328  */
    329 
    330 int get_errno()
    331 {
    332   return errno;
    333 }
    334 #endif
     291    libc_extension.thread_begin   = libc_begin_hook;
     292#endif
     293    libc_extension.thread_switch  = libc_switch_hook;
     294    libc_extension.thread_delete  = libc_delete_hook;
     295
     296    rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
     297                          &libc_extension, &extension_id);
     298    if (rc != RTEMS_SUCCESSFUL)
     299      rtems_fatal_error_occurred( rc );
     300
     301    libc_reentrant = reentrant;
     302    extension_index = rtems_get_index( extension_id );
     303  }
     304}
    335305
    336306/*
     
    367337void _exit(int status)
    368338{
    369     /*
    370      *  We need to do the exit processing on the global reentrancy structure.
    371      *  This has already been done on the per task reentrancy structure
    372      *  associated with this task.
    373      */
    374 
    375     libc_wrapup();
    376     rtems_shutdown_executive(status);
     339  /*
     340   *  We need to do the exit processing on the global reentrancy structure.
     341   *  This has already been done on the per task reentrancy structure
     342   *  associated with this task.
     343   */
     344
     345  libc_wrapup();
     346  rtems_shutdown_executive(status);
    377347}
    378348
     
    381351void exit(int status)
    382352{
    383     libc_wrapup();
    384     rtems_shutdown_executive(status);
    385 }
    386 #endif
    387 
    388 
    389 /*
    390  *  These are directly supported (and completely correct) in the posix api.
    391  */
    392 
    393 pid_t __getpid(void)
    394 {
    395   return getpid();
    396 }
    397 
    398 #if !defined(RTEMS_POSIX_API)
    399 pid_t getpid(void)
    400 {
    401   return 0;
    402 }
    403 
    404 pid_t _getpid_r(
    405   struct _reent *ptr
    406 )
    407 {
    408   return getpid();
    409 }
    410 #endif
    411 
    412 #if !defined(RTEMS_POSIX_API)
    413 int kill( pid_t pid, int sig )
    414 {
    415   return 0;
    416 }
    417 
    418 int _kill_r( pid_t pid, int sig )
    419 {
    420   return 0;
    421 }
    422 #endif
    423 
    424 int __kill( pid_t pid, int sig )
    425 {
    426   return 0;
    427 }
    428 
    429 #if !defined(RTEMS_POSIX_API)
    430 unsigned int sleep(
    431   unsigned int seconds
    432 )
    433 {
    434   rtems_status_code status;
    435   rtems_interval    ticks_per_second;
    436   rtems_interval    ticks;
    437  
    438   status = rtems_clock_get(
    439     RTEMS_CLOCK_GET_TICKS_PER_SECOND,
    440     &ticks_per_second
    441   );
    442  
    443   ticks = seconds * ticks_per_second;
    444  
    445   status = rtems_task_wake_after( ticks );
    446  
    447   /*
    448    *  Returns the "unslept" amount of time.  In RTEMS signals are not
    449    *  interruptable, so tasks really sleep all of the requested time.
    450    */
    451  
    452   return 0;
    453 }
    454 #endif
    455 
    456 
    457 /*
    458  *  Newlib Interface Support
    459  *
    460  *  Routines to Access Internal RTEMS Resources without violating
    461  *  kernel visibility.
    462  *
    463  */
    464 
    465 void MY_task_set_note(
    466   Thread_Control *the_thread,
    467   unsigned32      notepad,
    468   unsigned32      note
    469 )
    470 {
    471   RTEMS_API_Control    *api;
    472  
    473   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    474 
    475   if ( api )
    476     api->Notepads[ notepad ] = note;
    477 }
    478 
    479 
    480 unsigned32 MY_task_get_note(
    481   Thread_Control *the_thread,
    482   unsigned32      notepad
    483 )
    484 {
    485   RTEMS_API_Control    *api;
    486  
    487   api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
    488 
    489   return api->Notepads[ notepad ];
    490 }
    491 
    492 void *MY_CPU_Context_FP_start(
    493   void       *base,
    494   unsigned32  offset
    495 )
    496 {
    497   return _CPU_Context_Fp_start( base, offset );
    498 }
    499 #endif
     353  libc_wrapup();
     354  rtems_shutdown_executive(status);
     355}
     356#endif
     357
     358
     359#endif
Note: See TracChangeset for help on using the changeset viewer.