source: rtems/c/src/lib/libc/newlibc.c @ 5e9b32b

4.104.114.84.95
Last change on this file since 5e9b32b was b3ac6a8d, checked in by Joel Sherrill <joel.sherrill@…>, on 09/12/95 at 19:45:42

Initial attempt at building HP PA-RISC using Solaris hosted tools.

Changed back to Newlib for Solaris UNIX simulator.

  • Property mode set to 100644
File size: 6.7 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#include "internal.h"
50
51#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
52
53
54int              libc_reentrant;        /* do we think we are reentrant? */
55struct _reent    libc_global_reent = _REENT_INIT(libc_global_reent);;
56
57/*
58 * CYGNUS newlib routine that does atexit() processing and flushes
59 *      stdio streams
60 *      undocumented
61 */
62
63extern void _wrapup_reent(struct _reent *);
64extern void _reclaim_reent(struct _reent *);
65
66void
67libc_wrapup(void)
68{
69    _wrapup_reent(0);
70    if (_REENT != &libc_global_reent)
71    {
72        _wrapup_reent(&libc_global_reent);
73#if 0
74        /* don't reclaim this one, just in case we do printfs */
75        /* on our way out to ROM */
76        _reclaim_reent(&libc_global_reent);
77#endif
78        _REENT = &libc_global_reent;
79    }
80}
81
82
83rtems_boolean
84libc_create_hook(rtems_tcb *current_task,
85                 rtems_tcb *creating_task)
86{
87    MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
88    return TRUE;
89}
90
91/*
92 * Called for all user TASKS (system tasks are SYSI and IDLE)
93 */
94
95rtems_extension
96libc_start_hook(rtems_tcb *current_task,
97                rtems_tcb *starting_task)
98{
99    struct _reent *ptr;
100
101    /* NOTE: our malloc is reentrant without a reent ptr since
102     *  it is based on region manager
103     */
104
105    ptr = (struct _reent *) malloc(sizeof(struct _reent));
106
107    /* GCC extension: structure constants */
108    *ptr = (struct _reent) _REENT_INIT((*ptr));
109
110    MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
111}
112
113rtems_extension
114libc_switch_hook(rtems_tcb *current_task,
115                 rtems_tcb *heir_task)
116{
117    rtems_unsigned32 impure_value;
118
119    /* XXX We can't use rtems_task_set_note() here since SYSI task has a
120     * tid of 0, which is treated specially (optimized, actually)
121     * by rtems_task_set_note
122     *
123     * NOTE:  The above comment is no longer true and we need to use
124     *        the extension data areas added about the same time.
125     */
126
127    /*
128     *  Don't touch the outgoing task if it has been deleted.
129     */
130
131    if ( !_States_Is_transient( current_task->current_state ) ) {
132      impure_value = (rtems_unsigned32) _REENT;
133      MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
134    }
135
136    _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
137
138}
139
140/*
141 *  Function:   libc_delete_hook
142 *  Created:    94/12/10
143 *
144 *  Description:
145 *      Called when a task is deleted.
146 *      Must restore the new lib reentrancy state for the new current
147 *      task.
148 *
149 *  Parameters:
150 *
151 *
152 *  Returns:
153 *
154 *
155 *  Side Effects:
156 *
157 *  Notes:
158 *
159 *
160 *  Deficiencies/ToDo:
161 *
162 *
163 */
164rtems_extension
165libc_delete_hook(rtems_tcb *current_task,
166                 rtems_tcb *deleted_task)
167{
168    struct _reent *ptr;
169
170    /*
171     * The reentrancy structure was allocated by newlib using malloc()
172     */
173
174    if (current_task == deleted_task)
175    {
176        ptr = _REENT;
177    }
178    else
179    {
180        ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
181    }
182
183    /* if (ptr) */
184    if (ptr && ptr != &libc_global_reent)
185    {
186        _wrapup_reent(ptr);
187        _reclaim_reent(ptr);
188    }
189
190    MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
191
192    /*
193     * Require the switch back to another task to install its own
194     */
195
196    if (current_task == deleted_task)
197    {
198        _REENT = 0;
199    }
200}
201
202/*
203 *  Function:   libc_init
204 *  Created:    94/12/10
205 *
206 *  Description:
207 *      Init libc for CYGNUS newlib
208 *      Set up _REENT to use our global libc_global_reent.
209 *      (newlib provides a global of its own, but we prefer our
210 *      own name for it)
211 *
212 *      If reentrancy is desired (which it should be), then
213 *      we install the task extension hooks to maintain the
214 *      newlib reentrancy global variable _REENT on task
215 *      create, delete, switch, exit, etc.
216 *
217 *  Parameters:
218 *      reentrant               non-zero if reentrant library desired.
219 *
220 *  Returns:
221 *
222 *  Side Effects:
223 *      installs libc extensions if reentrant.
224 *
225 *  Notes:
226 *
227 *
228 *  Deficiencies/ToDo:
229 *
230 */
231
232void
233libc_init(int reentrant)
234{
235    rtems_extensions_table  libc_extension;
236    rtems_id                extension_id;
237    rtems_status_code       rc;
238
239    _REENT = &libc_global_reent;
240
241    if (reentrant)
242    {
243        memset(&libc_extension, 0, sizeof(libc_extension));
244
245        libc_extension.thread_create  = libc_create_hook;
246        libc_extension.thread_start   = libc_start_hook;
247        libc_extension.thread_switch  = libc_switch_hook;
248        libc_extension.thread_delete  = libc_delete_hook;
249
250        rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
251                              &libc_extension, &extension_id);
252        if (rc != RTEMS_SUCCESSFUL)
253            rtems_fatal_error_occurred(rc);
254
255        libc_reentrant = reentrant;
256    }
257}
258
259
260void
261exit(int status)
262{
263    libc_wrapup();
264    rtems_shutdown_executive(status);
265}
266
267
268/*
269 *  Function:   _exit
270 *  Created:    94/12/10
271 *
272 *  Description:
273 *      Called from exit() after it does atexit() processing and stdio fflush's
274 *
275 *      called from bottom of exit() to really delete the task.
276 *      If we are using reentrant libc, then let the delete extension
277 *      do all the work, otherwise if a shutdown is in progress,
278 *      then just do it.
279 *
280 *  Parameters:
281 *      exit status
282 *
283 *  Returns:
284 *      does not return
285 *
286 *  Side Effects:
287 *
288 *  Notes:
289 *
290 *
291 *  Deficiencies/ToDo:
292 *
293 *
294 */
295
296#if !defined(RTEMS_UNIX) && !defined(__GO32__)
297void _exit(int status)
298{
299    rtems_shutdown_executive(status);
300}
301#endif
302
303#endif
Note: See TracBrowser for help on using the repository browser.