Существует ли Windows API для атомарной установки 16-байтового массива? - PullRequest
1 голос
/ 24 марта 2012

Мне было интересно, есть ли в Windows API-интерфейс для атомарной установки 16-байтового массива?

Мне бы очень не хотелось вводить критические секции или мьютексы, чтобы реализовать эти операции, поэтому я пытаюсьнайти более простое решение.

PS.Мне это нужно, потому что этот 16-байтовый массив может быть записан из рабочего потока и в основном считан из основного потока.

1 Ответ

4 голосов
/ 24 марта 2012

Все перечисленное подразумевает 64-битную архитектуру x86_64.Я считаю, что в целом то, о чем вы просили, невозможно на 32-битной x86.

На самом деле есть два варианта.Первым является _InterlockedCompareExchange128, что означает LOCK CMPXCHG16B.Чтобы дублировать функциональность 16-байтового хранилища с ним, вам нужно сделать что-то вроде этого:

__int64* dest = ...;
__int64* orig = ...;
unsigned char ok;
do
{
    __int64 high = dest[0];
    __int64 low  = dest[1];
    ok = _InterlockedCompareExchange128(dest, high, low, orig);
}
while (!ok);

Обратите внимание, что, поскольку это операция с блокировкой, она подразумевает эквивалент _ReadWriteBarrier.Обычно это то, что подразумевается под «атомарной» операцией.

Если вы хотите чистый магазин, а не обмен сравнения, тогда вы можете использовать все, что преобразуется в согласованное 16-байтовое хранилище на оборудовании.Например, инструкция MOVDQA будет соответствовать.В C ++ это выглядело бы примерно так:

__m128i* dest = ...;
_mm_mfence();
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig));
_mm_mfence();

Если у вас нет причин избегать инструкций SSE, я думаю, что вторая версия может работать лучше.Вы также можете решить, хотите ли вы ослабить два барьера памяти в зависимости от ваших реальных потребностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...