Барьеры нужны для того, чтобы гарантировать порядок выполнения операций в многопоточных системах.
На классификацию барьеров влияют:
- виды операций, порядок которых надо гарантировать (операции чтения, операции записи, полные)
- уровень механизма выполнения (часть упорядочивания выполняется компилятором, остальное - процессором)
- виды потоков (разделение потоков на уровне ядра = HyperThreading), потоки собственно ядер когда гипертридинга нет, потоки разных процессоров
итого, мы имеем примерно 3 * 2 * ~3 ~= 18 видов барьеров
где-то в линуксе (в смысле в коде ядра) есть макрос barrier(), это полный програмный барьер (т.е. обеспечивается компилятором)
задание пытливому читателю - найти текст макроса и детально объяснить как работает, например что именно означает инструкция
asm volatile("": : :"memory")
в gcc есть ключевое слово __sync_synchronize, которое компилятором преобразуется в аппаратный барьер, то есть для архитектуры x86 генерируются инструкции MFENCE/SFENCE или что-нибудь с префиксом LOCK.
Вообще у меня ощущение, что при таком количестве разных видов барьеров синтаксических конструкций должно быть побольше, чем две (две - это макрос и ключевое слово, выписанные выше). Т.е. нужно по-подробнее изучить соответствующие ассемблерные команды.
И как эти команды используются в gcc
https://gcc.gnu.org/onlinedocs/gcc-4.4. … ltins.html
Отредактировано Лис (2017-07-14 14:40:39)