Атомарное чтение / запись значения int без дополнительных операций с самим значением int

GCC предлагает прекрасный набор встроенных функций для атомарных операций. А на MacOS или iOS даже Apple предлагает хороший набор элементарных функций . Однако все эти функции выполняют операцию, например сложение / вычитание, логическая операция (И / ИЛИ / ИСКЛЮЧАЮЩЕЕ ИЛИ) или сравнение и установка / сравнение и замена. Я ищу способ атомарного присвоения / чтения значения int , например:

int a;
/* ... */    
a = someVariable;

Вот и все. a будет прочитан другим потоком, и важно только, чтобы a имел старое или новое значение. К сожалению, стандарт C не гарантирует, что присвоение или чтение значения является атомарной операцией. Я помню, что однажды я где-то читал, что запись или чтение значения переменной типа int гарантированно будет атомарным в GCC (независимо от размера int), но я искал везде на домашней странице GCC, и я больше не могу найти этот оператор (возможно, он был удален).

Я не могу использовать sig_atomic_t , потому что sig_atomic_t не имеет гарантированного размера, а также может иметь другой размер, чем int .

Поскольку только один поток когда-либо «запишет» значение в a , в то время как оба потока будут «читать» текущее значение a , мне не нужно выполнять операции сами по себе атомарно, например:

/* thread 1 */
someVariable = atomicRead(a);
/* Do something with someVariable, non-atomic, when done */
atomicWrite(a, someVariable);

/* thread 2 */
someVariable = atomicRead(a);
/* Do something with someVariable, but never write to a */

Если оба потока собирались писать в a , тогда все операции должны были бы быть атомарными, но в этом случае это может только тратить время процессора; и у нас очень мало ресурсов ЦП в нашем проекте. Пока мы используем мьютекс для операций чтения / записи a , и хотя мьютекс удерживается в течение такого крошечного времени, это уже вызывает проблемы (один из потоков является потоком реального времени и блокирует мьютекс заставляет его не выполнять свои ограничения реального времени, что довольно плохо).

Конечно, я мог бы использовать __ sync_fetch_and_add для чтения переменной (и просто добавить к ней «0», чтобы не изменять ее value), а для записи используйте __ sync_val_compare_and_swap для записи (так как я знаю его старое значение, поэтому его передача гарантирует, что значение всегда будет меняться), но не добавит ли это ненужных накладных расходов?

6
задан Mecki 22 August 2011 в 14:29
поделиться