Переупорядочивание компилятора вокруг границ мьютекса? - PullRequest
7 голосов
/ 23 апреля 2010

Предположим, у меня есть свои собственные не встроенные функции LockMutex и UnlockMutex, которые используют некоторый надлежащий мьютекс - такой как boost - внутри. Как компилятор узнает, что не нужно переупорядочивать другие операции, связанные с вызовами LockMutex и UnlockMutex? Он не может знать, как я буду реализовывать эти функции в каком-то другом модуле компиляции.

void SomeClass::store(int i)
{
  LockMutex(_m);
  _field = i;  // could the compiler move this around?
  UnlockMutex(_m);
}

ps. Предполагается использовать экземпляры классов для удержания блокировок, чтобы гарантировать разблокировку. Я упустил это, чтобы упростить пример.

Ответы [ 6 ]

2 голосов
/ 23 апреля 2010

Не может знать, как я буду реализовывать эти функции в каком-то другом модуле компиляции.

Это ключ - поскольку компилятор не может (в общем) знать о реализации вызовов функций, он не может переместить хранилище на _field вне этих вызовов функций.

Обычно, поскольку _field доступен вне SomeClass::store() (это не локально), компилятор не может знать, был ли он изменен внешней функцией, поэтому он должен выполнить сохранение до _field между последовательность вызова функции указывает.

Базовой аппаратной платформе может потребоваться некоторое внимание в виде барьеров памяти или сбросов кеша, чтобы справиться с операциями кэширования или неупорядоченными операциями, которые происходят на аппаратном обеспечении. Внедрение платформой API-интерфейсов mutex будет решать эти проблемы в случае необходимости.

2 голосов
/ 23 апреля 2010

В общем, компилятор не будет перемещать код, если он не знает с уверенностью, что это не повлияет на поведение во время выполнения.

1 голос
/ 23 апреля 2010

Вы правы, этот код правильный и безопасный.Хотя я подумал о «шутке кода».

pthread_mutex_lock( &mx ) + foo() + pthread_mutex_unlock( &mx );
1 голос
/ 23 апреля 2010

Как написано, если функции не встроены, компилятор не будет перемещать присвоение переменной, так как вызов может быть не связан с переменной _field, но он должен сохранять строгий порядок вызовов. Однако, если компилятор решит встроить вызовы, я думаю, что он будет обрабатывать их как блоки независимого кода, то есть он будет только переупорядочивать команды в пределах одной и той же единицы кода (самой встроенной функции), но не с помощью следующего или предшествующего код (присвоение переменной _field).

0 голосов
/ 23 апреля 2010

Если компилятор не может гарантировать, что вызовы функций не будут иметь побочных эффектов, которые изменят переменные между вызовами, он не сможет переместить код. Если переменная является локальной переменной, и вы никогда не брали ссылку и не создавали указатель на нее, компилятор может предположить, что ее можно безопасно перемещать; Я не знаю.

0 голосов
/ 23 апреля 2010

Если бы компилятор делал это, это был бы плохой компилятор.; -)

...