EmbDev.net

Forum: ARM programming with GCC/GNU tools Reentrancy of newlib funktions


von Andrea R. (drea79)


Rate this post
useful
not useful
Hello,

I have a little problem with my system (TMS470 & WinArm-GCC Version
20070505
  & Eclipse). I have a program with min. 9 threads and when it runs in a
debug session it works fine. But when it runs in release version it get
an reset. I have set a breakpoint at my boot up and so I could read the
lr register. When I stop in error I see that impure_data calls my
thread. In the newlib documentation is a descriptionon of reentrancy,
but I don´t understand what I have to do. Needs every thread an own
struct _reent ? How do I call the funktion? Which funktion I have to
call _iprintf_r or iprintf? I couldn't find an example anywhere.
I hope somebody can help me.
Thanks Andrea

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful

von Clifford S. (clifford)


Rate this post
useful
not useful
The reentrancy support in syscalls is primarily to provide a
thread-local copy of errno (otherwise a failing function in one thread
could set a global errno being checked in another thread). If you never
use errno, I don't think you need worry. It is possible to add your own
thread-local data to _reent, but it is not necessary. In my system I
simply do not rely on errno being valid - i.e. I ignore it. And I have
in excess of 40 tasks.

Some standard library functions are inherently non-reentrant because
they use static data, such as strtok(). That is the putpose of
strtok_r() for example.

What makes you suspect that reentrancy is a problem? If the problem
manifests itself when optimization is enabled, it is far more likely
that you have failed to declare some shared data volatile.

You also need to ensure that access to non-atomic shared data is
protected by a mutual exclusion mechanism or is thread-locked.

Clifford

von Andrea R. (drea79)


Rate this post
useful
not useful
I thought, I have a problem with reentrancy, because in debugmode
(optimization is enabled) I saw that my thread was called from
impure_data(). Yesterday I insert for eacht task an own reent struct but
my system still gets a reset :-(
Regrettably I am at a loss.

von Clifford S. (clifford)


Rate this post
useful
not useful
Andrea Runge wrote:
> I thought, I have a problem with reentrancy, because in debugmode
> (optimization is enabled) I saw that my thread was called from
> impure_data(). Yesterday I insert for eacht task an own reent struct but
> my system still gets a reset :-(
> Regrettably I am at a loss.

And about shared data? Is it declared volatile?

You did not say what you were using to implement threads (RTOS or
scheduler oe whatever).

von Clifford S. (clifford)


Rate this post
useful
not useful
A further thoughts, a common cause of crashing in a multi-threaded
application is stack overflow.

How much stack have you allocated to each thread?

Bear in mind that formatted I/O functions such as printf() - and
probably iprintf() too - usually require a relatively large stack (in
excess of 4 Kbytes in my experience). That's a significant amount of
memory on a typical micro controller with on-chip RAM.

The fact that this occurs only when you use optimisation is irrelevant,
since the effect of a stack overflow is entirely non-deterministic, it
depends what gets corrupted and when, and the different memory
organisation and usage patterns in an optimised build will result in
different non-deterministic behaviour. It was just as likely to be the
other way around.

The fact that your thread appears to be called from an unlikely source
is a fair indicator of stack corruption.

Clifford

von Andrea R. (drea79)


Rate this post
useful
not useful
At next I'll prove my shared data again. Maybe I have forgot anyone.
I use FreeRtos to implement threads. My tasks have different stack size
depending on functionality. I use the funktion vTaskList to display the
remain stacksize. A problem is that the TMS470 has only 64k RAM and so
I use an extra extern RAM with 512k RAM. For testing I 'll comment out
all iprintf's.
I hope, I would find the bug soon. In the meantime I feel blue :-(

von Andrea R. (drea79)


Rate this post
useful
not useful
I'm so happy!!! I've comment out all iprintf's and it works :-) One
thread gets a stack overflow.
Many, many thanks!!!!!

von Clifford S. (clifford)


Rate this post
useful
not useful
Andrea Runge wrote:
> I'm so happy!!! I've comment out all iprintf's and it works :-) One
> thread gets a stack overflow.
> Many, many thanks!!!!!

As I said formatted I/O is expensive (and that includes sprintf and the
'v' variants such as vprintf). Some solutions you might consider:

1) Use a 'lean' alternative, of which there are several.

2) Use plain unformatted string output - puts() or a lower level
function, with a few data type specific functions  convert data t
strings.

3) Create a server thread that receives print requests via a message
queue, so that formatted I/O is restricted one thread with a larger
stack, rather than allocating the stack to all threads.

The last suggestion has the benefit of serializing the output so
multiple threads cannot 'interleave' their output. It also has the
advantage - by using fprintf() - of being able to easily redirect the
output to other devices, such as a file system. However the variable
argument list may have to go to simplify installation. The interface
would look rather like VxWorks' logLib:
http://www-kryo.desy.de/documents/vxWorks/V5.4/vxworks/ref/logLib.html

Clifford

von Clifford S. (clifford)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> argument list may have to go to simplify installation. The interface

I meant 'simplify implementation'.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.