ARM: Нужны ли LDRX/STRX, если прерывания отключены?

Я работаю с многопоточным приложением C/Assembler на чистом металле на Cortex-A9.

У меня есть некоторые общие переменные, то есть адреса, которые используются более чем в одном потоке. Чтобы выполнить атомарный обмен значениями переменных, я использую LDRX и STRX. Теперь мой вопрос: нужны ли мне LDRX и STRX при каждом доступе к одной из этих переменных, даже если прерывания отключены.

Предположим следующий пример:

  • Поток 1 использует LDRX и STRX для обмена значением адреса a.
  • Поток 2 отключает прерывания, использует обычные LDR и STR для обмена значением адреса a, делает что-то еще, что не должно прерываться, а затем снова разрешает прерывания.

Что произойдет, если поток 1 будет прерван сразу после LDRX потоком 2? STRX в потоке 1 все еще распознает, что был доступ по адресу a, или мне нужно использовать LDRX и STRX и в потоке 2?


person user3035952    schedule 28.05.2014    source источник
comment
Если ваша основная линия использует LDRX/STRX, вы должны сделать то же самое в прерываниях. LDRX резервирует место в памяти. Чтобы STRX сигнализировал о повторной попытке, каждый, кто использует память, должен использовать LDRX; вы не можете смешивать и сочетать доступ. MRC p15, 0, <Rd>, c0, c0, 1 возвращает ERG, то есть размер, который LDRX/STRX резервирует. Прочитайте об эксклюзивных мониторах.   -  person artless noise    schedule 28.05.2014
comment
См.: LDREX/STREX и кэш, вопрос ERG, вопрос по Linux atomic_inc. Некоторые концепции LDRX/STRX немного чужды. Что касается вопроса Linux atomic_inc, я думаю, вы думаете о атомном и без блокировки; см. там мой вики-ответ, за который проголосовали против.   -  person artless noise    schedule 28.05.2014
comment
ldrex и strex предназначены для того, чтобы гарантировать, что в многоядерном процессоре код вашего ядра имел эксклюзивный доступ к ячейке памяти, по сути, никто другой не вмешивался в эту ячейку между выполнением вами двух отдельных транзакций. Режимы прерывания и т. д. не имеют к этому никакого отношения, либо вам нужно использовать пару инструкций, либо нет.   -  person old_timer    schedule 28.05.2014
comment
у нас был этот аргумент бесчисленное количество раз, ldrex/strex не являются обязательными для однопроцессорных систем, и есть системы в этой области, где они не поддерживаются.   -  person old_timer    schedule 28.05.2014
comment
Да, это необязательно. Если он есть на одном ядре, то он будет работать. Для ОП кора головного мозга a9 кажется, включает поддержку. Вероятно, будет разумно прочитать документацию поставщика и протестировать поддержку; иногда разработчики удаляют что-то, даже если ARM документирует это как поддерживаемое.   -  person artless noise    schedule 28.05.2014
comment
если вы остаетесь в пределах логики руки, кеши будут работать, если/когда это коснется логики поставщика, то это может быть или не быть, и это может следовать другому набору правил или интерпретации правил. Как правило, кеши включены, и логика поставщика никогда не видит эксклюзивный доступ, поэтому все находится в сфере оружия.   -  person old_timer    schedule 28.05.2014


Ответы (2)


LDREX/STREX — это то, что должен реализовать производитель чипа, надеюсь, в соответствии со спецификацией оружия. Вы можете и должны получить документацию по армам по теме, в этом случае в дополнение к армам и trms вы должны получить документацию amba-axi.

Итак, если у вас есть

ldrex thread 1
interrupt
ldrex thread 2
strex thread 2
return from interrupt
strex thread 1

Между потоком 2 ldrex и strex не было изменений в этой области памяти, поэтому strex должен работать. Но между потоком 1 strex и предыдущим ldrex произошла модификация этого местоположения, поток 2 strex. Таким образом, теоретически это означает, что поток 1 strex должен дать сбой, и вам придется снова попробовать свою пару потока 1 ldrex/strex, пока она не заработает. Но это именно так, вы продолжаете пробовать пару ldrex/strex в цикле, пока не добьетесь успеха.

Но все это определяется реализацией, поэтому вам нужно смотреть на конкретного поставщика чипа, модель и версию и проводить свои собственные эксперименты. Ошибка в linux, например, заключается в том, что ldrex/strex представляет собой бесконечный цикл, применив его к системе/ситуации, где ldrex/strex не поддерживается, вы получите OKAY вместо EXOKAY, и strex навсегда выйдет из строя, вы застряли в этом бесконечный цикл навсегда (всегда удивляюсь, откуда я все это знаю, пришлось отлаживать эту проблему на логическом уровне).

Во-первых, ARM документирует, что поддержка монопольного доступа не требуется для однопроцессорных систем, поэтому пара ldrex/strex МОЖЕТ не работать, ЕСЛИ вы коснетесь специфической логики поставщика в одноядерных системах. Однопроцессорный или нет, если ваш ldrex/strex остается в пределах логики руки (кеши L1 и дополнительные кэши L2), тогда пара ldrex/strex управляется ARM, а не поставщиком чипа, поэтому вы подпадаете под один набор правил, если пара касается системной памяти. вне ядра руки, то вы подпадаете под правила поставщиков.

Большая проблема заключается в том, что документация ARM необычайно неполна по этой теме. В зависимости от того, какое руководство и где в руководстве вы читаете, например, говорится, что какой-то ДРУГОЙ мастер изменил это местоположение, которое в вашем случае является тем же мастером, поэтому местоположение было изменено, но поскольку это было вами, второй strex должен быть успешным . Затем в том же документе говорится, что еще одно монопольное чтение сбрасывает монитор на другой адрес, а что, если это еще одно монопольное чтение того же адреса?

По сути, ваш вопрос заключается в том, что насчет двух эксклюзивных записей на один и тот же адрес без эксклюзивного чтения между ними, делает ли / должен ли второй успех. Очень хороший вопрос... Я не вижу однозначного ответа ни во всех ядрах рук, ни во всем мире чипов на основе рук.

Суть в том, что ldrex/strex не полностью зависит от ядра ARM, но также зависит от чипа (поставщика). Вам нужно провести эксперименты, чтобы убедиться, что вы можете использовать эту пару инструкций в этой системе (однопроцессорной или нет). Вам нужно знать, что делает ядро ​​ARM (кеши) и что происходит, когда этот эксклюзивный доступ выходит за пределы ядра к логике поставщика. Повторите для каждого ядра и поставщика, которому вы хотите перенести этот код.

person old_timer    schedule 28.05.2014
comment
Необычно то, что в приведенном выше ответе dwelch есть несколько прямо неверных утверждений. Я читал те же документы и не удивлен, что они вызвали путаницу. Кэш-память управляется только с помощью локального монитора и не зависит от реализации какого-либо глобального монитора. В многоядерной системе отсутствие глобального монитора для ОЗУ фактически нарушает спецификацию архитектуры (но это произошло). Биты, называемые реализацией, определенные в Справочном руководстве по архитектуре ARM (в отношении мониторов), не повлияют на функциональность правильного кода. - person unixsmurf; 29.05.2014
comment
вам нужно прочитать больше документов, если вы не можете найти то, на что я ссылался. Документы ARM/TRM/AMBA-AXI противоречат сами себе и являются неполными в отношении вопроса плакатов и, в частности, неполными в отношении ошибок, обнаруженных в Linux, и других предположений, сделанных в отношении этих инструкций. Программисты думают, что они являются прямой заменой swp, потому что это подразумевает arm, но это не совсем то, как они работают. и, в конце концов, это реализация, поскольку это должен реализовать отдельный человек в какой-то компании по производству чипов. - person old_timer; 29.05.2014
comment
получите комнату, полную инженеров, вы получите комнату, полную различных решений, основанных на интерпретации документации. - person old_timer; 30.05.2014
comment
Если вы просто кэшируете область, то вы, по крайней мере, находитесь в сфере ARM, которая по-прежнему будет варьироваться от архитектуры к архитектуре, но она должна быть более последовательной, чем поставщик к поставщику. - person old_timer; 30.05.2014

Извиняюсь за то, что просто бросил заявление «это неправильно», но вчера у меня не было времени написать правильный ответ. Ответ dwelch на ваш вопрос правильный, но его части, по крайней мере, можно неправильно истолковать.

Короткий ответ: да, вам нужно либо отключить прерывания для обоих потоков, либо использовать ldrex/strex для обоих потоков.

Но уточним одну вещь: поддержка ldrex/strex является обязательной для всех процессоров ARM v6 или более поздней версии (за исключением микроконтроллеров v6M). Однако поддержка SWP не является обязательной для некоторых процессоров ARMv7.

Поведение ldrex/strex зависит от того, включен ли ваш MMU и какой тип памяти и атрибуты настроены для доступной области. Для некоторых возможных конфигураций потребуется добавить дополнительную поддержку либо в контроллеры межсоединений, либо в контроллеры оперативной памяти, чтобы ldrex/strex мог работать правильно.

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

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

Теперь dwelch прав в том смысле, что вокруг него слишком много «определяемых реализацией» опций. Описанная вами последовательность НЕ архитектурно гарантирует работу. Архитектура не требует, чтобы str переводил локальный (или глобальный) монитор из монопольного в открытое состояние (хотя в некоторых реализациях это возможно).

Следовательно, архитектурно безопасными вариантами являются:

  1. Используйте ldrex/strex в обоих контекстах.
  2. Отключите прерывания в обоих контекстах.
person unixsmurf    schedule 29.05.2014