//offtop по поводу #12. lock xchg ... ни у кого #GP не вызывает? P.S. пардон, разобрался. lock xchg rax, rbx
Mika0x65 Извиняюсь. Возможно, я неправильно понял вопрос. Разбиение одного четырёхбайтового чтения на 4 цикла чтения по одному байту невозможно (максимум на два в случае невыравненных данных). А разбиение на две неатомарные операции чтения/записи вполне возможно при невыравненных данных (точнее каждая из них атомарная, но общая операция доступа к памяти будет уже неатомарной).
Это из Intel Manual сведения? Потому что, например, word по адресу 1 тоже считается невыравненными данными. Ну, с read-modify-write, вроде, разобрались. Осталось два вопроса -- насчет примера, который я привел и сериализация.
Отвечаю на конкретный вопрос - приведенный пример вообще совершенно "дебильный" и не решает проблем с выравниванием, о которых вы тут так печетесь. Во-первых, если уж юзать Interlocked в #1 , то только так как положено: Код (Text): while (InterlockedCompareExchange(&nCPUsLocked, nOtherCPUs, nOtherCPUs) != nOtherCPUs) А в примере #1 юзается прямое чтение\сравнение (nCPUsLocked != nOtherCPUs) со всеми вытекающими из ваших рассуждений опасениями (о, ужОс!!!). Последующая же Interlocked-операция вообще ничего (полезного) не делает и может рассматриваться либо либо как (нехилая) задержка в цикле, либо просто как "мартышкины очки" или "горе от ума" Во-вторых, (чтобы подлить масла в огонь) гляньте в описание InterlockedCompareExchange и других Interlocked, и увидите "грозное" предепреждение: Можно конечно развернуть дискуссию на 10 страниц о правомерности данного заявления к x86, но лучше этого не делать и следовать данным рекомендациям, тем более, что все современные высокоуровневые компиляторы автоматом выравнивают данные, и нужно самому "сильно постараться", чтобы искусственно сбить выравнивание. Ну а ежели и для Interlocked-функций нужно (перестраховочное) выравнивание переменной, то все рассуждения о возможной неатомарности простого чтения идут лесом вместе с мартышкиными выкрутасами вокруг использования Interlocked для простого чтения\сравнения Что же касается какой-то "сериализации", то тут вообще сказать нечего, т.к. Interlocked-функции лишь обеспечивают атомарность операций read-midify-write, сами же эти операции на разных ядрах выполняются на конкурентной основе "кто успел, тот и съел", поэтому не понятно, о какой сериализации тут можно говорить.
Нашел я сообщение, которое меня смущало. https://wasm.ru/forum/viewtopic.php?pid=279018#p279018 PROFi с убедительной цитатой из Intel Manual утверждает, что 'mov [A], 0xFFFFFFFF' может выполниться "частями" при невыравненном адресе.
Достали уже эти страшилки про невыравненные адреса. Ладно бы речь шла об обязательности\необязательности выравнивания вообще (десятков, сотен переменных), но в данном случае же речь идет о совершенно конкретном использования одной-двух переменных для межпоточных взаимодействий. Неужели нельзя просто подумать\позаботиться об их выравнивании нежели "плясать с бубном" вокруг Interlocked-функций, которые согласно мсдн, также требуют выравнивания переменных ?!!
leo Ну, я же писал, что вопрос академический. Понятно, что выравнивание спасет всех отцов русской демократии, что за этим следит компилятор и т.д. Если бы речь шла о сугубо практическом подходе, я бы оставил все LOCK'и во имя безопасности и начал бы чесаться только в том случае, если начались тормоза. Но хочется разобраться же.
Ок, опишу ситуацию в моей голове. С 'cmpxchg' все ясно, префикса в InterlockedIncrement достаточно, чтобы обезопасить чтение переменной даже обычным 'mov'ом. Теперь про ситуацию 'mov m, r' & 'mov r, m'. Допустим, операции чтения/записи по невыравненным адресам атомарны. Тогда LOCK остается только для read-modify-write, чтобы избежать ситуации read0, read1; modify0, modify1; write0, write1. Допустим, операции чтения/записи по невыравненным адресам не атомарны. Тогда 'mov m, r' & 'mov r, m' небезопасны и надо заменить 'mov m, r', например, на 'xchg', чтобы LOCK нас обезопасил.
Mika0x65 Это из здравого смысла сведения. Глупо было бы по 64-разрядной шине данных гонять четыре байта побайтово. leo Ща достанем цитатку из Intel Manuals... По крайней мере я говорил об этой сериализации.
l_inc Ну ежели углубляться в тонкости, то само собой разумеется, что lock может\должен блокировать доступ к памяти только после завершения предыдущих операций чтения\записи. Вопрос в том "но зачем?" форсировать их завершение, да еще и при этом переписывать значение переменной, провоцируя инвалидацию соотв-х линеек кэша других ядер ? Из более или менее разумных объяснений - только напряг процессора с целью увеличения задержки цикла
leo Ладно. Спасибо. Примем, что, если хоть какой-то смысл в этих вызовах и есть, то необходимости нет гарантированно.