5
\$\begingroup\$

This is my second attempt to make simple lock using extended assembly. See https://stackoverflow.com/questions/37241553/locks-around-memory-manipulation-via-inline-assembly/37246263

The code:

static inline void atomic_open(volatile int *gate)
{
    asm volatile (
        "jmp check\n"
        "wait:\n"                      // Set spawning point.
        "pause\n"                      // Stroke your beard. (If you have one.)
        "check:\n"
        "cmp %[open], %[gate]\n"       // Check if gate is open.
        "jne wait\n"                   // If it isn't open, wait. If it is open, go through the gate.
        "lock xadd %[lock], %[gate]\n" // In case you where not alone entering the gate, at least try to be the first one to put the lock.
        "cmp %[lock], %[open]\n"       // Check to see you where the first one who put the lock.
        // "If not, consider thug life..."
        "jne wait\n"                   // If you didn't win, respawn and try again later.
        : [gate] "=m" (*gate)
        : [lock] "r" (1), [open] "r" (0)
    );
}

static inline void atomic_close(volatile int *gate)
{
    asm volatile (
        "pause\n"
        "lock xchg %[lock], %[gate]\n"
        : [gate] "=m" (*gate)
        : [lock] "r" (0)
    );
}

// Usage, example.
volatile int atomic_gate_memory = 0;
void *mymalloc(size_t size)
{
    atomic_open(&atomic_gate_memory);
    void *ptr = malloc(size);
    atomic_close(&atomic_gate_memory);
    return ptr;
}

The question: Will atomic_[open/close] make mymalloc both threadsafe and reentrant?

  • If no, what is wrong?
  • If yes, it is still wrong; isn't it?... Give me a good rant about what to consider, what is missing or about better approach. If you want to suggest libraries, please restrict your self to C. I am not experienced enough to bind C++ stuff to other languages, so I often can't use the good stuff over there :'(
\$\endgroup\$
  • 1
    \$\begingroup\$ Say code had 3 processes, all 3 having called mymalloc() at slightly different times. One processes gets through the gate, does the malloc(), atomic_close() and then the other 2 see the gate is now open at about the same time. does this not pose a race condition where both process 2 & 3 slip through - OR both fail and synchronously loop as thugs? IOWs, does not the "cmp %[lock], %[open]" need to be based on flags set by the previous lock xadd %[lock], %[gate] and not involve a re-sample of %[lock]? \$\endgroup\$ – chux - Reinstate Monica May 17 '16 at 20:00
  • \$\begingroup\$ You are right! This is not going to work! I would also assume the "%[lock]" it is going to be local to the thread so the whole basis of this approach is just bizarre now.. Even if it wasn't local, we have this race condition you pointed out. Wow... I will have to make another revision.. In the meantime, feel free to post an answer. I will accept it tomorrow after work as I am going to sleep now. Thanks for pointing me in the right direction btw! :) \$\endgroup\$ – user1235831 May 17 '16 at 22:33
2
\$\begingroup\$
  1. Op's code has a possible race condition between the lock and compare.

    "lock xadd %[lock], %[gate]\n" 
    "cmp %[lock], %[open]\n"       
    
  2. OP identified: lock is not certainly made a shared variable.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.