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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [lib/] [libc/] [newlibc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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