source: rtems/cpukit/libcsupport/src/newlibc.c @ 8b08935

4.104.114.95
Last change on this file since 8b08935 was 8b08935, checked in by Joel Sherrill <joel.sherrill@…>, on Aug 5, 2008 at 4:51:45 PM

2008-08-05 Joel Sherrill <joel.sherrill@…>

PR 537/bsps

  • libcsupport/include/rtems/libcsupport.h, libcsupport/src/newlibc.c, libcsupport/src/no_libc.c, libcsupport/src/unixlibc.c: Eliminate vestiges of ticks_per_timeslice controlling newlib reentrancy. The parameter was ignored in libc_init().
  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*
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 *
6 *  COPYRIGHT (c) 1994 by Division Incorporated
7 *
8 *  The license and distribution terms for this file may be
9 *  found in the file LICENSE in this distribution or at
10 *  http://www.rtems.com/license/LICENSE.
11 *
12 *  $Id$
13 *
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
21#include <rtems.h>
22
23#if defined(RTEMS_NEWLIB)
24#include <rtems/libcsupport.h>
25
26/* Since we compile with strict ANSI we need to undef it to get
27 * prototypes for extensions
28 */
29#undef __STRICT_ANSI__
30
31#include <stdlib.h>             /* for free() */
32#include <string.h>             /* for memset() */
33
34#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
35#include <errno.h>
36
37/*
38 *  NOTE:
39 *        There is some problem with doing this on the hpux version
40 *        of the UNIX simulator (symptom is printf core dumps), so
41 *        we just don't for now.
42 *        Not sure if this is a problem with hpux, newlib, or something else.
43 */
44
45#if defined(RTEMS_UNIX) && !defined(hpux)
46#define NEED_SETVBUF
47#endif
48
49#include <stdio.h>
50
51int _fwalk(struct _reent *ptr, int (*function) (FILE *) );
52
53struct _reent    libc_global_reent
54    __ATTRIBUTE_IMPURE_PTR__ = _REENT_INIT(libc_global_reent);
55
56/*
57 * reent struct allocation moved here from libc_start_hook() to avoid
58 * mutual exclusion problems when memory is allocated from the start hook.
59 *
60 * Memory is also now allocated from the workspace rather than the heap.
61 *  -- ptorre 9/30/03
62 */
63rtems_boolean libc_create_hook(
64  rtems_tcb *current_task,
65  rtems_tcb *creating_task
66)
67{
68  struct _reent *ptr;
69
70  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
71   *        it is based on the Classic API Region Manager.
72   */
73
74  #define REENT_MALLOCED 0
75  #if REENT_MALLOCED
76    ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
77  #else
78    /* It is OK to allocate from the workspace because these
79     * hooks run with thread dispatching disabled.
80     */
81    ptr = (struct _reent *) _Workspace_Allocate(sizeof(struct _reent));
82  #endif
83
84  if (ptr) {
85
86      _REENT_INIT_PTR((ptr)); /* GCC extension: structure constants */
87      creating_task->libc_reent = ptr;
88      return TRUE;
89  }
90  else
91    return FALSE;
92}
93
94/*
95 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
96 */
97
98#ifdef NEED_SETVBUF
99rtems_extension libc_begin_hook(rtems_tcb *current_task)
100{
101  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
102}
103#endif
104
105/*
106 *  Called when a task is deleted.
107 *  Must restore the new lib reentrancy state for the new current
108 *  task.
109 *
110 */
111
112int newlib_free_buffers(
113  FILE *fp
114)
115{
116  switch ( fileno(fp) ) {
117    case 0:
118    case 1:
119    case 2:
120      if (fp->_flags & __SMBF) {
121        free( fp->_bf._base );
122        fp->_flags &= ~__SMBF;
123        fp->_bf._base = fp->_p = (unsigned char *) NULL;
124      }
125      break;
126    default:
127     fclose(fp);
128  }
129  return 0;
130}
131
132rtems_extension libc_delete_hook(
133  rtems_tcb *current_task,
134  rtems_tcb *deleted_task
135)
136{
137  struct _reent *ptr;
138
139  /*
140   * The reentrancy structure was allocated by newlib using malloc()
141   */
142
143  if (current_task == deleted_task) {
144    ptr = _REENT;
145  } else {
146    ptr = deleted_task->libc_reent;
147  }
148
149  if (ptr && ptr != &libc_global_reent) {
150/*
151    _wrapup_reent(ptr);
152    _reclaim_reent(ptr);
153*/
154    /*
155     *  Just in case there are some buffers lying around.
156     */
157    _fwalk(ptr, newlib_free_buffers);
158#if REENT_MALLOCED
159    free(ptr);
160#else
161    _Workspace_Free(ptr);
162#endif
163  }
164
165  deleted_task->libc_reent = NULL;
166
167  /*
168   * Require the switch back to another task to install its own
169   */
170
171  if ( current_task == deleted_task ) {
172    _REENT = 0;
173  }
174}
175
176/*
177 *  Init libc for CYGNUS newlib
178 *
179 *  Set up _REENT to use our global libc_global_reent.
180 *  (newlib provides a global of its own, but we prefer our own name for it)
181 *
182 *  If reentrancy is desired (which it should be), then
183 *  we install the task extension hooks to maintain the
184 *  newlib reentrancy global variable _REENT on task
185 *  create, delete, switch, exit, etc.
186 *
187 */
188
189
190void
191libc_init(void)
192{
193  _REENT = &libc_global_reent;
194
195  _Thread_Set_libc_reent (&_REENT);
196}
197
198#endif
Note: See TracBrowser for help on using the repository browser.