(32)函 __iso_volatile_load32 (),顾名思义,该函数是要读取某个变量的值:
++ 还是测试一下:
(33)函数 _mm_pause () , CPU 忙等待时,降低功耗再等待:
++ 以下是一个简单的 C++ 示例,展示了如何在自旋锁中使用 _mm_pause:
#include <atomic>
#include <immintrin.h> // 包含 _mm_pause 函数的头文件
std::atomic<bool> lock_flag(false);
void spin_lock()
{
while (lock_flag.test_and_set(std::memory_order_acquire))
_mm_pause(); // 在循环中使用 _mm_pause 来降低功耗
}
void spin_unlock() { lock_flag.clear(std::memory_order_release); }
int main() {
// 示例用法
spin_lock();
// 执行临界区代码
spin_unlock();
return 0;
}
(34)全局函数 _Atomic_lock_acquire (),本函数似乎实现了一个 STL 库级别的自旋锁,源代码如下:
++ 再给个其代码版本,看哪个版本阅读时候更舒服一些:
inline void _Atomic_lock_acquire(_Smtx_t* _Spinlock) noexcept // 重载函数,功能肯定是一样的
{
_Smtx_lock_exclusive(_Spinlock); // using _Smtx_t = void*;
}
// 本函的语义是让本线程执行忙等待,直到形参的值为 0 才返回。
// 函数名顾名思义:原子性的获取锁。形参就是锁,形参值为0 表示锁空闲。
inline void _Atomic_lock_acquire(long& _Spinlock) noexcept // 本函有删减,仅仅适用于 intel CPU
{
#if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
int _Current_backoff = 1 ; // 这里是定义了一个偏移量
const int _Max_backoff = 64 ; // 随后每次都让 _Current_backoff 的值左移一位,增加 2 倍
// LONG _InterlockedExchange( LONG volatile* Target, LONG Value ); windows 平台的原子函数
// 原子性的把形参 2 赋值给形参 1,并返回形参 1 里的旧值。本函数只操作 32 bit 的数据
while (_InterlockedExchange(&_Spinlock, 1) != 0) // 外层循环只执行一次,自旋锁为 0 则同时结束内外循环
{
// 已知 int a = 3 ; int& b = a; 经测试:对左值引用取地址 &b 返回的是原始变量 a 的地址
// uint32_t __iso_volatile_load32(const volatile uint32_t *addr); 从形参地址里原子性的读取一个值
while (__iso_volatile_load32(&reinterpret_cast<int&>(_Spinlock)) != 0)
{
for (int _Count_down = _Current_backoff; _Count_down != 0; --_Count_down)
_mm_pause(); // 此函数是为了让 X86 x64 平台上的 CPU 执行低功耗的、低频率的忙等待
_Current_backoff = _Current_backoff < _Max_backoff ? _Current_backoff << 1 : _Max_backoff;
}
}
#endif
}
++ 测试一下:
(35) 函数 _Atomic_lock_release () ,本函数与上面的函数是对应的。本函数原子性的释放锁,其实就是拿一个整数值作为标志,来表示临界资源是否空闲:
// 顾名思义:这俩函数是原子性的释放锁,赋值形参锁为 0 值。
inline void _Atomic_lock_release(long& _Spinlock) noexcept // 本函有删减,仅仅适用于 intel CPU
{
#if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
_InterlockedExchange(&_Spinlock, 0);
#endif
}
inline void _Atomic_lock_release(_Smtx_t* _Spinlock) noexcept // 函数重载,32 位版本与 64 位版本
{
_Smtx_unlock_exclusive(_Spinlock); // 上面的函数更容易理解
}
(36)
谢谢