Как получить `gcc` для генерации инструкции` bts` для x86-64 из стандартного C?

Вдохновленный недавним вопросом , я хотел бы знать, знает ли кто, как получить gcc для генерации инструкции x86-64 bts (бит тест и набор) на платформах x86-64 Linux, не прибегая к встроенной сборке или к нестандартным встроенным компиляторам.

Похожие вопросы:

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

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

Ответы

Ответ 1

В первом ответе за первое звено - насколько это важно в великой схеме вещей. Единственная часть, когда вы тестируете биты:

  • Низкоуровневые драйверы. Однако, если вы пишете один, вы, вероятно, знаете ASM, он достаточно привязан к системе и, вероятно, большинство задержек происходит на вводе/выводе
  • Тестирование флажков. Обычно это либо при инициализации (один раз только в начале), либо при некоторых общих вычислениях (что занимает гораздо больше времени).

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

Для части Редактировать - только с помощью bts не гарантирует атома операции. Все это гарантирует, что он будет атомарным на этом ядре (так что or выполняется в памяти). На многопроцессорных устройствах (необычных) или многоядерных устройствах (очень распространенных) вам все равно придется синхронизировать с другими процессорами.

Поскольку синхронизация намного дороже, я считаю, что разница между:

asm("lock bts %0, %1" : "+m" (*array) : "r" (bit));

и

asm("lock or %0, %1" : "+m" (*array) : "r" (1 << bit));

минимальна. И вторая форма:

  • Можно установить сразу несколько флагов
  • Имейте приятную форму __sync_fetch_and_or (array, 1 << bit) (работая над компилятором gcc и intel, насколько я помню).

Ответ 2

Я использую встроенные ядра gcc, такие как __sync_lock_test_and_set (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html). Изменение флага -march будет напрямую влиять на генерируемое. Я использую его с i686 прямо сейчас, но http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options показывает все возможности.

Я понимаю, что это не то, о чем вы просите, но я нашел эти две веб-страницы очень полезными, когда я искал такие механизмы.

Ответ 3

Я считаю (но не уверен), что ни стандарты С++, ни C не имеют механизмов для этих типов механизмов синхронизации. Поддержка механизмов синхронизации более высокого уровня находится в разных состояниях стандартизации, но я даже не думаю, что один из них позволит вам получить доступ к типу примитива, который вы после.

Вы программируете блокирующие данные, где блокировки недостаточны?

Вероятно, вы захотите просто использовать gcc нестандартные расширения и/или операционную систему или библиотеку, обеспечивающие примитивы синхронизации. Я бы поставил там библиотеку, которая могла бы обеспечить тип переносимости, который вы ищете, если вы обеспокоены использованием встроенных функций компилятора. (Хотя действительно, я думаю, что большинство людей просто кусают пулю и используют код, специфичный для gcc, когда они в ней нуждаются. Не идеальны, но стандарты на самом деле не поддерживаются.)