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

4.104.114.84.95
Last change on this file since eb6fafd was eb6fafd, checked in by Joel Sherrill <joel.sherrill@…>, on 01/19/99 at 20:19:22

Per bug report from Jiri Gaisler that RTEMS would no longer build
with the --disable-posix option, stubs for some routines (_getpid_r and
_kill_r) that are normally defined with POSIX were added.

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