Я занимаюсь разработкой кроссплатформенного кода на C / C ++, и последняя платформа — HP-UX на базе Itanium. Соответствующая машина с информацией о процессоре может быть найдена в конце вопроса.
Мне нужно реализовать или найти атомарное сравнение и обмен для спецификаций машины и компилятора, приведенных ниже.
Я нашел несколько возможностей для решения, но не смог найти, как их использовать.
Первое возможное решение заключается в использовании _Asm_cmpxchg (документация здесь). Я не могу найти заголовок для этого или как его скомпилировать.
Второе возможное решение — написать собственную встроенную сборку с непосредственным использованием команд cmpxchg и cmpxchg8b, но я также не смог найти, как правильно это сделать. Я нашел различные ресурсы, большинство из которых пишут непосредственно на ассемблере, а не для архитектуры процессора, которая мне нужна, или не показывают достаточно конкретного примера.
Я нашел больше документации об инструкциях cmpxchg и cmpxchg8 (а также о tzcnt и lzcnt, которые приятно иметь, но не нужно) Вот. Если вы просматриваете в Google Chrome, значения страницы abosulte составляют 234 для cmpxchg и 236 для cmpxchg8.
Ограничения: Я не могу использовать стороннюю библиотеку из-за не зависящих от меня ограничений.
Результат uname -smr: HP-UX B.11.31 ia64
Модель процессора: Процессор Intel (R) Itanium (R) 9340
Компилятор -v: aCC: HP C / aC ++ B3910B A.06.28
Обновить: Мне удалось получить _Asm_cmpxchg для компиляции, но это не похоже на работу (значение остается неизменным). Для параметров я передал _SZ_W для _Asm_sz, _SEM_ACQ для _Asm_sem, _LDHINT_NONE для _Asm_ldhint, указатель на исходное 32-разрядное целочисленное значение для r3 и требуемое новое значение для r2. Я предполагаю значение параметров, учитывая, что документация очень тусклая.
В итоге я нашел решение самостоятельно, используя опцию 1. Ниже приведен пример кода, чтобы заставить его работать:
bool compare_and_swap(unsigned int* var, unsigned int oldval, unsigned int newval)
{
// Move the old value into register _AREG_CCV because this is the register
// that var will be compared against
_Asm_mov_to_ar(_AREG_CCV, oldval);
// Do the compare and swap
return oldval == _Asm_cmpxchg(
_SZ_W /* 4 byte word */,
_SEM_ACQ /* acquire the semaphore */,
var,
newval,
_LDHINT_NONE /* locality hint */);
}