Queries concerning RTOS protection in newllib
Antony KING
antony.king@st.com
Thu Jun 17 19:36:00 GMT 2004
Corinna Vinschen wrote:
> On Jun 17 14:32, Antony KING wrote:
snip
>
> As I said, reverting _GLOBAL_REENT to _impure_ptr restores the correct
> behaviour again. I still don't quite understand the invention of
> _global_impure_ptr. _GLOBAL_REENT is used a lot in newlib and due to
> it's redefinition to another global variable, all this functionality
> is potentially accessing the wrong datastructure. If you actually
> need a never changing _global_impure_ptr, then that's ok, but it shouldn't
> be used by default from all these functions and therefore not be defined
> as _GLOBAL_REENT, should it?
>
>
> Corinna
The reason for introducing a _global_impure_ptr was because from my
interpretation of the use of _GLOBAL_REENT it seemed to be intended to
be used as the single data structure (shared across tasks) for the
purpose of:
* the management of FILE objects, other than stdin, stdout and stderr,
which are still unique to each task;
* and for the management of atexit handlers.
This can be observed from the fact that _GLOBAL_REENT is only referenced
from the functions involved in these activities:
libc/stdio/findfp.c (__sfp, _cleanup)
libc/stdio/fcloseall.c (fcloseall)
libc/stdio/fflush.c (fflush)
libc/stdio/refill.c (__srefill)
libc/stdlib/atexit.c (atexit)
libc/stdlib/on_exit.c (on_exit)
libc/stdlib/exit.c (exit)
and is guaranteed thread safe via the protection accorded by the use of
the __sfp_lock_acquire/release functions.
Therefore in a multi-threaded system where _REENT is mapped to a global
variable (i.e. _impure_ptr) and changed on each context switch, if
_GLOBAL_REENT is also mapped to the same variable then that will also be
changed on each context switch as well. This will break the above
expectation that a single unchanging reentrancy object is used for the
management of the above resources (with the consequence that FILE
objects and atexit handlers may be distributed across multiple task
specific reentrancy objects).
As a result of the above observations I introduced a _global_reent_ptr
variable which initially points to the same object as _impure_ptr (in
the default newlib implementation) and also changed the definition of
_GLOBAL_REENT to refer to this variable instead of _impure_ptr. Now when
a task switch occurs _GLOBAL_REENT will still refer to the same object
instead of a potentially different reentrancy object referenced by
_impure_ptr.
The RTOS that I am using is a fairly typical embedded RTOS which is
linked into the application. In this implementation the main thread uses
the initial reentrancy object defined by newlib (in libc/reent/impure.c)
and referenced to by both _impure_ptr and _global_impure_ptr. When new
tasks are created each will be allocated their own reentrancy object
which will be referenced by _impure_ptr after each context switch. Only
when the main thread is the current task is _impure_ptr the same as
_global_impure_ptr. This scheme allows for the RTOS to be shut down and
restore the reentrancy structures to their initial state.
In a non multi-tasking system the introduction of a new variable should
be invisible since _impure_ptr should never change from its initial
value and so both _impure_ptr and _global_impure_ptr will always refer
to the same object.
Of course this change has broken Cygwin's use of reentrancy structures
since it seems that its manipulation of _impure_ptr and the meaning of
_GLOBAL_REENT is different from the embedded RTOS that I am working on.
Hence the proposal to conditionally define _GLOBAL_REENT to _impure_ptr
if using newlib under Cygwin.
I hope this interpretation has not rambled on too much...
Cheers,
Antony.
--
-----------------------------------------------------------------
Antony King | Email: antony.king@st.com
STMicroelectronics (R&D) Ltd. |
Bristol, BS32 4SQ. United Kingdom. | Tel: +44 (0)1454 462646
More information about the Newlib
mailing list