Должны ли инструкции ARM ldrex/strex работать с данными, выровненными по кешу?
В Intel аргументы CMPXCHG должны быть выровнены по строке кэша (поскольку Intel использует MESI для реализации CAS).
На ARM ldrex и strex работают на эксклюзивных гранулах бронирования.
Чтобы было ясно, значит ли это, что в ARM данные, на которые нужно работать, не обязательно должны быть выровнены по строке кэша?
3 ответа
Об этом прямо говорится в Справочном руководстве по архитектуре ARM A.3.2.1 "Нераспределенный доступ к данным". LDREX
а также STREX
требует выравнивания слов. Что имеет смысл, потому что доступ к данным без выравнивания может охватывать гранулы эксклюзивного резервирования.
Эксклюзивные ограничения доступа
К исключительным доступам применяются следующие ограничения:
• Размер и длина эксклюзивной записи с заданным идентификатором должны быть такими же, как размер и длина предыдущего эксклюзивного чтения с тем же идентификатором.
• Адрес монопольного доступа должен соответствовать общему количеству байтов в транзакции.
• Адрес для эксклюзивного чтения и эксклюзивной записи должен совпадать.
• Поле ARID считываемой части эксклюзивного доступа должно соответствовать AWID записываемой части.
• Управляющие сигналы для частей чтения и записи эксклюзивного доступа должны быть идентичны.
• Количество байтов, подлежащих передаче в пакете исключительного доступа, должно быть степенью 2, то есть 1, 2, 4, 8, 16, 32, 64 или 128 байтов.
• Максимальное количество байтов, которое может быть передано в эксклюзивном пакете, составляет 128.
• Значение сигналов ARCACHE[3:0] или AWCACHE[3:0] должно гарантировать, что подчиненное устройство, отслеживающее монопольный доступ, увидит транзакцию. Например, эксклюзивный доступ, отслеживаемый ведомым устройством, не должен иметь значение ARCACHE[3:0] или AWCACHE[3:0], которое указывает, что транзакция кэшируется.
Несоблюдение этих ограничений приводит к непредсказуемому поведению.
Выше приведено в спецификации AMBA/AXI. Вы обнаружите, что AWLOCK/ARLOCK игнорируется некоторыми поставщиками (то есть ldrex/strex не будет работать вне ядра). У меня есть некоторый код, который демонстрирует это, или, по крайней мере, будет, если вы найдете систему, которая не поддерживает эксклюзивный доступ.
https://github.com/dwelch67/raspberrypi/tree/master/extest
В зависимости от задачи и того, насколько вы хотите быть переносимым, вам может потребоваться предоставить решения swp и ldrex/strex, окруженные ifdefs, и / или использовать множество доступных регистров (во время выполнения), чтобы сообщить вам, какие инструкции поддерживаются или не поддерживаются ядром. ты бежишь дальше. (Вы можете обнаружить, что по крайней мере в одном случае ни swp, ни ldrex/strex не поддерживаются).
В Intel аргументы CMPXCHG НЕ нужно выравнивать в кеше. Попробуйте, вы увидите, что это работает.
Но вы правы: в кешируемой памяти Intel использует протокол кеша для реализации CMPXCHG. Таким образом, было бы разумно не помещать две независимые переменные синхронизации с высокой интенсивностью использования в одну и ту же строку кэша - потому что, если бы два процессора синхронизировались с использованием этих разных переменных, строки кэша могли бы перебегать взад и вперед. Но это точно такая же проблема, как и для любых данных: вам не нужно, чтобы разные процессоры одновременно записывали в одну и ту же строку кэша. Ложный обмен.
Но вы, конечно, не можете кэшировать блокировки выравнивания строк:
struct Foo {
int data;
Lock lock;
int data_after;
};
Вы можете поставить разные блокировки в одну и ту же кешлайн:
struct Foo {
int data;
Lock read_lock;
int data_between;
Lock write_lock;
int data_after;
};
Поскольку чтение и письмо имеют тенденцию быть взаимоисключающими, не может быть потерь;
Вы можете поставить разные блокировки в одну и ту же кешлайн:
struct Foo {
int data;
Lock read_lock;
int data_between;
Lock write_lock;
int data_after;
};
Кстати, в не кэшированной памяти Intel не использует протокол отслеживания кэша для атомарных операций, таких как CMPXCHG. Таким образом, есть меньше причин для кэширования строчных переменных синхронизации. Но вы все еще можете захотеть: многие подсистемы памяти чередуются по размеру кэша, даже когда не кэшированы.
А что касается ARM: это почти то же самое.
На снупи-шине или без кеширования вам, возможно, не нужно слишком беспокоиться о выравнивании строк кэша.
Но в иерархии кластерного кэша у вас точно такие же проблемы, как у x86. Более того, на самом деле хорошо известно, как "экспортировать" такие операции, как CMPXCHG, но не ARM ldrexd/strexd.