source: rtems/cpukit/libcsupport/src/newlibc.c @ 1a8fde6c

4.104.114.84.95
Last change on this file since 1a8fde6c was 1a8fde6c, checked in by Joel Sherrill <joel.sherrill@…>, on 03/06/96 at 21:34:57

Removed prototyes for static inline routines and moved the comments into
the inline implementation. The impetus for this was twofold. First,
it is incorrect to have static inline prototypes when using the macro
implementation. Second, this reduced the number of lines in the include
files seen by rtems.h by about 2000 lines.

Next we restricted visibility for the inline routines to inside the
executive itself EXCEPT for a handful of objects. This reduced the
number of include files included by rtems.h by 40 files and reduced
the lines in the include files seen by rtems.h by about 6000 lines.

In total, these reduced the compile time of the entire RTEMS tree by 20%.
This results in about 8 minutes savings on the SparcStation? 10 morgana.

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