[英]What is the equivalent of Windows .NET (C++) SpinWait on Linux and Mac OS X?
Windows .NET (C++) provides SpinWait for Hyper-threading friendly busy waiting with YIELD/PAUSE instructions. Windows .NET(C ++)通过YIELD / PAUSE指令为超线程友好忙等待提供SpinWait。 What is the equivalent function on Linux and Mac OS X?
Linux和Mac OS X上的等效功能是什么? If a system call isn't available, how can an equivalent be implemented in user space?
如果系统调用不可用,如何在用户空间中实现等效功能?
See Windows Thread::SpinWait 参见Windows Thread :: SpinWait
See Long Duration Spin-wait Loops on Hyper-Threading Technology Enabled Intel Processors for a discussion of performance issues with spin waits. 有关自旋等待的性能问题的讨论,请参阅启用超线程技术的英特尔处理器上的长时间自旋等待循环 。
See https://www.codeproject.com/articles/184046/spin-lock-in-c by sameer_87 参见sameer_87的 https://www.codeproject.com/articles/184046/spin-lock-in-c
#include "SpinLock.h"
#include <iostream>
using namespace LockFree;
using namespace std;
void tSpinWait::Lock(tSpinLock &LockObj)
{
m_iterations = 0;
while(true)
{
// A thread alreading owning the lock shouldn't be allowed to wait to acquire the lock - reentrant safe
if(LockObj.dest == GetCurrentThreadId())
break;
/*
Spinning in a loop of interlockedxxx calls can reduce the available memory bandwidth and slow
down the rest of the system. Interlocked calls are expensive in their use of the system memory
bus. It is better to see if the 'dest' value is what it is expected and then retry interlockedxx.
*/
if(InterlockedCompareExchange(&LockObj.dest, LockObj.exchange, LockObj.compare) == 0)
{
//assign CurrentThreadId to dest to make it re-entrant safe
LockObj.dest = GetCurrentThreadId();
// lock acquired
break;
}
// spin wait to acquire
while(LockObj.dest != LockObj.compare)
{
if(HasThreasholdReached())
{
if(m_iterations + YIELD_ITERATION >= MAX_SLEEP_ITERATION)
Sleep(0);
if(m_iterations >= YIELD_ITERATION && m_iterations < MAX_SLEEP_ITERATION)
{
m_iterations = 0;
SwitchToThread();
}
}
// Yield processor on multi-processor but if on single processor then give other thread the CPU
m_iterations++;
if(Helper::GetNumberOfProcessors() > 1) { YieldProcessor(/*no op*/); }
else { SwitchToThread(); }
}
}
}
//
void tSpinWait::Unlock(tSpinLock &LockObj)
{
if(LockObj.dest != GetCurrentThreadId())
throw std::runtime_error("Unexpected thread-id in release");
// lock released
InterlockedCompareExchange(&LockObj.dest, LockObj.compare, GetCurrentThreadId());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.