Мы с коллегой пишем мягко. ПО для различных платформ, работающих на x86, x64, Itanium, PowerPC и других серверных процессорах 10-летней давности.
Мы только что обсудили, достаточно ли функций мьютекса, таких как pthread_mutex_lock () ... pthread_mutex_unlock (), сами по себе, или же защищенная переменная должна быть изменчивой.
int foo::bar()
{
//...
//code which may or may not access _protected.
pthread_mutex_lock(m);
int ret = _protected;
pthread_mutex_unlock(m);
return ret;
}
Меня беспокоит кеширование. Может ли компилятор поместить копию _protected в стек или в регистр и использовать это устаревшее значение в присваивании? Если нет, то что этому мешает? Уязвимы ли варианты этого шаблона?
Я предполагаю, что компилятор на самом деле не понимает, что pthread_mutex_lock () - это специальная функция, поэтому мы просто защищены точками последовательности?
Большое спасибо.
Обновление: Хорошо , Я вижу тенденцию с ответами, объясняющими, почему волатильность - это плохо. Я уважаю эти ответы, но статьи на эту тему легко найти в Интернете. То, что я не могу найти в Интернете, и причина, по которой я задаю этот вопрос, заключается в том, как я защищен без volatile. Если приведенный выше код правильный, как он неуязвим для проблем с кешированием?
За исключением самого простого алгоритма спин-блокировки, взаимоисключающий код вполне включен : хорошая оптимизированная взаимоисключающая блокировка/код снятия блокировки содержит вид кода даже превосходная борьба программиста для понимания. Это использует особенный, сравнивают и устанавливают инструкции, справляется не только, разблокировал/блокировал состояние, но также и очередь ожидания, дополнительно системные вызовы использования, чтобы войти в состояние ожидания (для блокировки) или разбудить другие потоки (для разблокировали).
нет никакого способа, которым средний компилятор может декодировать и "понять" весь этот сложный код (снова, за исключением простой спин-блокировки), неважно, путь, поэтому даже для компилятора, не знающего, что взаимное исключение, и как это касается синхронизации, нет никакого пути на практике, компилятор мог оптимизировать что-либо вокруг такого кода .
Это - то, если код был "встроен", или доступен для, анализируют в целях перекрестной оптимизации модуля, или если глобальная оптимизация доступна.
я предполагаю, что компилятор на самом деле не понимает, что pthread_mutex_lock () является специальной функцией, также - мы просто защищены точками последовательности?
компилятор не знает то, что он делает, не пытается оптимизировать вокруг этого.
, Как это является "особенным"? Это непрозрачно и рассматривается как таковой. Это не является особенным среди непрозрачных функций .
нет никакого семантического различия с произвольной непрозрачной функцией, которая может получить доступ к любому другому объекту.
Мое беспокойство кэшируется. Компилятор мог поместить копию _protected на стеке или в регистре и использовании, которые лишают значение новизны в присвоении?
Да, в коде, которые действуют на объекты прозрачно и непосредственно, при помощи имени переменной или указателей способом, за которым компилятор может следовать . Не в коде, который мог бы использовать произвольные указатели для косвенного использования переменных.
Так да между вызовами к непрозрачным функциям . Не через.
И также для переменных, которые могут только использоваться в функции по имени: для локальных переменных, которые не имеют или их адреса взятыми или ссылки связанный с ними (таким образом, что компилятор не может следовать за всем дальнейшим использованием). Они могут действительно "кэшироваться" через произвольные вызовы, включают, блокируют/разблокируют.
В противном случае, что предотвращает это? Действительно ли изменения этого шаблона уязвимы?
Непрозрачность функций. Не встраивание. Ассемблерный код. Системные вызовы. Сложность кода. Все, что заставляет компиляторы прыгнуть с парашютом и думать, "что это усложнило материал просто, выполняет вызовы к нему".
положение по умолчанию компилятора всегда, "давайте выполнимся глупо, я не понимаю то, что делается так или иначе" не, "Я оптимизирую, которые переписывают алгоритм, который я знаю лучше". Большая часть кода не оптимизирована в комплексе не локальный путь.
Теперь позволяют нам принять абсолют, хуже (с точки зрения, которая является, что компилятор должен сдаться, который является абсолютом лучше всего из точки зрения алгоритма оптимизации):
затем у нас могла бы быть проблема, поскольку компилятор мог оптимизировать вокруг вызова функции . Это фиксируется тривиально путем вставки барьера компилятора, такого как пустой asm оператор с "ударением" для других доступных переменных. , Который означает, что компилятор просто предполагает, что что-либо, что могло бы быть доступно для вызванной функции, "ударено".
или должна ли защищенная переменная быть энергозависима.
можно сделать это энергозависимым по обычной причине, Вы делаете вещи энергозависимыми: чтобы убедиться смочь получить доступ к переменной в отладчике, препятствовать тому, чтобы переменная с плавающей точкой имела неверный тип данных во времени выполнения, и т.д.
Создание, это энергозависимый на самом деле даже не устранило бы проблему, описанную выше, поскольку энергозависимый по существу операция памяти в абстрактной машине, которая имеет семантику операции ввода-вывода , и как таковой только заказан относительно [1 139]
Энергозависимый, не заказан относительно побочных эффектов энергонезависимой памяти. , Который делает энергозависимым практически бесполезный (бесполезный для практических применений) для написания ориентированного на многопотоковое исполнение кода даже в наиболее конкретном случае, где энергозависимый, был бы априорный справка, случай, где никакой забор памяти никогда не необходим: при программировании поточной обработки примитивов в системе разделения по времени на единственном ЦП. (Который может быть одним из наименее понятых аспектов или C или C++.)
Поэтому, в то время как энергозависимый предотвращает "кэширование", энергозависимый даже не предотвращает переупорядочение компилятора, блокируют/разблокируют операцию, если все совместно используемые переменные не энергозависимы .