Thread: Test C code: function call order

  1. #16
    Registered User
    Join Date
    Apr 2006
    Quote Originally Posted by phantomotap View Post
    An atomic write to an unrelated variable (let's call it `gatom') in `g' does not in any way guarantee that the write to `result_of_f' happens before a read from `result_of_f'.

    An atomic write to `gatom' does not in any way guarantee that a write to `result_of_f' happens before a read from `gatom'.

    An atomic read from `gatom' does not guarantee that a read from `result_of_h' happens after the read from `gatom'.

    An atomic read from `result_of_f' does not guarantee that a read from `result_of_h' happens after the read from `result_of_f'.

    An atomic variable only guarantees that reads and writes are completed in isolation. They do not impose any mutual or identity ordering. If one thread (`i') increments a variable (`v1') while another thread (`d') decrements a variable (`v2') the sole use of atomic reads and writes to the variables (`v1' and `v2') is insufficient to enforce a `v1++'->`v2--' pattern; it is entirely possible to get `v1++'->`v1++'->`v2--' as an ordering. This lack of any mutual or identity ordering holds for single threaded applications as well as applications with multiple threads.
    Atomic do impose an odering.

    Quote Originally Posted by C committee draft from April 12, 2012
    Certain library calls synchronize with other library calls performed by another thread. In
    particular, an atomic operation A that performs a release operation on an object M
    synchronizes with an atomic operation B that performs an acquire operation on M and
    reads a value written by any side effect in the release sequence headed by A.

    An evaluation A inter-thread happens before an evaluation B if A synchronizes with B, A
    is dependency-ordered before B, or, for some evaluation X:
    — A synchronizes with X and X is sequenced before B,
    — A is sequenced before X and X inter-thread happens before B, or
    — A inter-thread happens before X and X inter-thread happens before B.
    f() is sequenced before g(). If g() preforms an release on an atomic 'gatom', then it synchronizes with a future thread that does an aquire on 'gatom'. Then in that thread, anything sequenced after that aquire can assume that result_of_f has been properly set. It cannot read from result_of_f prior to the aquire on 'gatom', because that would be a data race, and therefore undefined.

    Simmilarly in the other direction. The aquire of 'gatom' implies that everything sequenced before the previous release of gatom in another thread. That includes any writes to result_of_h. As a result, those writes to result_of_h does not constitute a data race with that prior write of result_of_h.

    This two way release and acquire also ensures a thread that acquires 'gatom' after this thread knows that it cannot write to result_of_h, because it is not inter thread happends before the write in this thread to result_of_h, and no other inter thread sequencing exists.

    So, we wind up back at the compiler and sequence points. If the compiler doesn't recognize a sequence point, and so reorders, the use of atomic doesn't buy you correct ordering. Any given compiler may recognize any specific atomic operation as a sequence point, but that is not something enforced by the standards. (Well, I do not know C11 at all so it may be something in that standard.) If a compiler does recognize atomic reads and writes and necessary sequence points the compiler doesn't reorder so you get the canonical ordering.
    It's not a matter of recognising sequence points or not. C simply does not define the order in which operations are done, except where there is a dependency or IO.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  2. #17
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Atomic do impose an odering.
    Your entire post is about inter-thread ordering; inter-thread ordering is different than the sequence points grumpy noted.

    The sequence points we are talking about may be viewed as intra-thread if you still aren't getting it.

    Beyond that, you misunderstand acquire and release semantics. The `gatom' from my post is an variable unrelated to the others. Throwing a fence over `gatom' using atomic primitives will prevent further operations on `gatom' by other threads. A different thread attempting an operation on `result_of_f' will not order reads and writes relative to the fence protecting `gatom' simply because the operations on both `gatom' and `result_of_f' are atomic.

    Your assertion that, for example, an atomic increment of `result_of_f' will prevent an atomic decrement of `gatom' by at the same time by another thread is false.

    If that held true you could use an atomic acquire as a full mutually exclusive lock protecting all resources across any processes sharing that region of memory.

    And yes, I know that there is such a thing as a "full fence", but you do not need a "full fence" just for an atomic operation on a single variable.

    Last edited by phantomotap; 07-24-2012 at 03:21 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Call managed code (c#) from unmanaged code (VC++ 6.0)
    By playxn in forum C++ Programming
    Replies: 3
    Last Post: 10-14-2008, 12:11 PM
  2. Replies: 14
    Last Post: 04-01-2008, 02:23 AM
  3. How do you order your game code?
    By Queatrix in forum A Brief History of
    Replies: 15
    Last Post: 02-05-2006, 06:26 PM
  4. using a driver function to test my code??
    By tommy69 in forum C Programming
    Replies: 24
    Last Post: 03-20-2004, 07:12 PM
  5. order of multiple test expression?
    By wolf in forum C Programming
    Replies: 5
    Last Post: 02-05-2002, 04:33 PM

Tags for this Thread