8

I want to use atomic compare and swap, but instead of equal to, I want to swap only if the memory location is not equal to the old value. Is it possible in C?

pb2q
  • 58,613
  • 19
  • 146
  • 147
0xhacker
  • 1,091
  • 2
  • 14
  • 26

2 Answers2

4

How about this:

void compare_and_swap_if_not_equal(word_t const required_non_value, word_t const new_value, word_t* ptr_to_shared_variable) { 
    for (;;) {
        word_t const snapshot_value = *ptr_to_shared_variable;
        if (required_non_value == snapshot_value) {
            break;
            // or (sleep and) 'continue;', if you want to wait for the stored value to be different 
            // -- but you might of course miss a transient change to a different state and back.
        } else { 
            if (compare_and_swap_if_equal(ptr_to_shared_variable, snapshot_value, new_value)) {
                // we know the stored value was different; if this 'theory' still matches reality: swap! done!
                break;
            }
        }
    }
}

Untested. Uncompiled. The 'const' used because I like it that way :). 'word_t' is a type placeholder, I don't know what the real type should be. And I don't know how what 'compare_and_swap_if_equal' is called in stdatomic.h.

(added) atomic_compare_exchange_weak() is the ticket. For some reason, it takes a pointer to the 'expected' argument, so you'll have to modify above code to

if (atomic_compare_exchange_weak(ptr_to_shared_variable, &snapshot_value, new_value)) ...

The 'weak' version should work in the above code; returning 'false' spuriously will only add another trip around the loop. Still uncompiled, untested; don't rely on this code at home.

Jonas N
  • 1,757
  • 2
  • 21
  • 41
  • What if the pointee always changes between taking `snapshot_value` and the atomic cas? It seems that the loop will never end then. Besides, don't we need a memory barrier before fetching the pointee? (atomic cas implies it) – Igor R. Feb 09 '14 at 12:33
  • 1
    @IgorR. Re: 'What if the pointee always changes between taking snapshot_value and the atomic cas?': Yes, I suppose that is a possibility on really unfair systems. A timeout or retry counter could be an option. One might wonder what kind of system and work that would be, and why the writer/s and reader don't cooperate better :). Also, I suppose this would happen for the typical application of CAS 'if equal' too, and even more so, since actual work is done between initial fetch and the CAS. – Jonas N Feb 09 '14 at 14:28
  • @IgorR. Re: 'Besides, don't we need a memory barrier before fetching the pointee? (atomic cas implies it)' Hmm, hadn't thought of such things... There is only one non-local variable affected, so I don't think that there is any such ordering problem here, right? – Jonas N Feb 09 '14 at 15:40
1

It depends on your architecture, but in general it is not possible to do this in C.

Typically compare and swap is implemented with an instruction that atomically loads from a location in memory and stores a value to that location if the location in memory matches some existing value that you specify.

At least on x86 there is no provision for only doing this load if the values don't match. Also it's not clear why you would want to do something like that. Perhaps another architecture would support something like this, but that would be architecture dependent, not something that could be done in C in a portable way.

Gabriel Southern
  • 9,602
  • 12
  • 56
  • 95
  • Isn't there a cmov instruction in modern x86 processors? Does it fit the required profile? – Janito Vaqueiro Ferreira Filho Oct 05 '12 at 23:34
  • I don't think that would work because you would need one instruction to set the condition code before you executed the cmov. So in the time between when the condition code was checked and when the cmov was executed another processor could change the value in the memory that you were trying to write to. – Gabriel Southern Oct 05 '12 at 23:45
  • @JanitoVaqueiroFerreiraFilho There *is* an `xchg` instruction on x86 that does precisely what the OP wants, an unconditional, atomic swap. – doug65536 Jan 26 '13 at 08:01