bublik 0 15 февраля, 2015 Опубликовано 15 февраля, 2015 (изменено) · Жалоба Зачем нужен барьер памяти (DMB) перед LDREX Здравствуйте, к сожалению не смог найти ответ на вопрос: зачем нужен барьер памяти (DMB) перед LDREX. Суть вопроса: В архитектурах ARMv6 и ARMv7 вместо операции SWP нужно использовать пару: LDREX/STREX. Вот так например будет выглядеть атомарная операция сложения: void atomic_add(int *obj; int val) .try: Ldrex r2, [r0] add r2, r2, r1 strex r3, r2, [r0] teq r3, #0 bne .try bx lr Все прекрасно работает и т.п. Но это если функция атомарного сложения у нас void. Если же мы сделаем ее, чтобы она возвращала результат: int atomic_add(int *obj; int val) .try: Ldrex r2, [r0] mov r12, r2 add r2, r2, r1 strex r3, r2, [r0] teq r3, #0 bne .try DMB //барьер mov r0, r12 bx lr Добавляется барьер (DMB) – это сделано для того, что если мы будем использовать данную функцию для реализации примитива синхронизации, мы при входе в критическую секцию знали (была дана гарантия), что те данные которые мы защищаем (работаем в критической секции) были в валидном состоянии (все операции по сохранению были завершены) подробнее в Barrier_Litmus_Tests_and_Cookbook_A08.pdf (http://infocenter.arm.com/help/topic/com.arm.doc.genc007826/Barrier_Litmus_Tests_and_Cookbook_A08.pdf) Но мне не понятно, зачем gcc 4.9.2 для атомарных операций (С11) типа atomic_fetch_add Вставляет dmb, до ldrex: int atomic_fetch_add(int *obj; int val) DMB SY // я не понимаю зачем нужен этот барьер .try: Ldrex r2, [r0] mov r12, r2 add r2, r2, r1 strex r3, r2, [r0] teq r3, #0 bne .try DMB SY //барьер mov r0, r12 bx lr Аналогично сделано для атомарных операций в ядре Linux: /arch/arm/include/asm/atomic.h Нашел коммит, который добавляет все это дело: https://git.kernel.org/cgit/linux/kernel/gi...0e59aa68af3b43a Автор говорит, что это требуется для операций, которые возвращают результат (с нижним DMB – понятно) но верхний ? Зачем нужный DMB до LDREX ? Спасибо. Изменено 22 ноября, 2022 пользователем haker_fox Добавил теги. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 15 февраля, 2015 Опубликовано 15 февраля, 2015 · Жалоба может чтобы операнды на всякий пожарный подтянуть? Мало ли откуда они идут, может из какой-то функции без барьеров? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bublik 0 15 февраля, 2015 Опубликовано 15 февраля, 2015 · Жалоба Страница 17, раздел 7.1 - да Ldrex в себе не содержат явных барьеров, и получается что Golikov A. прав для того, чтобы подтянуть операнды... Но тогда в ядре атомарные функции без return (. которые не возвращают результат) тоже должны иметь барьер до Ldrex. ведь мы им тоже передаем переменные, А их там нет. и код прекрасно работает. Но как только функция должна вернуть результат, аж два барьера.... Еще раз последний барьер нужен, если нас приспичит реализовать свой примитив синхронизации, а согласно: arrier_Litmus_Tests_and_Cookbook_A08.pdf п 7.2.1 - мы должны сделать барьер (чтобы при входе в критическую секцию - быть уверенными, что те данные которые мы защищаем при помощи нашей блокировки были в валидном состоянии. согласно п .7.2.2 - барьер нужен до сброса блокировки ( я так понимаю это требование из: http://infocenter.arm.com/help/index.jsp?t...qs/ka14041.html ) и так как мы можем гипотетически использовать данную атомарную функцию в своем примитиве синхронизации мы должны выполнить пункт 7.2.2 - Но так как у нас функция одна (мы не делим ее на lock, unlock) мы имеем верхний барьер. по идее он должен быти типа таким: int atomic_fetch_add(int *obj; int val) .try: Ldrex r2, [r0] mov r12, r2 add r2, r2, r1 DMB SY //Согласно п 7.2.2 до сохранения (требования для unlock) strex r3, r2, [r0] teq r3, #0 bne .try DMB SY //барьер согласно п 7.2.1 (lock) mov r0, r12 bx lr Но его засунули на вверх для большей производительности Но это мне так кажется.... Я не знаю точного ответа.. Убедите меня что я прав, или скажите где я НЕ прав. Спасибо Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 15 февраля, 2015 Опубликовано 15 февраля, 2015 · Жалоба Убедите меня что я прав, или скажите где я НЕ прав. Очень похоже, что правы: - atomic_add() и atomic_sub() не имеют барьеров, т.к. не могут использоваться как средства синхронизации - прочие обернуты барьерами как гипотетические элементы синхронизации Но его засунули на вверх для большей производительности Но это мне так кажется.... Я не знаю точного ответа.. Странно было бы его ставить теле цикла ldrex-strex. P.S. Сорри, предыдущий пост удалил, т.к. осознал, что не совсем понял вопрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
bublik 0 16 февраля, 2015 Опубликовано 16 февраля, 2015 · Жалоба Спасибо ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kimstik 0 22 марта, 2017 Опубликовано 22 марта, 2017 · Жалоба А по мне это похоже на обход эрраты ARM 782772 Там предлагают DMB перед LDREX ставить Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться