source: rtems/cpukit/libcsupport/src/newlibc.c @ fb327db3

4.104.114.84.95
Last change on this file since fb327db3 was fb327db3, checked in by Joel Sherrill <joel.sherrill@…>, on 09/22/00 at 20:35:12

2000-09-22 Joel Sherrill <joel@…>

  • libc/newlibc.c: Removed _A29K specific ifdef.
  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[ac7d5ef0]1/*
[07a3253d]2 *  Implementation of hooks for the CYGNUS newlib libc
3 *  These hooks set things up so that:
4 *       + '_REENT' is switched at task switch time.
5 *
[ac7d5ef0]6 *  COPYRIGHT (c) 1994 by Division Incorporated
7 *
[98e4ebf5]8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
[e71ce071]10 *  http://www.OARcorp.com/rtems/license.html.
[ac7d5ef0]11 *
[3235ad9]12 *  $Id$
[ac7d5ef0]13 *
14 */
15
[1a8fde6c]16#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
[ac7d5ef0]17#include <rtems.h>
[dcec5a4]18
19#if defined(RTEMS_NEWLIB)
[ac7d5ef0]20#include <libcsupport.h>
21#include <stdlib.h>             /* for free() */
22#include <string.h>             /* for memset() */
23
24#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
[8d7a1d76]25#include <errno.h>
[ac7d5ef0]26
[1f94ed6b]27/*
28 *  NOTE:
29 *        There is some problem with doing this on the hpux version
30 *        of the UNIX simulator (symptom is printf core dumps), so
31 *        we just don't for now.
32 *        Not sure if this is a problem with hpux, newlib, or something else.
33 */
34 
35#if defined(RTEMS_UNIX) && !defined(hpux)
36#define NEED_SETVBUF
37#endif
38 
39#ifdef NEED_SETVBUF
40#include <stdio.h>
[eaa442fc]41#endif
42
[7edb9281]43static int extension_index;
44
[07a3253d]45/*
46 *  Private routines
47 */
48
[7edb9281]49#define set_newlib_extension( _the_thread, _value ) \
50  (_the_thread)->extensions[ extension_index ] = (_value);
[ac7d5ef0]51
[7edb9281]52#define get_newlib_extension( _the_thread ) \
53  (_the_thread)->extensions[ extension_index ]
[ac7d5ef0]54
55int              libc_reentrant;        /* do we think we are reentrant? */
[edfb0eb]56struct _reent    libc_global_reent;
[ac7d5ef0]57
58/*
59 * CYGNUS newlib routine that does atexit() processing and flushes
60 *      stdio streams
61 *      undocumented
62 */
63
64extern void _wrapup_reent(struct _reent *);
65extern void _reclaim_reent(struct _reent *);
66
[9c3b406b]67#include <stdio.h>
68
[7edb9281]69void libc_wrapup(void)
[ac7d5ef0]70{
[7edb9281]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);
[ac7d5ef0]86#if 0
[7edb9281]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);
[ac7d5ef0]91#endif
[7edb9281]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);
[ac7d5ef0]105}
106
107
[7edb9281]108rtems_boolean libc_create_hook(
109  rtems_tcb *current_task,
110  rtems_tcb *creating_task
111)
[ac7d5ef0]112{
[7edb9281]113  set_newlib_extension( creating_task, NULL );
114  return TRUE;
[ac7d5ef0]115}
116
117/*
[8cbbe312]118 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
[ac7d5ef0]119 */
120
[7edb9281]121rtems_extension libc_start_hook(
122  rtems_tcb *current_task,
123  rtems_tcb *starting_task
124)
[ac7d5ef0]125{
[7edb9281]126  struct _reent *ptr;
[ac7d5ef0]127
[7edb9281]128  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
129   *        it is based on the Classic API Region Manager.
130   */
[ac7d5ef0]131
[7edb9281]132  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
[ac7d5ef0]133
[7edb9281]134  if (!ptr)
135     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
[5e9a594]136 
137#ifdef __GNUC__
[7edb9281]138  /* GCC extension: structure constants */
139  *ptr = (struct _reent) _REENT_INIT((*ptr));
[5e9a594]140#else
[7edb9281]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;
[5e9a594]153#endif
[ac7d5ef0]154
[7edb9281]155  set_newlib_extension( starting_task, ptr );
[ac7d5ef0]156}
157
[eaa442fc]158/*
[8cbbe312]159 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
[eaa442fc]160 */
161 
[8b2ecf85]162#ifdef NEED_SETVBUF
[7edb9281]163rtems_extension libc_begin_hook(rtems_tcb *current_task)
[eaa442fc]164{
165  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
166}
167#endif
168
[7edb9281]169rtems_extension libc_switch_hook(
170  rtems_tcb *current_task,
171  rtems_tcb *heir_task
172)
[ac7d5ef0]173{
[7edb9281]174  /*
175   *  Don't touch the outgoing task if it has been deleted.
176   */
[ac7d5ef0]177
[7edb9281]178  if ( !_States_Is_transient( current_task->current_state ) ) {
179    set_newlib_extension( current_task, _REENT );
180  }
[ac7d5ef0]181
[7edb9281]182  _REENT = (struct _reent *) get_newlib_extension( heir_task );
[ac7d5ef0]183}
184
185/*
186 *  Function:   libc_delete_hook
187 *  Created:    94/12/10
188 *
189 *  Description:
190 *      Called when a task is deleted.
191 *      Must restore the new lib reentrancy state for the new current
192 *      task.
193 *
194 *  Parameters:
195 *
196 *
197 *  Returns:
198 *
199 *
200 *  Side Effects:
201 *
202 *  Notes:
203 *
204 *
205 *  Deficiencies/ToDo:
206 *
207 *
208 */
[7edb9281]209
210rtems_extension libc_delete_hook(
211  rtems_tcb *current_task,
212  rtems_tcb *deleted_task
213)
[ac7d5ef0]214{
[7edb9281]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  }
[ac7d5ef0]243}
244
245/*
246 *  Function:   libc_init
247 *  Created:    94/12/10
248 *
249 *  Description:
250 *      Init libc for CYGNUS newlib
251 *      Set up _REENT to use our global libc_global_reent.
252 *      (newlib provides a global of its own, but we prefer our
253 *      own name for it)
254 *
255 *      If reentrancy is desired (which it should be), then
256 *      we install the task extension hooks to maintain the
257 *      newlib reentrancy global variable _REENT on task
258 *      create, delete, switch, exit, etc.
259 *
260 *  Parameters:
261 *      reentrant               non-zero if reentrant library desired.
262 *
263 *  Returns:
264 *
265 *  Side Effects:
266 *      installs libc extensions if reentrant.
267 *
268 *  Notes:
269 *
270 *
271 *  Deficiencies/ToDo:
272 *
273 */
274
275void
276libc_init(int reentrant)
277{
[7edb9281]278  rtems_extensions_table  libc_extension;
279  rtems_status_code       rc;
280  rtems_id                extension_id;
[ac7d5ef0]281
[7edb9281]282  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
283  _REENT = &libc_global_reent;
[ac7d5ef0]284
[7edb9281]285  if (reentrant) {
286    memset(&libc_extension, 0, sizeof(libc_extension));
[ac7d5ef0]287
[7edb9281]288    libc_extension.thread_create  = libc_create_hook;
289    libc_extension.thread_start   = libc_start_hook;
[8b2ecf85]290#ifdef NEED_SETVBUF
[7edb9281]291    libc_extension.thread_begin   = libc_begin_hook;
[eaa442fc]292#endif
[7edb9281]293    libc_extension.thread_switch  = libc_switch_hook;
294    libc_extension.thread_delete  = libc_delete_hook;
[ac7d5ef0]295
[7edb9281]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 );
[8d7a1d76]300
[7edb9281]301    libc_reentrant = reentrant;
302    extension_index = rtems_get_index( extension_id );
303  }
[8d7a1d76]304}
[ac7d5ef0]305
306/*
307 *  Function:   _exit
308 *  Created:    94/12/10
309 *
310 *  Description:
311 *      Called from exit() after it does atexit() processing and stdio fflush's
312 *
313 *      called from bottom of exit() to really delete the task.
314 *      If we are using reentrant libc, then let the delete extension
315 *      do all the work, otherwise if a shutdown is in progress,
316 *      then just do it.
317 *
318 *  Parameters:
319 *      exit status
320 *
321 *  Returns:
322 *      does not return
323 *
324 *  Side Effects:
325 *
326 *  Notes:
327 *
328 *
329 *  Deficiencies/ToDo:
330 *
331 *
332 */
333
[dcec5a4]334#include <stdio.h>
335
[fb327db3]336#if !defined(RTEMS_UNIX)
[ac7d5ef0]337void _exit(int status)
338{
[7edb9281]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);
[ac7d5ef0]347}
[07a3253d]348
[da4b6e8]349#else
350
351void exit(int status)
352{
[7edb9281]353  libc_wrapup();
354  rtems_shutdown_executive(status);
[8d7a1d76]355}
356#endif
357
[eb6fafd]358
[ac7d5ef0]359#endif
Note: See TracBrowser for help on using the repository browser.