Перейти к содержанию
    

Зачем нужен барьер памяти (DMB) перед LDREX

Зачем нужен барьер памяти (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 ?

 

Спасибо.

 

Изменено пользователем haker_fox
Добавил теги.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

может чтобы операнды на всякий пожарный подтянуть? Мало ли откуда они идут, может из какой-то функции без барьеров?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Страница 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

 

 

Но его засунули на вверх для большей производительности Но это мне так кажется.... Я не знаю точного ответа.. :wacko:

 

Убедите меня что я прав, или скажите где я НЕ прав.

 

Спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Убедите меня что я прав, или скажите где я НЕ прав.

Очень похоже, что правы:

- atomic_add() и atomic_sub() не имеют барьеров, т.к. не могут использоваться как средства синхронизации

- прочие обернуты барьерами как гипотетические элементы синхронизации

 

Но его засунули на вверх для большей производительности Но это мне так кажется.... Я не знаю точного ответа.. :wacko:

Странно было бы его ставить теле цикла ldrex-strex.

 

P.S. Сорри, предыдущий пост удалил, т.к. осознал, что не совсем понял вопрос.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А по мне это похоже на обход эрраты ARM 782772

Там предлагают DMB перед LDREX ставить

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...