Здравствуйте, к сожалению не смог найти ответ на вопрос: зачем нужен барьер памяти (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
.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
.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
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 ?
Спасибо.