В первых двух статьях цикла мы рассмотрели четыре способа упорядочить доступ к памяти: load-acquire и store-release операции в первой части, барьеры чтения и записи в память — во второй. Теперь пришла очередь познакомиться с полными барьерами памяти, их влиянием на производительность, и примерами использования полных барьеров в ядре Linux.
Рассмотренные ранее примитивы ограничивают возможный порядок исполнения операций с памятью четырьмя различными способами:
- Load-acquire операции выполняются перед последующими чтениями и записями.
- Store-release операции выполняются после предыдущих чтений и записей.
- Барьеры чтения разделяют предыдущие и последующие чтения из памяти.
- Барьеры записи разделяют предыдущие и последующие записи в память.
Внимательный читатель заметил, что одна из возможных комбинаций в этом списке отсутствует:
Чтение выполняется... | Запись выполняется... | |
… после чтения | smp_load_acquire(), smp_rmb() | smp_load_acquire(), smp_store_release() |
… после записи | ??? | smp_store_release(), smp_wmb() |