query about printf

R

Rahul

Hi Everyone,

I had a query reg printf(). I heard that it can't be used in ISR's
as it is non-re-enterant. I didn't get as to why
printf is non-re-enterant and why non-re-enterant library can't be
used in an ISR?

Thanks in advance ! ! !
 
A

Antoninus Twink

I had a query reg printf(). I heard that it can't be used in ISR's as
it is non-re-enterant. I didn't get as to why printf is
non-re-enterant and why non-re-enterant library can't be used in an
ISR?

I believe POSIX requires the functions that write to streams to be
implemented in a re-entrant way (certainly this will be true if you're
using threads)... In general I don't think the famous ANSI C Standard
(praise be upon it!) insists on it. It's easy to imagine an
implementation of printf() that used a static internal buffer to build
up the string before sending it to stdout, for example.

If you call a non-reentrant function from an ISR, what if the code you
interrupted was another call to the same function? You'd likely corrupt
both the interrupted function's data and the data in the function called
by your ISR.

In any case, calling printf() in an ISR is almost certainly a mistake,
reentrant or not. Latency considerations mean that you really don't want
to be calling big bloated functions like printf() inside an ISR - you
would be blocking further interrupts for far too long.
 
J

Jens Thoms Toerring

Rahul said:
What is the buffer is allocated on heap or declared as a local
varaible?

A non-static local variable shouldn't pose a problem. But
static (even local) variables aren't safe. If a call of
printf() gets interrupted by an ISR (or a signal or what-
ever asynchronous events there could be) and the handler
function itself uses printf() then a static buffer may
get overwritten by this new call and left in a state so
that it can't be used safely anymore by the original call
of printf() to which the program finally will get back.

But it's not only a problem with a static buffers.
printf() also could call malloc() and when, during the
execution of malloc() an asynchronous handler gets in-
voked that also calls malloc() or some related function
directly or indirectly, the whole memory allocation sys-
tem can get into a random state. Strange and nearly im-
possible to reproduce bugs would rather likely be the
result. So better check each and every function you use
in a handler for an asynchronous event that it is expli-
citely documented to be safe to use under such circum-
stances. That not means just thread-safety since in
threads the implementors can employ locking schemes etc.,
you need functions that are safe for use in signal hand-
lers. If a function isn't assume that it can't be used.

Regards, Jens
 
R

Rahul

(I guess you mean "what if.")

Wherever the buffer resides, characters destined for
output must pass through it. If it's statically allocated
or dynamically allocated, both the interrupted and the
interrupting activity need to deposit characters in it,
update a where-does-the-next-character-go indicator, and
decide whether to flush the contents. Unless all that can
be done uninterruptably, printf() is non-reentrant.

I hadn't considered an `auto' buffer, because it would
go out of existence when printf() returned to its caller.
It's possible that a printf() implementation could use such
a buffer, filling it during the call and draining it just
before the return. If it did so -- and if all the machinery
of draining the buffer to stdout was also re-entrant -- then
the worst that would happen would be that the output from
the interrupting printf() could appear in the middle of a
bunch of output from the interrupted printf():

Helloinvalid sense word 0xbadd
, world!

But that's an uncomfortably long chain of "ifs" to rely on,
especially since such a buffer is not the kind whose use is
suggested by the setbuf() and setvbuf() functions. (The
implementation need not "do anything" in response to those
calls, but their existence hints at a buffering regime that
uses longer-lived buffers.)

If i'm correct, the ISR runs as a part of the operating system (kernel
task) and other tasks might call printf function. Lets assume this
version of printf uses a static buffer or a global buffer. In any
case, wouldn't the printf get linked into both these tasks?
Wouldn't both these tasks have their own version of the static or
global variable?

If so, then i don't see any reason for conflict, (yes, it might be
a problem in multi-threaded task). Also that it wouldn't matter if
printf is implemented as a static or dynamic library?

Thanks in advance ! ! !
 
C

Chris Torek

[regarding reentrancy, or lack thereof, in printf implementations]

Wherever the buffer resides, characters destined for
output must pass through it. If it's statically allocated
or dynamically allocated, both the interrupted and the
interrupting activity need to deposit characters in it,
update a where-does-the-next-character-go indicator, and
decide whether to flush the contents. Unless all that can
be done uninterruptably, printf() is non-reentrant.

In my stdio, fprintf() (and hence printf()) is indeed non-reentrant,
in general.
I hadn't considered an `auto' buffer, because it would
go out of existence when printf() returned to its caller.
It's possible that a printf() implementation could use such
a buffer, filling it during the call and draining it just
before the return.

In my stdio, fprintf() does exactly this under some circumstances,
as an efficiency hack. However, it remains non-reentrant. In
particular, calling (f)printf from a signal handler can result in
slightly odd behavior (exactly "how odd" depends on how much the
compiler rearranges the adjustment of various "FILE" elements,
which in turn depends on machine architecture -- normally the bad
cases occur when "fp->_w--" or "*fp->_p++" gets interrupted in the
middle of a load/adjust/store sequence, so the "nested" printf sees
an unadjusted value and winds up using the same position in the
buffer, so that you "lose" one character).
 
A

Antoninus Twink

You believe incorrectly.


Wrong again.

Yeah, OK, s/reentrant/threadsafe/ I guess... And since this is such a
haunt of language lawyers, let's make clear that we're ignoring
functions that write to streams that are deliberately not threadsafe,
e.g. putc_unlocked().
 
F

Flash Gordon

Antoninus Twink wrote, On 29/05/08 16:20:

Yeah, OK, s/reentrant/threadsafe/ I guess... And since this is such a
haunt of language lawyers, let's make clear that we're ignoring
functions that write to streams that are deliberately not threadsafe,
e.g. putc_unlocked().

Well, the OP was not talking about threads, so talking about what is
acceptable in a threaded environment rather than in the situation the OP
*was* talking about is just plain unhelpful. So you were wrong and if
you had said something correct it would have still been of no use to the OP.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top