This is the mail archive of the
newlib@sources.redhat.com
mailing list for the newlib project.
Re: newlib reentrancy question
- To: "J. Johnston" <jjohnstn at cygnus dot com>
- Subject: Re: newlib reentrancy question
- From: Joel Sherrill <joel dot sherrill at OARcorp dot com>
- Date: Wed, 20 Jun 2001 08:27:11 -0500
- CC: newlib at sources dot redhat dot com
- Organization: OAR Corporation
- References: <3B2F5932.313619EE@OARcorp.com> <3B2FFB74.983D671C@cygnus.com>
- Reply-To: joel dot sherrill at OARcorp dot com
"J. Johnston" wrote:
>
> Joel Sherrill wrote:
> >
> > Where's the best description and/or example of how to
> > implement newlib pre-thread reentrancy support these
> > days?
> >
> > I am investigating a case where cout does not work
> > for the 2nd task in a system unless the 1st task
> > uses it. All of the standard C routines work fine.
> > In fact, the printf immediately before the cout calls
> > in the 2nd task prints. The clue I think is that
> > printf does not call fwrite and cout does. Here
> > is how we do the per-task reentrancy structures
> > now.
> >
> > + At system initialization, we use a global struct _reent.
> > It is initialized using _REENT_INIT.
> >
> > + Each task has its own copy of the reent structure.
> >
> > + As part of a context switch the contents of _impure_ptr
> > are switched.
> >
> > + As each task begins execution time, the following code
> > is executed:
> >
> > ptr = (struct _reent *) calloc(1, sizeof(struct _reent));
> > *ptr = (struct _reent) _REENT_INIT((*ptr));
> >
> > What seems to be happening is that the 2nd task gets to
> > CHECK_INIT:
> >
> > #define CHECK_INIT(fp) \
> > do \
> > { \
> > if ((fp)->_data == 0) \
> > (fp)->_data = _REENT; \
> > if (!(fp)->_data->__sdidinit) \
> > __sinit ((fp)->_data); \
> > } \
> > while (0)
> >
> > and it decides to do the copy in the first if. But since
> > _REENT_INIT at task_begin time set __sdidinit to 1, it
> > skips the __sinit portion. Any ideas? Do you think
> > that our per-task initialization should be different
> > and make sure __sdidinit is 0?
> >
> >
>
> Please clarify. The _REENT_INIT macro in newlib/libc/include/sys/reent.h initializes __sdidinit to
> 0. Have you modified this in your copy?
No. But I think I have a better description and narrowing of the
problem.
RTEMS starts with _impure_ptr pointing to libc_global_reent.
In this application, libc_global_reent is never used.
libio apparently grabs the stdout pointer from there
at system initialization time and thus never sees any of the
per thread reent data. So with this sequence of code:
printf uses the per-thread stdout FILE * but cout ends
up using the one from libc_global_reent. newlib gets
confused because the FILE * passed to fwrite() does not
correspond to the one for the task's reent structure.
I think I am technically out of newlib's domain now but
if anyone has ideas on how to fix this correctly, please
pass them along. At this point, I don't know enough
about libio to even know how it is grabbing the FILE *
initially that it plans to use.
This brings to mind a broader question. Is RTEMS the
only target switching the reent structure like this?
Should we be doing something different?
>
> -- Jeff J.
--
Joel Sherrill, Ph.D. Director of Research & Development
joel@OARcorp.com On-Line Applications Research
Ask me about RTEMS: a free RTOS Huntsville AL 35805
Support Available (256) 722-9985