我在Linux2.6和一个位于mmap文件备份内存中的互斥锁上遇到了一个奇怪的并发问题。这是一个锁存器管理器模块。页面错误逻辑会完全重新启动包含锁定前缀的指令吗?当它重新启动时,它的行为就像不包含lock前缀一样。如果我在mmap调用中设置了MAP_LOCKED属性,问题就会消失。有没有人有经验?
// mode & definition for hash latch implementation
enum {
Mutex = 1,
Write = 2,
Pending = 4,
Share = 8
} LockMode;
// mutex locks the other fields
// exclusive is set for write access
// share is count of read accessors
typedef struct {
volatile ushort mutex:1;
volatile ushort exclusive:1;
volatile ushort pending:1;
volatile ushort share:13;
} BtSpinLatch;
// wait for other read and write latches to relinquish
void bt_spinwritelock(BtSpinLatch *latch)
{
do {
#ifdef unix
while( __sync_fetch_and_or((ushort *)latch, Mutex | Pending) & Mutex )
sched_yield();
#else
while( _InterlockedOr16((ushort *)latch, Mutex | Pending) & Mutex )
SwitchToThread();
#endif
if( !(latch->share | latch->exclusive) ) {
#ifdef unix
__sync_fetch_and_or((ushort *)latch, Write);
__sync_fetch_and_and ((ushort *)latch, ~(Mutex | Pending));
#else
_InterlockedOr16((ushort *)latch, Write);
_InterlockedAnd16((ushort *)latch, ~(Mutex | Pending));
#endif
return;
}
#ifdef unix
__sync_fetch_and_and ((ushort *)latch, ~Mutex);
sched_yield();
#else
_InterlockedAnd16((ushort *)latch, ~Mutex);
SwitchToThread();
#endif
} while( 1 );
}
void bt_spinreadlock(BtSpinLatch *latch)
{
ushort prev;
do {
#ifdef unix
while( __sync_fetch_and_or((ushort *)latch, Mutex) & Mutex )
sched_yield();
#else
while( _InterlockedOr16((ushort *)latch, Mutex) & Mutex )
SwitchToThread();
#endif
// see if exclusive request is granted or pending
if( prev = !(latch->exclusive | latch->pending) )
#ifdef unix
__sync_fetch_and_add((ushort *)latch, Share);
#else
_InterlockedExchangeAdd16 ((ushort *)latch, Share);
#endif
#ifdef unix
__sync_fetch_and_and ((ushort *)latch, ~Mutex);
#else
_InterlockedAnd16((ushort *)latch, ~Mutex);
#endif
if( prev )
return;
#ifdef unix
} while( sched_yield(), 1 );
#else
} while( SwitchToThread(), 1 );
#endif
}发布于 2014-02-18 23:52:10
这可能是由页面错误引入的延迟暴露了否则看不到的竞争条件。
我建议从pthread_spinlock_t (它只是一个int)开始,在实现您自己的自旋锁之前,确保您的软件工作正常。错误可能出在其他地方。
该代码有几个问题:
BtSpinLatch* latch as BtSpinLatch和ushort会违反别名规则,从而导致未定义的行为。将BtSpinLatch设为ushort,并且只使用位掩码和移位来访问位。pending,即使有另一个未决写入器也是如此。__sync_fetch... 内置函数已过时且过于昂贵,因为它们构成了一个完整的内存屏障,并且它们在这里被调用的次数超过了必要的次数。 使用built-in functions for memory model aware atomic operations。https://stackoverflow.com/questions/21807231
复制相似问题