source: rtems/c/src/exec/libcsupport/src/newlibc.c @ 8dd1276

4.104.114.84.95
Last change on this file since 8dd1276 was 8dd1276, checked in by Joel Sherrill <joel.sherrill@…>, on 10/05/99 at 19:21:34

Removed go32 ifdefs

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