【问题标题】:mutex in linux page faulted memorylinux页面错误内存中的互斥锁
【发布时间】:2014-02-16 04:19:51
【问题描述】:

我在使用 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
}

【问题讨论】:

  • 你能展示在 mmap 内存中创建和初始化互斥锁的代码吗?
  • 我附上了读写器独占请求代码。它使用 ushort 的低位作为互斥体。
  • 锁存器被创建并初始化为零值。
  • 有什么理由不将进程共享互斥锁和条件变量放在共享内存中?
  • 是的,它们太大了。这些读/写锁是 ushorts。我需要它们来保护哈希表条目。

标签: c linux mutex


【解决方案1】:

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

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

该代码存在一些问题:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-09
    • 2015-09-10
    • 1970-01-01
    • 2014-09-11
    • 2015-10-06
    • 1970-01-01
    • 2016-02-18
    • 2018-05-23
    相关资源
    最近更新 更多