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

4.104.114.84.95
Last change on this file since df4b9d6 was df4b9d6, checked in by Joel Sherrill <joel.sherrill@…>, on 10/31/02 at 20:16:34

2002-10-31 Joel Sherrill <joel@…>

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