Я работаю над встроенной ОС для ARM. Однако есть несколько вещей, которые я не понимал в архитектуре даже после обращения к ARMARM и источнику Linux.
Атомные операции.
ARM ARM говорит, что инструкции Load и Store являются атомарными, и выполнение гарантировано завершено до выполнения обработчика прерываний. Проверено, посмотрев
arch/arm/include/asm/atomic.h :
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
Однако проблема возникает, когда я хочу управлять этим значением атомарно, используя инструкции cpu (atomic_inc, atomic_dec, atomic_cmpxchg и т.д.), которые используют LDREX и STREX для ARMv7 (моя цель).
ARMARM ничего не говорит о блокировке прерываний в этом разделе, поэтому я предполагаю, что прерывание может происходить между LDREX и STREX. Дело в том, что речь идет о блокировке шины памяти, которая, по моему мнению, полезна только для систем MP, где в то же время может быть больше процессоров, пытающихся получить доступ к одному и тому же местоположению. Но для UP (и, возможно, MP), если в этом маленьком окне LDREX и STREX срабатывает прерывание таймера (или IPI для SMP), обработчик Exception выполняет, возможно, изменения cpu-контекста и возвращается к новой задаче, однако теперь поразительная часть, он выполняет "CLREX" и, следовательно, удаляет любую исключительную блокировку, удерживаемую предыдущим потоком. Итак, насколько лучше использовать LDREX и STREX, чем LDR и STR для атомарности в системе UP?
Я прочитал что-то об эксклюзивном мониторе блокировки, поэтому у меня есть возможная теория о том, что когда поток возобновляется и запускается STREX, монитор os вызывает этот вызов, который может быть обнаружен, и цикл может быть повторно выполнен используя новое значение в процессе (ответьте на LDREX), Am я прямо здесь?