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