OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libcsupport/] [src/] [newlibc.c] - Blame information for rev 1026

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
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.OARcorp.com/rtems/license.html.
11
 *
12
 *  newlibc.c,v 1.41 2002/05/15 16:29:05 joel Exp
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
#include <stdlib.h>             /* for free() */
26
#include <string.h>             /* for memset() */
27
 
28
#include <sys/reent.h>          /* for extern of _REENT (aka _impure_ptr) */
29
#include <errno.h>
30
 
31
/*
32
 *  NOTE:
33
 *        There is some problem with doing this on the hpux version
34
 *        of the UNIX simulator (symptom is printf core dumps), so
35
 *        we just don't for now.
36
 *        Not sure if this is a problem with hpux, newlib, or something else.
37
 */
38
 
39
#if defined(RTEMS_UNIX) && !defined(hpux)
40
#define NEED_SETVBUF
41
#endif
42
 
43
#ifdef NEED_SETVBUF
44
#include <stdio.h>
45
#endif
46
 
47
int              libc_reentrant;        /* do we think we are reentrant? */
48
struct _reent    libc_global_reent;
49
 
50
/*
51
 * CYGNUS newlib routine that does atexit() processing and flushes
52
 *      stdio streams
53
 *      undocumented
54
 */
55
 
56
extern void _wrapup_reent(struct _reent *);
57
extern void _reclaim_reent(struct _reent *);
58
 
59
#include <stdio.h>
60
 
61
void libc_wrapup(void)
62
{
63
  /*
64
   *  In case RTEMS is already down, don't do this.  It could be
65
   *  dangerous.
66
   */
67
 
68
  if (!_System_state_Is_up(_System_state_Get()))
69
     return;
70
 
71
  /*
72
   *  This was already done if the user called exit() directly .
73
  _wrapup_reent(0);
74
   */
75
 
76
  if (_REENT != &libc_global_reent) {
77
      _wrapup_reent(&libc_global_reent);
78
#if 0
79
      /*  Don't reclaim this one, just in case we do printfs
80
       *  on the way out to ROM.
81
       */
82
      _reclaim_reent(&libc_global_reent);
83
#endif
84
      _REENT = &libc_global_reent;
85
  }
86
 
87
  /*
88
   * Try to drain output buffers.
89
   *
90
   * Should this be changed to do *all* file streams?
91
   *    _fwalk (_REENT, fclose);
92
   */
93
 
94
  fclose (stdin);
95
  fclose (stdout);
96
  fclose (stderr);
97
}
98
 
99
 
100
rtems_boolean libc_create_hook(
101
  rtems_tcb *current_task,
102
  rtems_tcb *creating_task
103
)
104
{
105
  creating_task->libc_reent = NULL;
106
  return TRUE;
107
}
108
 
109
/*
110
 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
111
 */
112
 
113
rtems_extension libc_start_hook(
114
  rtems_tcb *current_task,
115
  rtems_tcb *starting_task
116
)
117
{
118
  struct _reent *ptr;
119
 
120
  /*  NOTE: The RTEMS malloc is reentrant without a reent ptr since
121
   *        it is based on the Classic API Region Manager.
122
   */
123
 
124
  ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
125
 
126
  if (!ptr)
127
     rtems_fatal_error_occurred(RTEMS_NO_MEMORY);
128
 
129
#ifdef __GNUC__
130
  /* GCC extension: structure constants */
131
  *ptr = (struct _reent) _REENT_INIT((*ptr));
132
#else
133
  /*
134
   *  WARNING: THIS IS VERY DEPENDENT ON NEWLIB!!!
135
   *           Last visual check was against newlib 1.8.2 but last known
136
   *           use was against 1.7.0.  This is basically an exansion of
137
   *           REENT_INIT() in <sys/reent.h>.
138
   *  NOTE:    calloc() takes care of zeroing fields.
139
   */
140
  ptr->_stdin = &ptr->__sf[0];
141
  ptr->_stdout = &ptr->__sf[1];
142
  ptr->_stderr = &ptr->__sf[2];
143
  ptr->_current_locale = "C";
144
  ptr->_new._reent._rand_next = 1;
145
#endif
146
 
147
  starting_task->libc_reent = ptr;
148
}
149
 
150
/*
151
 * Called for all user TASKS (system tasks are MPCI Receive Server and IDLE)
152
 */
153
 
154
#ifdef NEED_SETVBUF
155
rtems_extension libc_begin_hook(rtems_tcb *current_task)
156
{
157
  setvbuf( stdout, NULL, _IOLBF, BUFSIZ );
158
}
159
#endif
160
 
161
/*
162
 *  Function:   libc_delete_hook
163
 *  Created:    94/12/10
164
 *
165
 *  Description:
166
 *      Called when a task is deleted.
167
 *      Must restore the new lib reentrancy state for the new current
168
 *      task.
169
 *
170
 *  Parameters:
171
 *
172
 *
173
 *  Returns:
174
 *
175
 *
176
 *  Side Effects:
177
 *
178
 *  Notes:
179
 *
180
 *
181
 *  Deficiencies/ToDo:
182
 *
183
 *
184
 */
185
 
186
rtems_extension libc_delete_hook(
187
  rtems_tcb *current_task,
188
  rtems_tcb *deleted_task
189
)
190
{
191
  struct _reent *ptr;
192
 
193
  /*
194
   * The reentrancy structure was allocated by newlib using malloc()
195
   */
196
 
197
  if (current_task == deleted_task) {
198
    ptr = _REENT;
199
  } else {
200
    ptr = (struct _reent *) deleted_task->libc_reent;
201
  }
202
 
203
  /* if (ptr) */
204
  if (ptr && ptr != &libc_global_reent) {
205
    _wrapup_reent(ptr);
206
    _reclaim_reent(ptr);
207
    free(ptr);
208
  }
209
 
210
  deleted_task->libc_reent = NULL;
211
 
212
  /*
213
   * Require the switch back to another task to install its own
214
   */
215
 
216
  if ( current_task == deleted_task ) {
217
    _REENT = 0;
218
  }
219
}
220
 
221
/*
222
 *  Function:   libc_init
223
 *  Created:    94/12/10
224
 *
225
 *  Description:
226
 *      Init libc for CYGNUS newlib
227
 *      Set up _REENT to use our global libc_global_reent.
228
 *      (newlib provides a global of its own, but we prefer our
229
 *      own name for it)
230
 *
231
 *      If reentrancy is desired (which it should be), then
232
 *      we install the task extension hooks to maintain the
233
 *      newlib reentrancy global variable _REENT on task
234
 *      create, delete, switch, exit, etc.
235
 *
236
 *  Parameters:
237
 *      reentrant               non-zero if reentrant library desired.
238
 *
239
 *  Returns:
240
 *
241
 *  Side Effects:
242
 *      installs libc extensions if reentrant.
243
 *
244
 *  Notes:
245
 *
246
 *
247
 *  Deficiencies/ToDo:
248
 *
249
 */
250
 
251
void
252
libc_init(int reentrant)
253
{
254
  rtems_extensions_table  libc_extension;
255
  rtems_status_code       rc;
256
  rtems_id                extension_id;
257
 
258
  libc_global_reent = (struct _reent) _REENT_INIT((libc_global_reent));
259
  _REENT = &libc_global_reent;
260
 
261
  if (reentrant) {
262
    memset(&libc_extension, 0, sizeof(libc_extension));
263
 
264
    libc_extension.thread_create  = libc_create_hook;
265
    libc_extension.thread_start   = libc_start_hook;
266
#ifdef NEED_SETVBUF
267
    libc_extension.thread_begin   = libc_begin_hook;
268
#endif
269
    libc_extension.thread_delete  = libc_delete_hook;
270
 
271
    _Thread_Set_libc_reent ((void**) &_REENT);
272
 
273
    rc = rtems_extension_create(rtems_build_name('L', 'I', 'B', 'C'),
274
                          &libc_extension, &extension_id);
275
    if (rc != RTEMS_SUCCESSFUL)
276
      rtems_fatal_error_occurred( rc );
277
 
278
    libc_reentrant = reentrant;
279
  }
280
}
281
 
282
/*
283
 *  Function:   _exit
284
 *  Created:    94/12/10
285
 *
286
 *  Description:
287
 *      Called from exit() after it does atexit() processing and stdio fflush's
288
 *
289
 *      called from bottom of exit() to really delete the task.
290
 *      If we are using reentrant libc, then let the delete extension
291
 *      do all the work, otherwise if a shutdown is in progress,
292
 *      then just do it.
293
 *
294
 *  Parameters:
295
 *      exit status
296
 *
297
 *  Returns:
298
 *      does not return
299
 *
300
 *  Side Effects:
301
 *
302
 *  Notes:
303
 *
304
 *
305
 *  Deficiencies/ToDo:
306
 *
307
 *
308
 */
309
 
310
#include <unistd.h>
311
 
312
#if !defined(RTEMS_UNIX)
313
void _exit(int status)
314
{
315
  /*
316
   *  We need to do the exit processing on the global reentrancy structure.
317
   *  This has already been done on the per task reentrancy structure
318
   *  associated with this task.
319
   */
320
 
321
  libc_wrapup();
322
  rtems_shutdown_executive(status);
323
}
324
 
325
#else
326
 
327
void exit(int status)
328
{
329
  libc_wrapup();
330
  rtems_shutdown_executive(status);
331
}
332
#endif
333
 
334
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.