query about printf

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rahul

    query about printf

    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 ! ! !
  • Antoninus Twink

    #2
    Re: query about printf

    On 28 May 2008 at 12:27, Rahul wrote:
    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.

    Comment

    • Eric Sosman

      #3
      Re: query about printf

      Antoninus Twink wrote:
      On 28 May 2008 at 12:27, Rahul wrote:
      >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
      <off-topicYou believe incorrectly. </off-topic>
      (certainly this will be true if you're
      using threads)...
      <off-topicWrong again. </off-topic>
      In general I don't think the famous ANSI C Standard
      (praise be upon it!) insists on it.
      In fact, there's an explicit warning to the contrary.
      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.
      The buffer needn't be static; its mere existence is
      enough to doom re-entrancy.

      --
      Eric Sosman
      esosman@ieee-dot-org.invalid

      Comment

      • Rahul

        #4
        Re: query about printf

        >
        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.
        >
        The buffer needn't be static; its mere existence is
        enough to doom re-entrancy.
        >
        What is the buffer is allocated on heap or declared as a local
        varaible?

        Comment

        • Eric Sosman

          #5
          Re: query about printf

          Rahul wrote:
          >>It's easy to imagine an
          >>implementatio n of printf() that used a static internal buffer to build
          >>up the string before sending it to stdout, for example.
          >The buffer needn't be static; its mere existence is
          >enough to doom re-entrancy.
          >>
          >
          What is the buffer is allocated on heap or declared as a local
          varaible?
          (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.)

          --
          Eric Sosman
          esosman@ieee-dot-org.invalid

          Comment

          • Jens Thoms Toerring

            #6
            Re: query about printf

            Rahul <sam_cit@yahoo. co.inwrote:
            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.
            The buffer needn't be static; its mere existence is
            enough to doom re-entrancy.
            >
            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
            --
            \ Jens Thoms Toerring ___ jt@toerring.de
            \______________ ____________ http://toerring.de

            Comment

            • Rahul

              #7
              Re: query about printf

              On May 28, 6:52 pm, Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
              Rahul wrote:
              >It's easy to imagine an
              >implementati on of printf() that used a static internal buffer to build
              >up the string before sending it to stdout, for example.
              The buffer needn't be static; its mere existence is
              enough to doom re-entrancy.
              >
              What is the buffer is allocated on heap or declared as a local
              varaible?
              >
              (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.)
              >
              --
              Eric Sosman
              esos...@ieee-dot-org.invalid
              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 ! ! !

              Comment

              • Eric Sosman

                #8
                Re: query about printf

                Rahul wrote:
                >
                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?
                The situation is far outside the scope of the C language.
                In C there is no such thing as an "ISR" and there is only one
                "task." Your questions aren't about C, but about specific
                environments in which C can be used. And the answers will
                be different[*] in different environments: An ISR in a Linux
                system will have different conventions and constraints than
                an ISR in Windows or in OS/390 or in your cell phone, even
                if all these ISRs are written in C.
                [*] Well, maybe not. I predict, with a confidence level
                exceeding ninety percent, that the answer to "Is it safe to
                call printf() in an ISR" will be "No," even though the reasons
                behind the "No" will differ.
                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?
                C has no notion of a static library or a dynamic library.
                All it knows about are functions and data, and about some kind
                of "linkage" that pulls a bunch of them together into a running
                program. If you need information about the details of how
                different systems accomplish this, you are asking not about C
                but about those systems.

                --
                Eric.Sosman@sun .com

                Comment

                • Chris Torek

                  #9
                  Re: query about printf

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

                  In article <MM2dnSl-HaUC_qDVnZ2dnUV Z_sudnZ2d@comca st.com>,
                  Eric Sosman <esosman@ieee-dot-org.invalidwrot e:
                  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).
                  --
                  In-Real-Life: Chris Torek, Wind River Systems
                  Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
                  email: gmail (figure it out) http://web.torek.net/torek/index.html

                  Comment

                  • Antoninus Twink

                    #10
                    Re: query about printf

                    On 28 May 2008 at 13:21, Eric Sosman wrote:
                    Antoninus Twink wrote:
                    >I believe POSIX requires the functions that write to streams to be
                    >implemented in a re-entrant way
                    >
                    You believe incorrectly.
                    >
                    >(certainly this will be true if you're using threads)...
                    >
                    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() .

                    Comment

                    • Flash Gordon

                      #11
                      Re: query about printf

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

                      <snip>
                      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.
                      --
                      Flash Gordon

                      Comment

                      Working...