Изменение порядка доступа к нескольким переменным в C - PullRequest
0 голосов
/ 03 сентября 2018

В этом примере:

volatile uint32_t * pOne = 0xDEADBEEF;
volatile uint32_t * pTwo = 0x0BADC0DE;

void same(void)
{
    uint32_t tmp;

    tmp = *pOne;   // A
    *pOne = 0;     // B
    *pOne = tmp;   // C
}

void different(void)
{
    uint32_t tmp;

    tmp = *pOne;
    *pOne = 0;     // E
    *pTwo = 0;     // F
    *pOne = tmp;
}

Насколько мне известно, компилятору C99 не разрешается переупорядочивать строки A, B и C в функции same(), поскольку все они ссылаются на один и тот же энергозависимый объект.
Но как насчет строк E и F в функции different()? Они взаимодействуют с различными летучими объектами.

  1. Разрешено ли компилятору C99 переупорядочивать строки E и F?

Мне не удалось найти ответ в самом стандарте, поскольку раздел 5.1.2.3 меня немного смущает. Так что, если бы вы могли объяснить это, я был бы рад.

Мне известно, что это касается только переупорядочения компилятора и не влияет на переупорядочение процессором.

  1. Так есть ли стандартная библиотека, которая (если реализована) обеспечивает барьеры памяти?

  2. На данный момент я застрял на C99, но из любопытства: есть ли изменения в C11?

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

из спецификации (6.7.3.6)

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

Получение / установка значения будет считаться «доступом» в большинстве, если не во всех реализациях.

А из 5.1.2.3:

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

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

Каждое присвоение является точкой последовательности, поэтому, если реализация не «выводит, что никакие побочные эффекты не возникают» из изменчивого доступа, это означает, что эти строки не могут быть переупорядочены в реализации, поскольку это не имело бы тот же смысловой смысл.

Конечно, многие компиляторы не соответствуют стандартам на 100%.

Здесь вы можете увидеть выходные данные ассемблера с различными компиляторами: https://godbolt.org/z/b0TNmT.

GCC, Clang и MSVC не переупорядочивают операции чтения и записи в сборке. (Хотя я не уверен, что это означает для реального исполняемого файла)

0 голосов
/ 05 сентября 2018

Реализациям допускается значительное усмотрение в отношении семантики volatile объектов. Наблюдаемое поведение программы должно быть согласовано со всеми операциями над всеми изменчивыми объектами, выполненными в указанной последовательности, но реализации имеют полное разрешение на выполнение почти всего, что не влияет на наблюдаемое поведение программы. Реализации также имеют достаточно широкое разрешение для определения - в рамках «поведения, определяемого реализацией», - какие аспекты доступа с квалификацией с изменчивой квалификацией являются и не являются «наблюдаемыми».

Соответствующая реализация, которая не предназначена для использования во встроенном программировании, может указывать, что volatile -квалифицированный доступ будет вести себя странным и произвольным образом, что сделает его непригодным для таких целей. На большинстве платформ должно быть достаточно ясно, как качественная реализация, предназначенная для обеспечения возможности встроенного программирования без использования специфических для компилятора директив, должна обрабатывать volatile -квалифицированные обращения, а высококачественные реализации, предназначенные для такого использования, должны обрабатывать их таким образом. мода, хотя Стандарт не требует от них этого. К сожалению, некоторые авторы компиляторов ограничивают свою семантику тем, что прямо предписывает Стандарт, вместо того, чтобы расширять свою семантику для соответствия базовой платформе (например, при таргетинге на платформы, где доступы volatile могут вести себя как вызовы подпрограмм, не переупорядочивать какие-либо операции через volatile доступ, если только он не может быть переупорядочен через вызов неизвестной функции). В то время как icc, похоже, обрабатывает volatile -качественные записи таким способом, компиляторы, такие как gcc и clang, которые не предназначены для использования во встроенных системах с включенной оптимизацией, будут делать это только тогда, когда большинство оптимизаций отключены. .

...