use*_*112 5 c++ x86 multithreading atomic cpu-architecture
以std::bitset原子方式更新单个位(来自a )的最便宜的技术是什么?我不认为x86 BTR是原子的.
我想知道我是否必须读取最近的字节,然后使用CAS?
如果LOCK+ BTR 是最快速的解决方案,我很乐意接受内联的x86-64汇编答案.
BTS/BTR 默认情况下不是原子的,但它们可以带有 LOCK 前缀。
这是我对原子位设置和原子位重置的实现,它适用于 Intel 64 位和 32 位平台(适用于 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;
}
Run Code Online (Sandbox Code Playgroud)