source: rtems/cpukit/libcsupport/src/newlibc.c @ 7bd88b54

4.104.114.84.95
Last change on this file since 7bd88b54 was 7bd88b54, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/15/03 at 00:58:13

2003-09-15 Ralf Corsepius <corsepiu@…>

PR 489/rtems

  • src/newlibc.c: Reflect struct Thread_Control_struct.libc_reent having changed from void * to struct _reent*.
  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
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 *
6 *  COPYRIGHT (c) 1994 by Division Incorporated
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 *
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
21#include <rtems.h>
22
23#if defined(RTEMS_NEWLIB)
24#include <rtems/libcsupport.h>
25#include <stdlib.h>             /* for free() */
26#include <string.h>             /* for memset() */
27
28#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
29#include <errno.h>
30
31/*
32 *  NOTE:
33 *        There is some problem with doing this on the hpux version
34 *        of the UNIX simulator (symptom is printf core dumps), so
35 *        we just don't for now.
36 *        Not sure if this is a problem with hpux, newlib, or something else.
37 */
38 
39#if defined(RTEMS_UNIX) && !defined(hpux)
40#define NEED_SETVBUF
41#endif
42 
43#include <stdio.h>
44
45int              libc_reentrant;        /* do we think we are reentrant? */
46struct _reent    libc_global_reent;
47
48/*
49 * CYGNUS newlib routine that does atexit() processing and flushes
50 *      stdio streams
51 *      undocumented
52 */
53
54extern void _wrapup_reent(struct _reent *);
55extern void _reclaim_reent(struct _reent *);
56
57void libc_wrapup(void)
58{
59  /*
60   *  In case RTEMS is already down, don't do this.  It could be
61   *  dangerous.
62   */
63
64  if (!_System_state_Is_up(_System_state_Get()))
65     return;
66
67  /*
68   *  This was already done if the user called exit() directly .
69  _wrapup_reent(0);
70   */
71
72  if (_REENT != &libc_global_reent) {
73      _wrapup_reent(&libc_global_reent);
74#if 0
75      /*  Don't reclaim this one, just in case we do printfs
76       *  on the way out to ROM.
77       */
78      _reclaim_reent(&libc_global_reent);
79#endif
80      _REENT = &libc_global_reent;
81  }
82 
83  /*
84   * Try to drain output buffers.
85   *
86   * Should this be changed to do *all* file streams?
87   *    _fwalk (_REENT, fclose);
88   */
89
90  fclose (stdin);
91  fclose (stdout);
92  fclose (stderr);
93}
94
95
96rtems_boolean libc_create_hook(
97  rtems_tcb *current_task,
98  rtems_tcb *creating_task
99)
100{
101  creating_task->libc_reent = NULL;
102  return TRUE;
103}
104
105/*
106 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
107 */
108
109rtems_extension libc_start_hook(
110  rtems_tcb *current_task,
111  rtems_tcb *starting_task
112)
113{
114  struct _reent *ptr;
115
116  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
117   *        it is based on the Classic API Region Manager.
118   */
119
120  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
121
122  if (!ptr)
123     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
124 
125#ifdef __GNUC__
126  /* GCC extension: structure constants */
127  _REENT_INIT_PTR((ptr));
128#else
129  /*
130   *  WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
131   *           Last visual check was against newlib 1.8.2 but last known
132   *           use was against 1.7.0.  This is basically an exansion of
133   *           REENT_INIT() in <sys/reent.h>.
134   *  NOTE:    calloc() takes care of zeroing fields.
135   */
136  ptr->_stdin = &ptr->__sf[0];
137  ptr->_stdout = &ptr->__sf[1];
138  ptr->_stderr = &ptr->__sf[2];
139  ptr->_current_locale = "C";
140  ptr->_new._reent._rand_next = 1;
141#endif
142
143  starting_task->libc_reent = ptr;
144}
145
146/*
147 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
148 */
149 
150#ifdef NEED_SETVBUF
151rtems_extension libc_begin_hook(rtems_tcb *current_task)
152{
153  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
154}
155#endif
156
157/*
158 *  Function:   libc_delete_hook
159 *  Created:    94/12/10
160 *
161 *  Description:
162 *      Called when a task is deleted.
163 *      Must restore the new lib reentrancy state for the new current
164 *      task.
165 *
166 *  Parameters:
167 *
168 *
169 *  Returns:
170 *
171 *
172 *  Side Effects:
173 *
174 *  Notes:
175 *
176 *
177 *  Deficiencies/ToDo:
178 *
179 *
180 */
181
182rtems_extension libc_delete_hook(
183  rtems_tcb *current_task,
184  rtems_tcb *deleted_task
185)
186{
187  struct _reent *ptr;
188
189  /*
190   * The reentrancy structure was allocated by newlib using malloc()
191   */
192
193  if (current_task == deleted_task) {
194    ptr = _REENT;
195  } else {
196    ptr = deleted_task->libc_reent;
197  }
198
199  /* if (ptr) */
200  if (ptr && ptr != &libc_global_reent) {
201    _wrapup_reent(ptr);
202    _reclaim_reent(ptr);
203    free(ptr);
204  }
205
206  deleted_task->libc_reent = NULL;
207
208  /*
209   * Require the switch back to another task to install its own
210   */
211
212  if ( current_task == deleted_task ) {
213    _REENT = 0;
214  }
215}
216
217/*
218 *  Function:   libc_init
219 *  Created:    94/12/10
220 *
221 *  Description:
222 *      Init libc for CYGNUS newlib
223 *      Set up _REENT to use our global libc_global_reent.
224 *      (newlib provides a global of its own, but we prefer our
225 *      own name for it)
226 *
227 *      If reentrancy is desired (which it should be), then
228 *      we install the task extension hooks to maintain the
229 *      newlib reentrancy global variable _REENT on task
230 *      create, delete, switch, exit, etc.
231 *
232 *  Parameters:
233 *      reentrant               non-zero if reentrant library desired.
234 *
235 *  Returns:
236 *
237 *  Side Effects:
238 *      installs libc extensions if reentrant.
239 *
240 *  Notes:
241 *
242 *
243 *  Deficiencies/ToDo:
244 *
245 */
246
247void
248libc_init(int reentrant)
249{
250  rtems_extensions_table  libc_extension;
251  rtems_status_code       rc;
252  rtems_id                extension_id;
253
254  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
255  _REENT = &libc_global_reent;
256
257  if (reentrant) {
258    memset(&libc_extension, 0, sizeof(libc_extension));
259
260    libc_extension.thread_create  = libc_create_hook;
261    libc_extension.thread_start   = libc_start_hook;
262#ifdef NEED_SETVBUF
263    libc_extension.thread_begin   = libc_begin_hook;
264#endif
265    libc_extension.thread_delete  = libc_delete_hook;
266
267    _Thread_Set_libc_reent (&_REENT);
268
269    rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
270                          &libc_extension, &extension_id);
271    if (rc != RTEMS_SUCCESSFUL)
272      rtems_fatal_error_occurred( rc );
273
274    libc_reentrant = reentrant;
275  }
276}
277
278/*
279 *  Function:   _exit
280 *  Created:    94/12/10
281 *
282 *  Description:
283 *      Called from exit() after it does atexit() processing and stdio fflush's
284 *
285 *      called from bottom of exit() to really delete the task.
286 *      If we are using reentrant libc, then let the delete extension
287 *      do all the work, otherwise if a shutdown is in progress,
288 *      then just do it.
289 *
290 *  Parameters:
291 *      exit status
292 *
293 *  Returns:
294 *      does not return
295 *
296 *  Side Effects:
297 *
298 *  Notes:
299 *
300 *
301 *  Deficiencies/ToDo:
302 *
303 *
304 */
305
306#include <unistd.h>
307
308#if !defined(RTEMS_UNIX)
309void _exit(int status)
310{
311  /*
312   *  We need to do the exit processing on the global reentrancy structure.
313   *  This has already been done on the per task reentrancy structure
314   *  associated with this task.
315   */
316
317  libc_wrapup();
318  rtems_shutdown_executive(status);
319  for (;;) ; /* to avoid warnings */
320}
321
322#else
323
324void exit(int status)
325{
326  libc_wrapup();
327  rtems_shutdown_executive(status);
328  for (;;) ; /* to avoid warnings */
329}
330#endif
331
332#endif
Note: See TracBrowser for help on using the repository browser.