是"声称我把这个互斥锁锁定了#34;可行?

时间:2011-12-26 16:08:56

标签: c multithreading thread-safety pthreads mutex

The Tools We Work With 中,Varnish软件的作者对新的ISO C标准草案表示失望。特别是他认为应该有一些有用的东西,比如“断言我持有这个互斥锁定”的功能,并且他声称他在Vanish中写了一个。

我查了一下代码。它基本上是这样的:

struct ilck {
    unsigned        magic;
    pthread_mutex_t     mtx;
    int         held;
    pthread_t       owner;
    VTAILQ_ENTRY(ilck)  list;
    const char      *w;
    struct VSC_C_lck    *stat;
};


void Lck__Lock(struct ilck *ilck, const char *p, const char *f, int l)
{
    if (!(params->diag_bitmap & 0x18)) {
        AZ(pthread_mutex_lock(&ilck->mtx));
        AZ(ilck->held);
        ilck->stat->locks++;
        ilck->owner = pthread_self();
        ilck->held = 1;
        return;
    }
    r = pthread_mutex_trylock(&ilck->mtx);
    assert(r == 0 || r == EBUSY);
    if (r) {
        ilck->stat->colls++;
        if (params->diag_bitmap & 0x8)
            VSL(SLT_Debug, 0, "MTX_CONTEST(%s,%s,%d,%s)",
                p, f, l, ilck->w);
        AZ(pthread_mutex_lock(&ilck->mtx));
    } else if (params->diag_bitmap & 0x8) {
        VSL(SLT_Debug, 0, "MTX_LOCK(%s,%s,%d,%s)", p, f, l, ilck->w);
    }
    ilck->stat->locks++;
    ilck->owner = pthread_self();
    ilck->held = 1;
}

void
Lck__Assert(const struct ilck *ilck, int held)
{
    if (held)
        assert(ilck->held &&
            pthread_equal(ilck->owner, pthread_self()));
    else
        assert(!ilck->held ||
            !pthread_equal(ilck->owner, pthread_self()));
}

我省略了try-lock和unlock操作的实现,因为它们基本上是常规的。我有疑问的地方是Lck__Assert(),其中对ilck-> hold和lick->所有者的访问不受任何互斥锁的保护。

所以说下面的事件序列:

  1. 线程A锁定互斥锁。
  2. 线程A将其解锁。
  3. 线程B锁定相同的互斥锁。在锁定过程中(内部 Lck_lock()),线程B在更新ilck-> hold之后被抢占 在它更新ilck->所有者之前。这应该是可能的,因为 优化器和CPU无序。
  4. 线程A运行并调用Lck__Assert(),断言将是 true和线程A实际上不包含互斥锁。
  5. 在我看来,应该有一些“全局”互斥锁来保护互斥锁自己的数据,或者至少是一些写/读屏障。我的分析是否正确?

1 个答案:

答案 0 :(得分:0)

我已联系过作者。他说我的分析是有效的,并使用memset(,0)取消设置“thread_t所有者”,因为thread_t不是具有指定赋值运算符的透明结构。希望适用于大多数平台。