Лучший способ реализовать общую атомарную загрузку или хранение в GCC?

Мне известны встроенные атомарные операции GCC: http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Atomic-Builtins.html

Но в этот список не входят очень простые операции, такие как загрузка и сохранение. Я мог бы реализовать их на ограниченных архитектурах с помощью встроенной сборки (фактически для многих, таких как x86, они будут в основном просто обычными mov), но нет лучшего способа в общем случае, чем что-то вроде этого:

// returns the value at ptr
void *atomic_load_ptr(void **ptr)
{
    return __sync_fetch_and_add(ptr, 0);
}

// returns old value int ptr after setting it to newval
void *atomic_store_ptr(void **ptr, void *newval)
{
    void *oldval = atomic_load_ptr(ptr)
    void *oldval2;
    do {
        oldval2 = oldval;
    } while ((oldval = __sync_val_compare_and_swap(ptr, oldval, newval)) != oldval2);
    return oldval;
}

person Greg Rogers    schedule 02.05.2009    source источник
comment
Остановите меня, если я ошибаюсь, но ваша функция store на самом деле не является хранилищем, поскольку она возвращает старое значение (поэтому оно очень близко к CAS).   -  person claf    schedule 04.05.2009
comment
Это действительно обмен - сохранение нового значения и возврат предыдущего значения, если вы этого хотите.   -  person Greg Rogers    schedule 04.05.2009
comment
Я обнаружил, что у этой реализации загрузки есть проблема: ее нельзя использовать в постоянной памяти.   -  person Mabus    schedule 27.08.2014


Ответы (1)


Вы можете реализовать мьютекс низкого уровня с помощью test_and_set. Функция загрузки хороша imo, но вы сохраняете функцию, должны использовать test_and_set вместо того, чтобы иметь

while ((oldval = __sync_val_compare_and_swap(ptr, oldval, newval)) != oldval2);

для предотвращения ошибок.

person claf    schedule 04.05.2009