source: rtems/cpukit/libcsupport/src/newlibc.c @ 5b9d6ddf

4.104.114.84.95
Last change on this file since 5b9d6ddf was 88d594a, checked in by Joel Sherrill <joel.sherrill@…>, on 05/24/95 at 21:39:42

Fully tested on all in-house targets

  • Property mode set to 100644
File size: 6.4 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 *  newlibc.c,v 1.2 1995/05/09 20:24:37 joel Exp
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_extension
84libc_create_hook(rtems_tcb *current_task,
85                 rtems_tcb *creating_task)
86{
87    MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
88}
89
90/*
91 * Called for all user TASKS (system tasks are SYSI and IDLE)
92 */
93
94rtems_extension
95libc_start_hook(rtems_tcb *current_task,
96                rtems_tcb *starting_task)
97{
98    struct _reent *ptr;
99
100    /* NOTE: our malloc is reentrant without a reent ptr since
101     *  it is based on region manager
102     */
103
104    ptr = (struct _reent *) malloc(sizeof(struct _reent));
105
106    /* GCC extension: structure constants */
107    *ptr = (struct _reent) _REENT_INIT((*ptr));
108
109    MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
110}
111
112rtems_extension
113libc_switch_hook(rtems_tcb *current_task,
114                 rtems_tcb *heir_task)
115{
116    rtems_unsigned32 impure_value;
117
118    /* XXX We can't use rtems_task_set_note() here since SYSI task has a
119     * tid of 0, which is treated specially (optimized, actually)
120     * by rtems_task_set_note
121     */
122
123    impure_value = (rtems_unsigned32) _REENT;
124    MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
125
126    _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
127
128}
129
130/*
131 *  Function:   libc_delete_hook
132 *  Created:    94/12/10
133 *
134 *  Description:
135 *      Called when a task is deleted.
136 *      Must restore the new lib reentrancy state for the new current
137 *      task.
138 *
139 *  Parameters:
140 *
141 *
142 *  Returns:
143 *
144 *
145 *  Side Effects:
146 *
147 *  Notes:
148 *
149 *
150 *  Deficiencies/ToDo:
151 *
152 *
153 */
154rtems_extension
155libc_delete_hook(rtems_tcb *current_task,
156                 rtems_tcb *deleted_task)
157{
158    struct _reent *ptr;
159
160    /*
161     * The reentrancy structure was allocated by newlib using malloc()
162     */
163
164    if (current_task == deleted_task)
165    {
166        ptr = _REENT;
167    }
168    else
169    {
170        ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
171    }
172
173    if (ptr)
174    {
175        _wrapup_reent(ptr);
176        _reclaim_reent(ptr);
177    }
178
179    MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
180
181    /*
182     * Require the switch back to another task to install its own
183     */
184
185    if (current_task == deleted_task)
186    {
187        _REENT = 0;
188    }
189}
190
191/*
192 *  Function:   libc_init
193 *  Created:    94/12/10
194 *
195 *  Description:
196 *      Init libc for CYGNUS newlib
197 *      Set up _REENT to use our global libc_global_reent.
198 *      (newlib provides a global of its own, but we prefer our
199 *      own name for it)
200 *
201 *      If reentrancy is desired (which it should be), then
202 *      we install the task extension hooks to maintain the
203 *      newlib reentrancy global variable _REENT on task
204 *      create, delete, switch, exit, etc.
205 *
206 *  Parameters:
207 *      reentrant               non-zero if reentrant library desired.
208 *
209 *  Returns:
210 *
211 *  Side Effects:
212 *      installs libc extensions if reentrant.
213 *
214 *  Notes:
215 *
216 *
217 *  Deficiencies/ToDo:
218 *
219 */
220
221void
222libc_init(int reentrant)
223{
224    rtems_extensions_table  libc_extension;
225    rtems_id                extension_id;
226    rtems_status_code       rc;
227
228    _REENT = &libc_global_reent;
229
230    if (reentrant)
231    {
232        memset(&libc_extension, 0, sizeof(libc_extension));
233
234        libc_extension.rtems_task_create  = libc_create_hook;
235        libc_extension.rtems_task_start   = libc_start_hook;
236        libc_extension.task_switch  = libc_switch_hook;
237        libc_extension.rtems_task_delete  = libc_delete_hook;
238
239        rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
240                              &libc_extension, &extension_id);
241        if (rc != RTEMS_SUCCESSFUL)
242            rtems_fatal_error_occurred(rc);
243
244        libc_reentrant = reentrant;
245    }
246}
247
248
249void
250exit(int status)
251{
252    libc_wrapup();
253    rtems_shutdown_executive(status);
254}
255
256
257/*
258 *  Function:   _exit
259 *  Created:    94/12/10
260 *
261 *  Description:
262 *      Called from exit() after it does atexit() processing and stdio fflush's
263 *
264 *      called from bottom of exit() to really delete the task.
265 *      If we are using reentrant libc, then let the delete extension
266 *      do all the work, otherwise if a shutdown is in progress,
267 *      then just do it.
268 *
269 *  Parameters:
270 *      exit status
271 *
272 *  Returns:
273 *      does not return
274 *
275 *  Side Effects:
276 *
277 *  Notes:
278 *
279 *
280 *  Deficiencies/ToDo:
281 *
282 *
283 */
284
285#ifndef RTEMS_UNIX
286void _exit(int status)
287{
288    rtems_shutdown_executive(status);
289}
290#endif
291
292#endif
Note: See TracBrowser for help on using the repository browser.