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

4.104.114.84.95
Last change on this file since da4b6e8 was da4b6e8, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 1996 at 10:50:03 PM

use exit() from newlib by default.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1#if defined(RTEMS_NEWLIB)
2
3/*
4 *  COPYRIGHT (c) 1994 by Division Incorporated
5 *
6 *  To anyone who acknowledges that this file is provided "AS IS"
7 *  without any express or implied warranty:
8 *      permission to use, copy, modify, and distribute this file
9 *      for any purpose is hereby granted without fee, provided that
10 *      the above copyright notice and this notice appears in all
11 *      copies, and that the name of Division Incorporated not be
12 *      used in advertising or publicity pertaining to distribution
13 *      of the software without specific, written prior permission.
14 *      Division Incorporated makes no representations about the
15 *      suitability of this software for any purpose.
16 *
17 *  Description:
18 *      Implementation of hooks for the CYGNUS newlib libc
19 *      These hooks set things up so that:
20 *              '_REENT' is switched at task switch time.
21 *
22 *
23 *  TODO:
24 *
25 *  NOTE:
26 *
27 *  $Id$
28 *
29 */
30
31#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
32#include <rtems.h>
33#include <libcsupport.h>
34#include <stdlib.h>             /* for free() */
35#include <string.h>             /* for memset() */
36
37#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
38
39/*
40 *  NOTE: When using RTEMS fake stat, fstat, and isatty, all output
41 *        is line buffered so this setvbuf is not necessary.  This
42 *        setvbuf insures that we can redirect the output of a test
43 *        on the UNIX simulator and it is in the same order as for a
44 *        real target.
45 *  NOTE:
46 *        There is some problem with doing this on the hpux version
47 *        of the UNIX simulator (symptom is printf core dumps), so
48 *        we just don't for now.
49 *        Not sure if this is a problem with hpux, newlib, or something else.
50 */
51 
52#if defined(RTEMS_UNIX) && !defined(hpux)
53#define NEED_SETVBUF
54#endif
55 
56#ifdef NEED_SETVBUF
57#include <stdio.h>
58#endif
59
60#include "internal.h"
61
62#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
63
64
65int              libc_reentrant;        /* do we think we are reentrant? */
66struct _reent    libc_global_reent = _REENT_INIT(libc_global_reent);;
67
68/*
69 * CYGNUS newlib routine that does atexit() processing and flushes
70 *      stdio streams
71 *      undocumented
72 */
73
74extern void _wrapup_reent(struct _reent *);
75extern void _reclaim_reent(struct _reent *);
76
77void
78libc_wrapup(void)
79{
80    _wrapup_reent(0);
81    if (_REENT != &libc_global_reent)
82    {
83        _wrapup_reent(&libc_global_reent);
84#if 0
85        /* don't reclaim this one, just in case we do printfs */
86        /* on our way out to ROM */
87        _reclaim_reent(&libc_global_reent);
88#endif
89        _REENT = &libc_global_reent;
90    }
91}
92
93
94rtems_boolean
95libc_create_hook(rtems_tcb *current_task,
96                 rtems_tcb *creating_task)
97{
98    MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
99    return TRUE;
100}
101
102/*
103 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
104 */
105
106rtems_extension
107libc_start_hook(rtems_tcb *current_task,
108                rtems_tcb *starting_task)
109{
110    struct _reent *ptr;
111
112    /* NOTE: our malloc is reentrant without a reent ptr since
113     *  it is based on region manager
114     */
115
116    ptr = (struct _reent *) malloc(sizeof(struct _reent));
117
118    /* GCC extension: structure constants */
119    *ptr = (struct _reent) _REENT_INIT((*ptr));
120
121    MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
122}
123
124/*
125 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
126 *
127 *  NOTE: When using RTEMS fake stat, fstat, and isatty, all output
128 *        is line buffered so this setvbuf is not necessary.  This
129 *        setvbuf insures that we can redirect the output of a test
130 *        on the UNIX simulator and it is in the same order as for a
131 *        real target.
132 */
133 
134#ifdef NEED_SETVBUF
135rtems_extension
136libc_begin_hook(rtems_tcb *current_task)
137{
138  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
139}
140#endif
141
142rtems_extension
143libc_switch_hook(rtems_tcb *current_task,
144                 rtems_tcb *heir_task)
145{
146    rtems_unsigned32 impure_value;
147
148    /* XXX We can't use rtems_task_set_note() here since SYSI task has a
149     * tid of 0, which is treated specially (optimized, actually)
150     * by rtems_task_set_note
151     *
152     * NOTE:  The above comment is no longer true and we need to use
153     *        the extension data areas added about the same time.
154     */
155
156    /*
157     *  Don't touch the outgoing task if it has been deleted.
158     */
159
160    if ( !_States_Is_transient( current_task->current_state ) ) {
161      impure_value = (rtems_unsigned32) _REENT;
162      MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
163    }
164
165    _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
166
167}
168
169/*
170 *  Function:   libc_delete_hook
171 *  Created:    94/12/10
172 *
173 *  Description:
174 *      Called when a task is deleted.
175 *      Must restore the new lib reentrancy state for the new current
176 *      task.
177 *
178 *  Parameters:
179 *
180 *
181 *  Returns:
182 *
183 *
184 *  Side Effects:
185 *
186 *  Notes:
187 *
188 *
189 *  Deficiencies/ToDo:
190 *
191 *
192 */
193rtems_extension
194libc_delete_hook(rtems_tcb *current_task,
195                 rtems_tcb *deleted_task)
196{
197    struct _reent *ptr;
198
199    /*
200     * The reentrancy structure was allocated by newlib using malloc()
201     */
202
203    if (current_task == deleted_task)
204    {
205      ptr = _REENT;
206    }
207    else
208    {
209      ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
210    }
211
212    /* if (ptr) */
213    if (ptr && ptr != &libc_global_reent)
214    {
215      _wrapup_reent(ptr);
216      _reclaim_reent(ptr);
217      free(ptr);
218    }
219
220    MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
221
222    /*
223     * Require the switch back to another task to install its own
224     */
225
226    if (current_task == deleted_task)
227    {
228      _REENT = 0;
229    }
230}
231
232/*
233 *  Function:   libc_init
234 *  Created:    94/12/10
235 *
236 *  Description:
237 *      Init libc for CYGNUS newlib
238 *      Set up _REENT to use our global libc_global_reent.
239 *      (newlib provides a global of its own, but we prefer our
240 *      own name for it)
241 *
242 *      If reentrancy is desired (which it should be), then
243 *      we install the task extension hooks to maintain the
244 *      newlib reentrancy global variable _REENT on task
245 *      create, delete, switch, exit, etc.
246 *
247 *  Parameters:
248 *      reentrant               non-zero if reentrant library desired.
249 *
250 *  Returns:
251 *
252 *  Side Effects:
253 *      installs libc extensions if reentrant.
254 *
255 *  Notes:
256 *
257 *
258 *  Deficiencies/ToDo:
259 *
260 */
261
262void
263libc_init(int reentrant)
264{
265    rtems_extensions_table  libc_extension;
266    rtems_id                extension_id;
267    rtems_status_code       rc;
268
269    _REENT = &libc_global_reent;
270
271    if (reentrant)
272    {
273        memset(&libc_extension, 0, sizeof(libc_extension));
274
275        libc_extension.thread_create  = libc_create_hook;
276        libc_extension.thread_start   = libc_start_hook;
277#ifdef NEED_SETVBUF
278        libc_extension.thread_begin   = libc_begin_hook;
279#endif
280        libc_extension.thread_switch  = libc_switch_hook;
281        libc_extension.thread_delete  = libc_delete_hook;
282
283        rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
284                              &libc_extension, &extension_id);
285        if (rc != RTEMS_SUCCESSFUL)
286            rtems_fatal_error_occurred(rc);
287
288        libc_reentrant = reentrant;
289    }
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
327#else
328
329void exit(int status)
330{
331    libc_wrapup();
332    rtems_shutdown_executive(status);
333}
334#endif
335
336
337/*
338 *  These are directly supported (and completely correct) in the posix api.
339 */
340
341#ifndef RTEMS_POSIX_API
342
343#include <assert.h>
344
345pid_t __getpid(void)
346{
347  assert( 0 );
348  return 0;
349}
350
351int __kill( pid_t pid, int sig )
352{
353  assert( 0 );
354  return 0;
355}
356
357unsigned int sleep(
358  unsigned int seconds
359)
360{
361  rtems_status_code status;
362  rtems_interval    ticks_per_second;
363  rtems_interval    ticks;
364 
365  status = rtems_clock_get(
366    RTEMS_CLOCK_GET_TICKS_PER_SECOND,
367    &ticks_per_second
368  );
369 
370  ticks = seconds * ticks_per_second;
371 
372  status = rtems_task_wake_after( ticks );
373 
374  /*
375   *  Returns the "unslept" amount of time.  In RTEMS signals are not
376   *  interruptable, so tasks really sleep all of the requested time.
377   */
378 
379  return 0;
380}
381
382#endif
383
384#endif
Note: See TracBrowser for help on using the repository browser.