This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: Porting 1.14.0 to new OS
- From: Jeff Johnston <jjohnstn at redhat dot com>
- To: Anders Lindgren <ali at df dot lth dot se>
- Cc: newlib at sources dot redhat dot com
- Date: Fri, 14 Jul 2006 14:47:42 -0400
- Subject: Re: Porting 1.14.0 to new OS
- References: <Pine.GSO.4.60.0607131812300.3844@igloo.df.lth.se>
Anders Lindgren wrote:
I am porting newlib to a new OS and have successfully created my own
cross-toolchain and cross-built newlib (with stub syscalls) from within
the GCC build for my new target. Now I am looking into the details of
how to replace the stubs in sys/MyOS with real syscalls, and finishing
things up.
I think I've managed to get my head around most of the configuration
and knobs, but I'd appreciate some help with the details. I am building
a multithreaded newlib, with __DYNAMIC_REENT__ so I don't need to modify
the (single memory space) kernel's thread-switching:
o It is my understanding that some dummy files in newlib should be
overridden by placing files with the same name in my sys/MyOS dir:
reent/impure.c (libc TLS data for "MyOS"), reent/getreent.c
(replace dummy __getreent()) and <sys/lock.h> (dummy lock defines).
Is this the Right(tm) way to implement the multithread support, i.e.
will C files and includes in my sys/MyOS dir override newlib's
corresponding default stubs? Are there other files I need to override?
Yes. Object files of the same name will override the shared newlib ones
(i.e. you can choose to replace with asm or C as long as the object name
ends up the same). Header files are also overridden as you have noted.
I don't recommend overriding impure.c. If your platform doesn't
provide hardware support for TLS via a special register, I would suggest
you consider adding a generic tls pointer to the reentrant struct,
initialized to NULL.
o To skip one layer of indirection, one can supply reentrant
versions of libc syscalls (open, close etc) directly and define
MISSING_SYSCALL_NAMES, make syscall_dir empty in configure.host
(Linux does this?) and thus avoid getting stubs that only call
_open_r etc anyway -- correct? Is there any reason I shouldn't
do this?
No. If you do your syscalls properly, errno in the dynamic reent case
will be set correctly for the thread. A lot of _r stuff is in keeping
track of errno for the thread so you can skip the extra level of
indirection.
o I understand _GLOBAL_REENT is only used to hold truly global data
such as potentially shared FILE pointers that shouldn't be cleaned up
when only a single thread exits, and that my __getreent()
implementation should arrange for each new thread to have its own
_reent structure allocated as needed. This brings up the question of
_impure_ptr, _global_impure_ptr and _reclaim_reent(): I don't quite
understand _reclaim_reent() in reent/reent.c:48 -- _impure_ptr is
referenced explicitly, which seems wrong in a __DYNAMIC_REENT__ newlib.
If it is meant to compare against the global _reent it should've been
_GLOBAL_REENT (or at least _global_reent_ptr) -- but doing so would
effectively turn the cleanup in stdlib/exit.c into a nop? Or is that
what the comment about not returning malloc()'d memory is about?)
o _wrapup_reent()/_reclaim_reent() aren't referenced anywhere afaict. I
take it these are utility routines provided for my convenience, to be
called in my thread implementation's thread-cleanup code?
Yes, you would want to use them there. They aren't referenced anywhere
else.
o I was under the impression that in a __DYNAMIC_REENT__ newlib,
_impure_ptr shouldn't even be defined at all, since all references
to _reents should go through _REENT (== __getreent()) or _GLOBAL_REENT
(which will only equal _impure_ptr in a single-threaded or
!__DYNAMIC_REENT_ newlib). Please explain this relationship between
_impure_ptr, _global_impure_ptr and _reclaim_reent(). It sounds like
a pretty important, race condition prone thing I certainly don't want
to get wrong! :-)
_impure_ptr is useful in startup. It won't get used in the dynamic case
unless your __getreent() chooses to use it as a default (e.g. before any
threads are kicked off from the main thread).
-- Jeff J.
Ok, quite a few questions and clarification points at once, but I hope
you at least find them reasonably informed questions -- I've tried to
dig through the source and mailing lists[0] thoroughly, and appreciate
any answers the list may have -- I really want to understand newlib
internals properly.
[0] And many thanks to Jeff for all of his excellent and patient answers
on the list, which have contributed the bulk of my so far accumulated
understanding of newlib's internals.
Best Regards,
Anders "ali" Lindgren