gpt4 book ai didi

c - Linux页面错误内存中的互斥锁

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:30 24 4
gpt4 key购买 nike

我在 linux 2.6 和位于 mmap 文件后备内存中的互斥量时遇到了一个奇怪的并发问题。它是一个闩锁管理器模块。页错误逻辑是否重新启动了一条完全包含锁定前缀的指令?它的行为就像它在重新启动时不包含锁定前缀一样。如果我在 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
}

最佳答案

可能是页面错误引入的延迟暴露了否则看不到的竞争条件。

我建议从 pthread_spinlock_t(它只是一个 int)开始,并在实现您自己的自旋锁之前确保您的软件正常工作。错误可能出在其他地方。

该代码存在一些问题:

  1. 混合访问 BtSpinLatch* latch 作为 BtSpinLatchushort 打破了导致未定义行为的别名规则。将 BtSpinLatch 设为 ushort 并坚持仅使用位掩码和移位访问位。
  2. 当一个写者获得锁时,它会清除 pending 位,即使还有另一个 pending writer。
  3. __sync_fetch... 内置函数已过时且过于昂贵,因为它们构成了完整的内存屏障,并且在这里被调用的次数超过了必要的次数。使用 built-in functions for memory model aware atomic operations .
  4. 位域位顺序是平台相关的。该代码采用低端位域。

关于c - Linux页面错误内存中的互斥锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21807231/

24 4 0