source: rtems/cpukit/libcsupport/src/newlibc.c @ d9d75fc

4.104.114.84.95
Last change on this file since d9d75fc was d9d75fc, checked in by Joel Sherrill <joel.sherrill@…>, on 08/31/98 at 23:06:50

Patch from Emmanuel Raguet <raguet@…>:

I have reworked the ethernet driver for the BSP pc386 and
here is the patch to apply.

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