[OT] Atomics in general


#1

Following the recent discussions, I’m just trying to get my head around lock-free stuff (yes, Vinn it is hard!) and reading around issues such as the ABA problem etc. Particularly I’m looking for a 128 bit atomic op for storing a pointer and a counter on 64-bit systems.

I thought I was getting somewhere until I found this at Microsoft:

typedef struct _LARGE_INTEGER_128 {
    __int64 Int[2];
} LARGE_INTEGER_128, *PLARGE_INTEGER_128;

volatile LARGE_INTEGER_128 BigInt;

// This AtomicOp() function atomically performs:
//   BigInt.Int[1] += BigInt.Int[0]
//   BigInt.Int[0] += 1
void AtomicOp ()
{
    LARGE_INTEGER_128 Comparand;
    Comparand.Int[0] = BigInt.Int[0];
    Comparand.Int[1] = BigInt.Int[1];
    do {
        ; // nothing
    } while (_InterlockedCompareExchange128(BigInt.Int,
                                            Comparand.Int[0] + Comparand.Int[1],
                                            Comparand.Int[0] + 1,
                                            Comparand.Int) == 0);
}

My understanding is that if multiple threads contend for the value of BigInt and the value has changed in between grabbing the Comparand and the call to _InterlockedCompareExchange128 then the next attempt around the do…while needs to grab the Comparand otherwise it’ll just get stuck?

i.e., should this be:

typedef struct _LARGE_INTEGER_128 {
    __int64 Int[2];
} LARGE_INTEGER_128, *PLARGE_INTEGER_128;

volatile LARGE_INTEGER_128 BigInt;

// This AtomicOp() function atomically performs:
//   BigInt.Int[1] += BigInt.Int[0]
//   BigInt.Int[0] += 1
void AtomicOp ()
{
    LARGE_INTEGER_128 Comparand;

    do { 
        Comparand.Int[0] = BigInt.Int[0];
        Comparand.Int[1] = BigInt.Int[1];
    } while (_InterlockedCompareExchange128(BigInt.Int,
                                            Comparand.Int[0] + Comparand.Int[1],
                                            Comparand.Int[0] + 1,
                                            Comparand.Int) == 0);
}

#2

Can’t you first store the 128 bits, then change a uintptr_t variable to signal the storage ? Then the 128 bits store need not be atomic, but the uintptr_t change will always be atomic… ?


#3

You are gonna get hurt LOL 128 bit atomic operation? Run away!

If you insist on this form of suicide, there are some forums and sites dedicated to atomic / lock-free discussions:

http://groups.google.com/group/lock-free

http://groups.google.com/group/comp.programming.threads/topics

http://groups.google.com/group/linuxkernelnewbies/browse_thread/thread/70e8af61a5c0732e/e3f1e44292e775db?q=wait-free#e3f1e44292e775db


#4

Thanks… I’ll wear a helmet.