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
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
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.
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).
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
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 :-(
I'm so happy!!! I've comment out all iprintf's and it works :-) One thread gets a stack overflow. Many, many thanks!!!!!
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
Clifford Slocombe wrote: > argument list may have to go to simplify installation. The interface I meant 'simplify implementation'.