Реализация Mutex без аппаратной поддержки Test-and-Set и CAS-операций - PullRequest
0 голосов
/ 22 октября 2018

Давайте получим следующее простое определение мьютекса:

class Mutex {
private:
    bool lock;
public:
    void acquire();

    void release();

    Mutex() {
        lock = 0;
    }
};

И следующую реализацию acquire() func (с использованием операций сравнения и обмена):

void Mutex::acquire() {
    bool oldValue;
    __atomic_load(&lock, &oldValue, 0);
    bool newValue = true;
    while (!__atomic_compare_exchange_n(&lock, &oldValue, newValue, true, 0, 0)) {
        sched_yield();
    }
}

В этомВ этом случае мы получим следующий код сборки:

movzx   eax, BYTE PTR [rsp+15]
lock cmpxchg    BYTE PTR [rbx], bpl
je      .L9

Или в случае использования __atomic_test_and_set:

void Mutex::acquire() {
    while (__atomic_test_and_set(&lock, 0)) {
        sched_yield();
    }
}

Получим следующий код сборки:

    mov     eax, ebp
    xchg    al, BYTE PTR [rbx]
    test    al, al
    jne     .L6

Но, что, если у нас нет аппаратной поддержки атомарных операций Test-and-Set и CAS-операций (xchg и lock cmpxchg на x86 и их эквивалентах на других архитектурах)? Какое решение будет использовать компилятор в этом случае?

PS - я использовал gcc 8.2 для создания ассемблерного кода, а вот __atomic_ встроенные функции: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html

...