C ++ volatile: гарантированный 32-битный доступ? - PullRequest
2 голосов
/ 22 января 2020

В моем Linux C ++ проекте у меня есть область аппаратной памяти, отображенная где-то в физическом адресном пространстве , к которой я обращаюсь с помощью указателей uint32_t после mmap .

Выпуск сборки приложения завершается с SIGBUS (ошибка шины) .

Это происходит потому, что компилятор оптимизирует доступ к вышеупомянутой аппаратной памяти, используя 64-битный доступ , вместо того, чтобы придерживаться 32-битной => ошибки шины, доступ к аппаратной памяти возможен только с использованием 32-битной читает / пишет .

Я пометил указатель uint32_t как volatile .

Работает. Для этой определенной c части кода не менее . Потому что компилятору сказано не делать переупорядочение. И большую часть времени пришлось бы менять порядок для оптимизации.

Я знаю, что volatile контролирует , когда компилятор обращается к памяти. Вопрос в следующем: volatile также сообщает компилятору , как получить доступ к памяти, то есть , чтобы получить к нему доступ именно так, как программист указывает ? Я гарантирую, что компилятор всегда будет придерживаться 32-битного доступа к энергозависимым буферам uint32_t?

Например, гарантирует ли volatile то, что компилятор будет обращаться к 2 последовательных операций записи к 2 последовательным 32-битным значениям в следующем фрагменте кода, используя также 32-битные операции чтения / записи?

void aFunction(volatile uint32_t* hwmem_array)
{
    [...]

    // Are we guaranteed by volatile that the following 2 consecutive writes, in consecutive memory regions
    // are not merged into a single 64-bit write by the compiler?
    hwmem_array[0] = 0x11223344u;
    hwmem_array[1] = 0xaabbccddu;

    [...]
}

1 Ответ

0 голосов
/ 22 января 2020

Я думаю, что ответил на свой вопрос, пожалуйста, поправьте меня, если я ошибаюсь.

C99 стандартный черновик : http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Цитаты:

«

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

Раздел 5.1.2.3:

«

2 Доступ к изменчивому объекту , изменение объекта, изменение файла или вызов функции, выполняющей любую из этих операций все побочные эффекты, которые являются изменениями в состоянии среды выполнения. Оценка выражения может вызывать побочные эффекты . В определенных точках последовательности выполнения, называемых точками последовательности , все побочные эффекты предыдущих оценок должны быть полными, и никаких побочных эффектов последующие оценки должны быть проведены . (Сводная информация о точках последовательности приведена в приложении C.)

5 Минимальные требования к соответствующей реализации: - В точках последовательности летучие объекты стабильный в том смысле, что предыдущие обращения завершены, а последующие обращения еще не произошли .

Приложение C (информативное) Точки последовательности:

«

1 Ниже приведены точки последовательности, описанные в 5.1.2.3:

[…]

- конец полного выражения : инициализатор (6.7.8); выражение в выражении выражения (6.8.3); управляющее выражение оператора выбора (if или switch) (6.8.4); управляющее выражение оператора while или do (6.8.5); каждое из выражений оператора for (6.8.5.3); выражение в операторе возврата (6.8.6.4).

Таким образом, теоретически мы гарантируем, что в конце любого выражения, включающего изменчивый объект, изменчивый объект записывается / читается, как было указано компилятору .

...