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

4.104.114.84.95
Last change on this file since eaa442fc was eaa442fc, checked in by Joel Sherrill <joel.sherrill@…>, on 01/19/96 at 22:20:40

added a task begin extension for unix simulator configurations. This extension
insures that stdout is line buffered (see setvbuf).

  • Property mode set to 100644
File size: 7.3 KB
Line 
1/*
2 *      @(#)newlibc.c   1.9 - 95/05/16
3 *     
4 */
5
6#if defined(RTEMS_NEWLIB)
7
8/*
9 *  File:       newlibc.c,v
10 *  Project:    PixelFlow
11 *  Created:    94/12/7
12 *  Revision:   1.2
13 *  Last Mod:   1995/05/09 20:24:37
14 *
15 *  COPYRIGHT (c) 1994 by Division Incorporated
16 *
17 *  To anyone who acknowledges that this file is provided "AS IS"
18 *  without any express or implied warranty:
19 *      permission to use, copy, modify, and distribute this file
20 *      for any purpose is hereby granted without fee, provided that
21 *      the above copyright notice and this notice appears in all
22 *      copies, and that the name of Division Incorporated not be
23 *      used in advertising or publicity pertaining to distribution
24 *      of the software without specific, written prior permission.
25 *      Division Incorporated makes no representations about the
26 *      suitability of this software for any purpose.
27 *
28 *  Description:
29 *      Implementation of hooks for the CYGNUS newlib libc
30 *      These hooks set things up so that:
31 *              '_REENT' is switched at task switch time.
32 *
33 *
34 *  TODO:
35 *
36 *  NOTE:
37 *
38 *  $Id$
39 *
40 */
41
42#include <rtems.h>
43#include <libcsupport.h>
44#include <stdlib.h>             /* for free() */
45#include <string.h>             /* for memset() */
46
47#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
48
49#ifdef RTEMS_UNIX
50#include <stdio.h>              /* for setvbuf() */
51#endif
52
53#include "internal.h"
54
55#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
56
57
58int              libc_reentrant;        /* do we think we are reentrant? */
59struct _reent    libc_global_reent = _REENT_INIT(libc_global_reent);;
60
61/*
62 * CYGNUS newlib routine that does atexit() processing and flushes
63 *      stdio streams
64 *      undocumented
65 */
66
67extern void _wrapup_reent(struct _reent *);
68extern void _reclaim_reent(struct _reent *);
69
70void
71libc_wrapup(void)
72{
73    _wrapup_reent(0);
74    if (_REENT != &libc_global_reent)
75    {
76        _wrapup_reent(&libc_global_reent);
77#if 0
78        /* don't reclaim this one, just in case we do printfs */
79        /* on our way out to ROM */
80        _reclaim_reent(&libc_global_reent);
81#endif
82        _REENT = &libc_global_reent;
83    }
84}
85
86
87rtems_boolean
88libc_create_hook(rtems_tcb *current_task,
89                 rtems_tcb *creating_task)
90{
91    MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
92    return TRUE;
93}
94
95/*
96 * Called for all user TASKS (system tasks are SYSI and IDLE)
97 */
98
99rtems_extension
100libc_start_hook(rtems_tcb *current_task,
101                rtems_tcb *starting_task)
102{
103    struct _reent *ptr;
104
105    /* NOTE: our malloc is reentrant without a reent ptr since
106     *  it is based on region manager
107     */
108
109    ptr = (struct _reent *) malloc(sizeof(struct _reent));
110
111    /* GCC extension: structure constants */
112    *ptr = (struct _reent) _REENT_INIT((*ptr));
113
114    MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
115}
116
117/*
118 * Called for all user TASKS (system tasks are SYSI and IDLE)
119 *
120 *  NOTE: When using RTEMS fake stat, fstat, and isatty, all output
121 *        is line buffered so this setvbuf is not necessary.  This
122 *        setvbuf insures that we can redirect the output of a test
123 *        on the UNIX simulator and it is in the same order as for a
124 *        real target.
125 */
126 
127#ifdef RTEMS_UNIX
128rtems_extension
129libc_begin_hook(rtems_tcb *current_task)
130{
131  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
132}
133#endif
134
135rtems_extension
136libc_switch_hook(rtems_tcb *current_task,
137                 rtems_tcb *heir_task)
138{
139    rtems_unsigned32 impure_value;
140
141    /* XXX We can't use rtems_task_set_note() here since SYSI task has a
142     * tid of 0, which is treated specially (optimized, actually)
143     * by rtems_task_set_note
144     *
145     * NOTE:  The above comment is no longer true and we need to use
146     *        the extension data areas added about the same time.
147     */
148
149    /*
150     *  Don't touch the outgoing task if it has been deleted.
151     */
152
153    if ( !_States_Is_transient( current_task->current_state ) ) {
154      impure_value = (rtems_unsigned32) _REENT;
155      MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
156    }
157
158    _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
159
160}
161
162/*
163 *  Function:   libc_delete_hook
164 *  Created:    94/12/10
165 *
166 *  Description:
167 *      Called when a task is deleted.
168 *      Must restore the new lib reentrancy state for the new current
169 *      task.
170 *
171 *  Parameters:
172 *
173 *
174 *  Returns:
175 *
176 *
177 *  Side Effects:
178 *
179 *  Notes:
180 *
181 *
182 *  Deficiencies/ToDo:
183 *
184 *
185 */
186rtems_extension
187libc_delete_hook(rtems_tcb *current_task,
188                 rtems_tcb *deleted_task)
189{
190    struct _reent *ptr;
191
192    /*
193     * The reentrancy structure was allocated by newlib using malloc()
194     */
195
196    if (current_task == deleted_task)
197    {
198        ptr = _REENT;
199    }
200    else
201    {
202        ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
203    }
204
205    /* if (ptr) */
206    if (ptr && ptr != &libc_global_reent)
207    {
208        _wrapup_reent(ptr);
209        _reclaim_reent(ptr);
210    }
211
212    MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
213
214    /*
215     * Require the switch back to another task to install its own
216     */
217
218    if (current_task == deleted_task)
219    {
220        _REENT = 0;
221    }
222}
223
224/*
225 *  Function:   libc_init
226 *  Created:    94/12/10
227 *
228 *  Description:
229 *      Init libc for CYGNUS newlib
230 *      Set up _REENT to use our global libc_global_reent.
231 *      (newlib provides a global of its own, but we prefer our
232 *      own name for it)
233 *
234 *      If reentrancy is desired (which it should be), then
235 *      we install the task extension hooks to maintain the
236 *      newlib reentrancy global variable _REENT on task
237 *      create, delete, switch, exit, etc.
238 *
239 *  Parameters:
240 *      reentrant               non-zero if reentrant library desired.
241 *
242 *  Returns:
243 *
244 *  Side Effects:
245 *      installs libc extensions if reentrant.
246 *
247 *  Notes:
248 *
249 *
250 *  Deficiencies/ToDo:
251 *
252 */
253
254void
255libc_init(int reentrant)
256{
257    rtems_extensions_table  libc_extension;
258    rtems_id                extension_id;
259    rtems_status_code       rc;
260
261    _REENT = &libc_global_reent;
262
263    if (reentrant)
264    {
265        memset(&libc_extension, 0, sizeof(libc_extension));
266
267        libc_extension.thread_create  = libc_create_hook;
268        libc_extension.thread_start   = libc_start_hook;
269#ifdef RTEMS_UNIX
270        libc_extension.thread_begin   = libc_begin_hook;
271#endif
272        libc_extension.thread_switch  = libc_switch_hook;
273        libc_extension.thread_delete  = libc_delete_hook;
274
275        rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
276                              &libc_extension, &extension_id);
277        if (rc != RTEMS_SUCCESSFUL)
278            rtems_fatal_error_occurred(rc);
279
280        libc_reentrant = reentrant;
281    }
282}
283
284
285void
286exit(int status)
287{
288    libc_wrapup();
289    rtems_shutdown_executive(status);
290}
291
292
293/*
294 *  Function:   _exit
295 *  Created:    94/12/10
296 *
297 *  Description:
298 *      Called from exit() after it does atexit() processing and stdio fflush's
299 *
300 *      called from bottom of exit() to really delete the task.
301 *      If we are using reentrant libc, then let the delete extension
302 *      do all the work, otherwise if a shutdown is in progress,
303 *      then just do it.
304 *
305 *  Parameters:
306 *      exit status
307 *
308 *  Returns:
309 *      does not return
310 *
311 *  Side Effects:
312 *
313 *  Notes:
314 *
315 *
316 *  Deficiencies/ToDo:
317 *
318 *
319 */
320
321#if !defined(RTEMS_UNIX) && !defined(__GO32__)
322void _exit(int status)
323{
324    rtems_shutdown_executive(status);
325}
326#endif
327
328#endif
Note: See TracBrowser for help on using the repository browser.