source: rtems/c/src/exec/libcsupport/src/newlibc.c @ 3235ad9

4.104.114.84.95
Last change on this file since 3235ad9 was 3235ad9, checked in by Joel Sherrill <joel.sherrill@…>, on 08/23/95 at 19:30:23

Support for variable length names added to Object Handler. This supports
both fixed length "raw" names and strings from the API's point of view.

Both inline and macro implementations were tested.

  • 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 *  $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_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#if !defined(RTEMS_UNIX) && !defined(__GO32__)
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.