source: rtems/c/src/lib/libc/newlibc.c @ a5cb673

4.104.114.84.95
Last change on this file since a5cb673 was c796ea9, checked in by Joel Sherrill <joel.sherrill@…>, on 04/06/98 at 15:57:58

More stuff removed as a result of using newlib's isatty() implementation.
These were noticed by Eric Norum.

  • Property mode set to 100644
File size: 8.6 KB
Line 
1
2/*
3 *  COPYRIGHT (c) 1994 by Division Incorporated
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.OARcorp.com/rtems/license.html.
8 *
9 *  Description:
10 *      Implementation of hooks for the CYGNUS newlib libc
11 *      These hooks set things up so that:
12 *              '_REENT' is switched at task switch time.
13 *
14 *
15 *  TODO:
16 *
17 *  NOTE:
18 *
19 *  $Id$
20 *
21 */
22
23#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
24#include <rtems.h>
25
26#if defined(RTEMS_NEWLIB)
27#include <libcsupport.h>
28#include <stdlib.h>             /* for free() */
29#include <string.h>             /* for memset() */
30
31#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
32#include <errno.h>
33
34/*
35 *  NOTE:
36 *        There is some problem with doing this on the hpux version
37 *        of the UNIX simulator (symptom is printf core dumps), so
38 *        we just don't for now.
39 *        Not sure if this is a problem with hpux, newlib, or something else.
40 */
41 
42#if defined(RTEMS_UNIX) && !defined(hpux)
43#define NEED_SETVBUF
44#endif
45 
46#ifdef NEED_SETVBUF
47#include <stdio.h>
48#endif
49
50#include "internal.h"
51
52#define LIBC_NOTEPAD RTEMS_NOTEPAD_LAST
53
54
55int              libc_reentrant;        /* do we think we are reentrant? */
56struct _reent    libc_global_reent = _REENT_INIT(libc_global_reent);
57
58/*
59 * CYGNUS newlib routine that does atexit() processing and flushes
60 *      stdio streams
61 *      undocumented
62 */
63
64extern void _wrapup_reent(struct _reent *);
65extern void _reclaim_reent(struct _reent *);
66
67void
68libc_wrapup(void)
69{
70    /*
71     *  In case RTEMS is already down, don't do this.  It could be
72     *  dangerous.
73     */
74
75    if (!_System_state_Is_up(_System_state_Get()))
76       return;
77
78    _wrapup_reent(0);
79    if (_REENT != &libc_global_reent)
80    {
81        _wrapup_reent(&libc_global_reent);
82#if 0
83        /* don't reclaim this one, just in case we do printfs */
84        /* on our way out to ROM */
85        _reclaim_reent(&libc_global_reent);
86#endif
87        _REENT = &libc_global_reent;
88    }
89}
90
91
92rtems_boolean
93libc_create_hook(rtems_tcb *current_task,
94                 rtems_tcb *creating_task)
95{
96    MY_task_set_note(creating_task, LIBC_NOTEPAD, 0);
97    return TRUE;
98}
99
100/*
101 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
102 */
103
104rtems_extension
105libc_start_hook(rtems_tcb *current_task,
106                rtems_tcb *starting_task)
107{
108    struct _reent *ptr;
109
110    /* NOTE: our malloc is reentrant without a reent ptr since
111     *  it is based on region manager
112     */
113
114    ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
115
116    if (!ptr)
117       rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
118 
119#ifdef __GNUC__
120    /* GCC extension: structure constants */
121    *ptr = (struct _reent) _REENT_INIT((*ptr));
122#else
123    /*
124     *  Warning: THIS IS VERY DEPENDENT ON NEWLIB!!! WRITTEN FOR 1.7.0
125     */
126    ptr->_errno=0;
127    ptr->_stdin=&ptr->__sf[0];
128    ptr->_stdout=&ptr->__sf[1];
129    ptr->_stderr=&ptr->__sf[2];
130    ptr->_scanpoint=0;
131    ptr->_asctime[0]=0;
132    ptr->_next=1;
133    ptr->__sdidinit=0;
134#endif
135
136    MY_task_set_note(starting_task, LIBC_NOTEPAD, (rtems_unsigned32) ptr);
137}
138
139/*
140 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
141 */
142 
143#ifdef NEED_SETVBUF
144rtems_extension
145libc_begin_hook(rtems_tcb *current_task)
146{
147  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
148}
149#endif
150
151rtems_extension
152libc_switch_hook(rtems_tcb *current_task,
153                 rtems_tcb *heir_task)
154{
155    rtems_unsigned32 impure_value;
156
157    /* XXX We can't use rtems_task_set_note() here since SYSI task has a
158     * tid of 0, which is treated specially (optimized, actually)
159     * by rtems_task_set_note
160     *
161     * NOTE:  The above comment is no longer true and we need to use
162     *        the extension data areas added about the same time.
163     */
164
165    /*
166     *  Don't touch the outgoing task if it has been deleted.
167     */
168
169    if ( !_States_Is_transient( current_task->current_state ) ) {
170      impure_value = (rtems_unsigned32) _REENT;
171      MY_task_set_note(current_task, LIBC_NOTEPAD, impure_value);
172    }
173
174    _REENT = (struct _reent *) MY_task_get_note(heir_task, LIBC_NOTEPAD);
175
176}
177
178/*
179 *  Function:   libc_delete_hook
180 *  Created:    94/12/10
181 *
182 *  Description:
183 *      Called when a task is deleted.
184 *      Must restore the new lib reentrancy state for the new current
185 *      task.
186 *
187 *  Parameters:
188 *
189 *
190 *  Returns:
191 *
192 *
193 *  Side Effects:
194 *
195 *  Notes:
196 *
197 *
198 *  Deficiencies/ToDo:
199 *
200 *
201 */
202rtems_extension
203libc_delete_hook(rtems_tcb *current_task,
204                 rtems_tcb *deleted_task)
205{
206    struct _reent *ptr;
207
208    /*
209     * The reentrancy structure was allocated by newlib using malloc()
210     */
211
212    if (current_task == deleted_task)
213    {
214      ptr = _REENT;
215    }
216    else
217    {
218      ptr = (struct _reent *) MY_task_get_note(deleted_task, LIBC_NOTEPAD);
219    }
220
221    /* if (ptr) */
222    if (ptr && ptr != &libc_global_reent)
223    {
224      _wrapup_reent(ptr);
225      _reclaim_reent(ptr);
226      free(ptr);
227    }
228
229    MY_task_set_note(deleted_task, LIBC_NOTEPAD, 0);
230
231    /*
232     * Require the switch back to another task to install its own
233     */
234
235    if (current_task == deleted_task)
236    {
237      _REENT = 0;
238    }
239}
240
241/*
242 *  Function:   libc_init
243 *  Created:    94/12/10
244 *
245 *  Description:
246 *      Init libc for CYGNUS newlib
247 *      Set up _REENT to use our global libc_global_reent.
248 *      (newlib provides a global of its own, but we prefer our
249 *      own name for it)
250 *
251 *      If reentrancy is desired (which it should be), then
252 *      we install the task extension hooks to maintain the
253 *      newlib reentrancy global variable _REENT on task
254 *      create, delete, switch, exit, etc.
255 *
256 *  Parameters:
257 *      reentrant               non-zero if reentrant library desired.
258 *
259 *  Returns:
260 *
261 *  Side Effects:
262 *      installs libc extensions if reentrant.
263 *
264 *  Notes:
265 *
266 *
267 *  Deficiencies/ToDo:
268 *
269 */
270
271void
272libc_init(int reentrant)
273{
274    rtems_extensions_table  libc_extension;
275    rtems_id                extension_id;
276    rtems_status_code       rc;
277
278    _REENT = &libc_global_reent;
279
280    if (reentrant)
281    {
282        memset(&libc_extension, 0, sizeof(libc_extension));
283
284        libc_extension.thread_create  = libc_create_hook;
285        libc_extension.thread_start   = libc_start_hook;
286#ifdef NEED_SETVBUF
287        libc_extension.thread_begin   = libc_begin_hook;
288#endif
289        libc_extension.thread_switch  = libc_switch_hook;
290        libc_extension.thread_delete  = libc_delete_hook;
291
292        rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
293                              &libc_extension, &extension_id);
294        if (rc != RTEMS_SUCCESSFUL)
295            rtems_fatal_error_occurred(rc);
296
297        libc_reentrant = reentrant;
298    }
299}
300
301#if 0
302/*
303 *  Routines required by the gnat runtime.
304 */
305
306int get_errno()
307{
308  return errno;
309}
310#endif
311
312/*
313 *  Function:   _exit
314 *  Created:    94/12/10
315 *
316 *  Description:
317 *      Called from exit() after it does atexit() processing and stdio fflush's
318 *
319 *      called from bottom of exit() to really delete the task.
320 *      If we are using reentrant libc, then let the delete extension
321 *      do all the work, otherwise if a shutdown is in progress,
322 *      then just do it.
323 *
324 *  Parameters:
325 *      exit status
326 *
327 *  Returns:
328 *      does not return
329 *
330 *  Side Effects:
331 *
332 *  Notes:
333 *
334 *
335 *  Deficiencies/ToDo:
336 *
337 *
338 */
339
340#include <stdio.h>
341
342/* #if !defined(RTEMS_UNIX) && !defined(__GO32__) && !defined(_AM29K) */
343#if !defined(RTEMS_UNIX) && !defined(_AM29K)
344#if !defined(pc386)
345void _exit(int status)
346{
347    libc_wrapup(); /* Why? XXX */
348    rtems_shutdown_executive(status);
349}
350#endif
351
352#else
353
354void exit(int status)
355{
356    libc_wrapup();
357    rtems_shutdown_executive(status);
358}
359#endif
360
361
362/*
363 *  These are directly supported (and completely correct) in the posix api.
364 */
365
366pid_t __getpid(void)
367{
368  return getpid();
369}
370
371/* #if !defined(RTEMS_POSIX_API) || defined(__GO32__) */
372#if !defined(RTEMS_POSIX_API)
373pid_t getpid(void)
374{
375  return (0);
376}
377#endif
378
379/* #if !defined(RTEMS_POSIX_API) || defined(__GO32__) */
380#if !defined(RTEMS_POSIX_API)
381int kill( pid_t pid, int sig )
382{
383  return 0;
384}
385#endif
386
387int __kill( pid_t pid, int sig )
388{
389  return 0;
390}
391
392#if !defined(RTEMS_POSIX_API)
393unsigned int sleep(
394  unsigned int seconds
395)
396{
397  rtems_status_code status;
398  rtems_interval    ticks_per_second;
399  rtems_interval    ticks;
400 
401  status = rtems_clock_get(
402    RTEMS_CLOCK_GET_TICKS_PER_SECOND,
403    &ticks_per_second
404  );
405 
406  ticks = seconds * ticks_per_second;
407 
408  status = rtems_task_wake_after( ticks );
409 
410  /*
411   *  Returns the "unslept" amount of time.  In RTEMS signals are not
412   *  interruptable, so tasks really sleep all of the requested time.
413   */
414 
415  return 0;
416}
417#endif
418
419
420#endif
Note: See TracBrowser for help on using the repository browser.