volatile and multiple threads

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • S James S Stapleton

    volatile and multiple threads

    Is volatile necessary anymore? I have a two-thread piece of code I've been
    testing to figure out what volatile does (fairly simple code, uses
    pthreads). I have an update thread (variables passed as volatile) and a
    print thread (one variable volatile, the other, not). There is no difference
    in the behavior of the volatile and nonvolatile thread.

    I'm compiling this with gcc, using the -O2 and -pthreads flags.

    The sudocode is at the end. The result I'm getting is that the correct
    memory addresses and values are being printed by the volatile and
    non-volatile variable. If I understand things correctly, the non-volatile
    variables should give the wrong addresses at least half the time. Is GCC
    just smart enough to handle this, or am I completely misunderstandin g
    things. I can provide the code, but I'd rather not clutter up the list with
    it, without a request.

    Thanks,
    -Jim Stapleton

    * two pointers (a, b) are global (non volatile) variables. Each is of type
    (int*)
    * each is malloc'ed and the value in the allocated memory set to the value
    of a counter variable (0).
    * A global volatile turn variable is set to 0 (0 = print, 1 = update).
    * the print and update functions are called.

    * print function
    ** output that the print function was called
    ** call the internal print function with a non-volatile pointer to a
    (int**), and a volatile pointer to b (volatile int**)
    ** output that the print function is closing
    ** exit

    * internal print function
    ** wait until turn = 0
    ** loop until count = 5
    *** print the memory addresses a & b point to, and the values stored therein
    *** set turn to 1
    *** wait until turn = 0
    ** exit

    * update function
    ** output that the update function was called
    ** call the internal update function with a volatile pointer to a (volatile
    int**), and a volatile pointer to b (volatile int**)
    ** output that the update function is closing
    ** exit

    * internal update function
    ** wait until turn = 1
    ** loop until count = 5
    *** increment count
    *** assign integer pointers (int*) t1 and t2 to the memory values pointed to
    by the arguments (eqiv to t1 = a, t2 = b)
    *** malloc new memory to a and b (sizeof(int)), and set the value to the
    same as count.
    *** print out eqiv: "*t1 (t1) -*a (a) *t2 (t2) -*b (b)"
    *** free t1 and t2
    *** set turn = 0
    *** wait until turn = 1
    ** exit






  • Walter Roberson

    #2
    Re: volatile and multiple threads

    In article <g556rb$7ae$1@c harm.magnus.acs .ohio-state.edu>,
    S James S Stapleton <stapleton.41@o su.eduwrote:
    >Is volatile necessary anymore? I have a two-thread piece of code
    Threads are not part of the C programming language itself.
    Your system's implementation of threads might (or might not)
    have imposed constraints on the generated code such that
    everything worked out okay in your particular program on
    that particular implementation (on that particular hardware.)

    Is volatile necessary anymore? Try writing a C program
    on an embedded platform that has memory-mapped I/O registers,
    such that reading a register fetches the "next" input value.
    On such systems, you don't want the compiler optimizing away
    references to the location because it figures the reference
    is just going to generate the same value as last time; you
    also don't want the compiler introducing new references to the
    location figuring that it doesn't need to remember the value
    because the value will still be there when it is needed next.

    I do not know whether volatile is of any theoretical benefit in
    variables shared between pthreads; for that you should consult
    comp.programmin g.threads or the like.
    --
    "There is no greater calling than to serve your fellow men.
    There is no greater contribution than to help the weak.
    There is no greater satisfaction than to have done it well."
    -- Walter Reuther

    Comment

    • S James S Stapleton

      #3
      Re: volatile and multiple threads

      Is volatile necessary anymore? Try writing a C program
      on an embedded platform that has memory-mapped I/O registers,
      such that reading a register fetches the "next" input value.
      On such systems, you don't want the compiler optimizing away
      references to the location because it figures the reference
      is just going to generate the same value as last time; you
      also don't want the compiler introducing new references to the
      location figuring that it doesn't need to remember the value
      because the value will still be there when it is needed next.
      OK, I kept seeing references to embedded systems when I was look at things
      regarding this. I assume then that they have more agressively optimising
      compilers? Would volatile thus be less useful in a non-embedded system?
      I do not know whether volatile is of any theoretical benefit in
      variables shared between pthreads; for that you should consult
      comp.programmin g.threads or the like.
      Thanks, I'll check that out.

      -Jim Stapleton


      Comment

      • Jens Thoms Toerring

        #4
        Re: volatile and multiple threads

        S James S Stapleton <stapleton.41@o su.eduwrote:
        Is volatile necessary anymore? Try writing a C program
        on an embedded platform that has memory-mapped I/O registers,
        such that reading a register fetches the "next" input value.
        On such systems, you don't want the compiler optimizing away
        references to the location because it figures the reference
        is just going to generate the same value as last time; you
        also don't want the compiler introducing new references to the
        location figuring that it doesn't need to remember the value
        because the value will still be there when it is needed next.
        OK, I kept seeing references to embedded systems when I was look at things
        regarding this. I assume then that they have more agressively optimising
        compilers?
        It's not because of the optimization being more aggresive. If
        you have a hardware register mapped to memory and you can achieve
        a certain effect by writing to that address, then you must make
        sure that the write really happens. If the memory address isn't
        marked as volatile the comiler is allowed to make up a copy of
        what gets written there in a register instead of really writing
        it out since it can't know that this write has side-effects.
        Would volatile thus be less useful in a non-embedded system?
        It's not only embedded systems, also hardware drivers for opera-
        ting systems will use volatile. But you can also see the diffe-
        rence with a "normal" program, just try

        #include <limits.h>
        int main( void )
        {
        volatile int i;
        for ( i = 0; i < INT_MAX; i++ )
        /* empty */ ;
        return 0;
        }

        If you remove the 'volatile' the compiler will rather likely opti-
        mize out the whole loop, drastically reducing the execution time.

        But volatile can also be useful for signal handlers to make sure
        the part of a program accessing a flag that gets set in a signal
        handler doesn't use an out of date copy in a register (but then
        you usually also throw 'sig_atomic' into the mix to avoid partial
        reads).
        Regards, Jens
        --
        \ Jens Thoms Toerring ___ jt@toerring.de
        \______________ ____________ http://toerring.de

        Comment

        • Roberto Waltman

          #5
          Re: volatile and multiple threads

          "S James S Stapleton" <stapleton.41@o su.eduwrote:

          (Walter Roberson) wrote:
          >Is volatile necessary anymore? Try writing a C program
          >on an embedded platform that has memory-mapped I/O registers,
          >such that reading a register fetches the "next" input value.
          >On such systems, you don't want the compiler optimizing away
          >references to the location because it figures the reference
          >is just going to generate the same value as last time; you
          >also don't want the compiler introducing new references to the
          >location figuring that it doesn't need to remember the value
          >because the value will still be there when it is needed next.
          >
          >OK, I kept seeing references to embedded systems when I was look at things
          >regarding this. I assume then that they have more agressively optimising
          >compilers? Would volatile thus be less useful in a non-embedded system?
          To give a concrete example, lets assume the following program is built
          in such a way that the variables 'inputs' and 'outputs' are mapped in
          the obvious ways to hardware registers.

          -------------------------------------------

          #define MAKE_IT_WORK ???

          #if MAKE_IT_WORK
          #define MAGIC volatile
          #else
          #define MAGIC
          #endif

          extern unsigned char MAGIC inputs;
          extern unsigned char MAGIC outputs;

          #define SMOKE_DETECTOR 0x01
          #define SPRINKLERS_ON 0x01

          int main(void)
          {
          while (1)
          {
          if (inputs & SMOKE_DETECTOR)
          {
          outputs |= SPRINKLERS_ON;
          break;
          }
          }
          return 0;
          }

          -------------------------------------------

          If 'inputs' is not declared as volatile, a compiler could relocate
          reading its value before the loop, doing it only once (since nothing
          changes its value inside the loop)
          Similarly if 'outputs' is not volatile, the assignment to it could be
          removed altogether, (since it is not used afterwards,) leaving the
          equivalent of:

          ...
          int main(void)
          {
          /* read the value of 'inputs' into a register */
          while (1)
          {
          if ( [saved value of 'inputs'] & SMOKE_DETECTOR)
          {
          break;
          }
          }
          return 0;
          }

          --
          Roberto Waltman

          [ Please reply to the group,
          return address is invalid ]

          Comment

          • Kaz Kylheku

            #6
            Re: volatile and multiple threads

            On 2008-07-10, S James S Stapleton <stapleton.41@o su.eduwrote:
            Is volatile necessary anymore?
            Yes, in portable, standard-conforming C, volatile is a necessary
            attribute on a variable that is written by an asynchronous signal handler.
            The type volatile sig_atomic_t must be used.
            I have a two-thread piece of code I've been
            The C language doesn't incorporate a threading API. Threads are described
            in various competing extensions to the language, such as POSIX and Win32.
            Rules about concurrent access to shared data by multiple threads are
            defined by those interfaces.

            In POSIX, volatile is not required. Shared data is guarded by the use of
            a synchronization object, whose use ensures that the memory is stable.

            Volatile is a bad idea because (if implemented earnestly) it interferes
            with compiler optimizations, So it would be insane for a threading
            platform to require it.

            When a thread holds a lock over some shared data, it may make many accesses
            and stores to that data. Propagation of data changes from one thread to another
            are only necessary on entry to and exit from the critical section. Volatile
            goes beyond what is required, asking for more memory traffic than necessary.
            The sudocode is at the end.
            That's ``pseudocode''.

            Sudo is a utility for executing commands with superuser privilege.

            So ``sudocode'' is perhaps a script executed by sudo. :)

            Comment

            • S James S Stapleton

              #7
              Re: volatile and multiple threads

              Thanks, I guess I'm just not sure how my code differs from this in a multi
              threaded context. Since another thread may modify the code. Anyway, I'm
              continuing this on comp.programmin g.threading

              Thanks for the help.
              -Jim Stapleton


              Comment

              • Chris Torek

                #8
                Re: volatile and multiple threads

                In article <g556rb$7ae$1@c harm.magnus.acs .ohio-state.edu>
                S James S Stapleton <stapleton.41@o su.eduwrote:
                >Is volatile necessary anymore? I have a two-thread piece of code ...
                The rules for using variables in threads depends on the thread
                implementation, so there is no single answer to this question.
                (Threads, as others noted, are not standardized in C. Different
                thread implementations thus behave differently.)

                As a general rule, though, in code that *implements* threads
                (rather than simply *using* those provided by some existing
                implementation) , "volatile" is necessary but not sufficient.
                That is, the thread locking code needs to mark certain things
                volatile, but *also* needs to prod the compiler in some special
                way(s) to get hardware guarantees that are not provided by
                the volatile qualifier. (In some specific cases, the hardware
                guarantees *are* already provided, and volatile is sufficient.
                In some specific compilers, the optimization is weak, and even
                the volatile keyword is not required.)
                --
                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

                • CBFalconer

                  #9
                  Re: volatile and multiple threads

                  S James S Stapleton wrote:
                  >
                  Is volatile necessary anymore? I have a two-thread piece of code
                  I've been testing to figure out what volatile does (fairly simple
                  code, uses pthreads). I have an update thread (variables passed as
                  volatile) and a print thread (one variable volatile, the other,
                  not). There is no difference in the behavior of the volatile and
                  nonvolatile thread.
                  .... snip monstrosity ...

                  First, realize what the 'volatile' characteristic says about an
                  object. It has nothing to do with threads. It does have to do
                  with how the object can be modified. For example, the volatile
                  object could be an integer, which is non-zero when an input port
                  has unread data, and zero after that data has been read. The
                  actions which set or reset that flag can be external to the
                  program. If anything reads the port value, the flag is reset. If
                  you read the 'ready' status, the flag is unaltered. It can only be
                  set when the external unit has fresh data. It can only be reset by
                  reading that data.

                  Remember that the above is only one illustration of a use for
                  'volatile'.

                  --
                  [mail]: Chuck F (cbfalconer at maineline dot net)
                  [page]: <http://cbfalconer.home .att.net>
                  Try the download section.

                  Comment

                  • GPS

                    #10
                    Re: volatile and multiple threads

                    Kaz Kylheku wrote:
                    On 2008-07-10, S James S Stapleton <stapleton.41@o su.eduwrote:
                    >Is volatile necessary anymore?
                    >
                    Yes, in portable, standard-conforming C, volatile is a necessary
                    attribute on a variable that is written by an asynchronous signal handler.
                    The type volatile sig_atomic_t must be used.
                    >
                    >I have a two-thread piece of code I've been
                    >
                    The C language doesn't incorporate a threading API. Threads are described
                    in various competing extensions to the language, such as POSIX and Win32.
                    Rules about concurrent access to shared data by multiple threads are
                    defined by those interfaces.
                    >
                    In POSIX, volatile is not required. Shared data is guarded by the use of
                    a synchronization object, whose use ensures that the memory is stable.
                    >
                    Volatile is a bad idea because (if implemented earnestly) it interferes
                    with compiler optimizations, So it would be insane for a threading
                    platform to require it.
                    <offtopic>
                    Some lockless algorithms use volatile. Microsoft's documentation
                    suggests it for their XBox.



                    Some POSIX-based systems use volatile, and the atomic macros for
                    Linux/BSD sometimes use volatile.

                    Another thing to keep in mind is that most systems these days do atomic
                    writes of pointers, and integers, as long as alignment is correct.

                    The GNU libc for instance depends on this.

                    When a thread holds a lock over some shared data, it may make many accesses
                    and stores to that data. Propagation of data changes from one thread to another
                    are only necessary on entry to and exit from the critical section. Volatile
                    goes beyond what is required, asking for more memory traffic than necessary.
                    volatile is not ideal, but it's sometimes required.

                    Another danger with lock-free algorithms is reordering of writes. So it
                    requires a lot of care, but sometimes lock-free is the best solution
                    when lock contention would otherwise reduce performance.

                    The sooner we can move from the current popular thread models to
                    Flow-based programming, or the Plan 9 model, or something like those the
                    better. The current thread models just don't scale with the current
                    languages to 500 or 1000 cores.
                    </offtopic>

                    Comment

                    • Kenneth Brody

                      #11
                      Re: volatile and multiple threads

                      S James S Stapleton wrote:
                      >
                      Is volatile necessary anymore?
                      [... mega-snip ...]

                      Yes.

                      Consider a memory-mapped I/O device:

                      #define MyIODevice ((volatile char *)0x12345678)
                      ...
                      void ResetDevice()
                      {
                      *MyIODevice = 0x12;
                      *MyIODevice = 0x34;
                      }

                      Without volatile, the compiler can discard the first assignment.

                      --
                      +-------------------------+--------------------+-----------------------+
                      | Kenneth J. Brody | www.hvcomputer.com | #include |
                      | kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer .h|
                      +-------------------------+--------------------+-----------------------+
                      Don't e-mail me at: <mailto:ThisIsA SpamTrap@gmail. com>

                      Comment

                      Working...