ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
25 апреля
842962 Топик полностью
fk0, легенда (24.05.2018 00:35, просмотров: 249) ответил Николай Коровин на Неееее, я именно про барьерные инструкции проца в их аппаратном смысле. С компилятором действительно договориться проще, volatile, char*... Проблема именно в том, что инфа о том, когда сам камень может переставить команды -- весьма противоречива.
Уже миллион раз обсуждали, не хочется повторяться. volatile и memory barrier -- оба нужны, у них разный ортогональный смысл. Компилятор имеет право всё переупорядочить, в память не писать, а кешировать в регистрах, и вообще вытворять всё что вздумается, лишь бы результат и побочные эффекты были такие же. Но при этом в момент прохождения барьера всё незаписанное в память должно быть записано (присвоения неавтоматических переменных и т.п.) Барьер может быть явный (для gcc -- asm volatile("": : :"memory")), либо неявный (любой вызов функции, кроме inline функций, и видимо статических/локальных для модуля, является барьером). Спецификатор типа volatile лишь запрещает оптимизации и заставляет обращаться к переменной, запрещает её кеширование в регистре. Но он не говорит о том когда это обращение должно быть фактически выполнено и запросто можно получить оптимизацию такую, когда ты, например, пишешь в volatile, чтоб обработчик прерывания понял, и потом только меняешь в глобальном буфере что-то. А компилятор генерирует тебе код, когда он вначале меняет в буфере (порядок разный), а запись в volatile вообще выносит в конец функции перед выходом предпоследней операцией! Ему так удобнее (в конце регистр свободный нашёлся для временного значения). И логика синхронизации с параллельными потоками (обработчиком прерывания) развалилась. И здесь вот нужен и явный volatile (чтоб вообще если сказано записать два раза -- то так и сделал, а не записал только в последний раз), и явный барьер между операциями (чтоб вот в точке барьера всё записано было). Барьерных инструкций (sync у MIPS, lock у x86) это вообще не касается, речь про барьер для компилятора и актуально даже на однопроцессорной машине. Барьерные инструкции нужны на многопроцессорных. Ну и инструкция sync имеет ещё такой смысл, что она дожидается записи всего, что застряло в конвейере у процессора. В том смысле, что следующая инструкция уже может прочитать записанное, а не некий старый результат (для x86 вроде не актуально).
[ZX]