Самый дешевый / наименее-навязчивый способ атомарного обновления немного?

Какой самый дешевый метод обновления одного бита (от std::bitset) атомно? Я не думаю, что x86 BTR атомно.

Мне интересно, если бы я должен был прочитать ближайший байт, а затем использовать CAS?

Если LOCK + BTR является самое быстрое решение, я бы с радостью принял встроенный ответ на сборку x86-64.

5

Решение

BTS / BTR не являются атомарными по умолчанию, но они могут быть с префиксом LOCK.

Вот моя реализация набора атомарных битов и сброса атомных битов, которая работает как на 64-битной, так и на 32-битной платформе Intel (работает как с MSVC, gcc и, возможно, clang).

Реализация для ARM также доступна от:
http://alice.loria.fr/software/geogram/doc/html/atomics_8h_source.html

/**
* \brief Atomically tests and sets a bit (INTEL only)
* \details Sets bit \p bit of *\p ptr and returns its previous value.
* The function is atomic and acts as a read-write memory barrier.
* \param[in] ptr a pointer to an unsigned integer
* \param[in] bit index of the bit to set in *\p ptr
* \return the previous value of bit \p bit
*/
inline char atomic_bittestandset_x86(volatile unsigned int* ptr, unsigned int bit) {
char out;
#if defined(__x86_64)
__asm__ __volatile__ (
"lock; bts %2,%1\n"  // set carry flag if bit %2 (bit) of %1 (ptr) is set
//   then set bit %2 of %1
"sbb %0,%0\n"        // set %0 (out) if carry flag is set
: "=r" (out), "=m" (*ptr)
: "Ir" (bit)
: "memory");
#else
__asm__ __volatile__ (
"lock; bts %2,%1\n"  // set carry flag if bit %2 (bit) of %1 (ptr) is set
//   then set bit %2 of %1
"sbb %0,%0\n"        // set %0 (out) if carry flag is set
: "=q" (out), "=m" (*ptr)
: "Ir" (bit)
: "memory");
#endif
return out;
}

/**
* \brief Atomically tests and resets a bit (INTEL only)
* \details Resets bit \p bit of *\p ptr and returns its previous value.
* The function is atomic and acts as a read-write memory barrier
* \param[in] ptr a pointer to an unsigned integer
* \param[in] bit index of the bit to reset in \p ptr
* \return the previous value of bit \p bit
*/
inline char atomic_bittestandreset_x86(volatile unsigned int* ptr, unsigned int bit) {
char out;
#if defined(__x86_64)
__asm__ __volatile__ (
"lock; btr %2,%1\n"  // set carry flag if bit %2 (bit) of %1 (ptr) is set
//   then reset bit %2 of %1
"sbb %0,%0\n"        // set %0 (out) if carry flag is set
: "=r" (out), "=m" (*ptr)
: "Ir" (bit)
: "memory");
#else
__asm__ __volatile__ (
"lock; btr %2,%1\n"  // set carry flag if bit %2 (bit) of %1 (ptr) is set
//   then reset bit %2 of %1
"sbb %0,%0\n"        // set %0 (out) if carry flag is set
: "=q" (out), "=m" (*ptr)
: "Ir" (bit)
: "memory");
#endif
return out;
}
0

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector