基于futex的4字节单写入器/多读卡器锁

时间:2010-10-19 01:36:55

标签: locking contention futex

寻找基于futex的单一编写器/多读卡器锁的实现,不需要超出单个4字节互斥锁状态变量的空间开销。

一些背景知识:我有一个应用程序,它将在每个数十亿到数亿个小对象中嵌入一个锁。由于锁定的非常精细的性质和应用程序的结构,我预计最小的争用。此外,作家将是罕见的,竞争作家仍然很少见。由于所有这些原因,在这个特定的环境中,一个倾向于(理论上)“雷鸣般的”现象的解决方案是完全可以接受的。

1 个答案:

答案 0 :(得分:0)

您将在https://gist.github.com/smokku/653c469d695d60be4fe8170630ba8205

找到我的实施方案

这个想法是只有一个线程可以锁定写入(futex值0),锁定可以打开(futex值1)或者可以有很多读取线程(futex)值大于1)。因此1以下的值(只有一个)会阻止futex上的读者和作者,而1以上的值只会阻止编写者。解锁线程会唤醒一个等待线程,但是你需要注意不要仅仅通过写入器线程来唤醒读者。

#define cpu_relax() __builtin_ia32_pause()
#define cmpxchg(P, O, N) __sync_val_compare_and_swap((P), (O), (N))

static unsigned _lock = 1; // read-write lock futex
const static unsigned _lock_open = 1;
const static unsigned _lock_wlocked = 0;

static void _unlock()
{
    unsigned current, wanted;
    do {
        current = _lock;
        if (current == _lock_open) return;
        if (current == _lock_wlocked) {
            wanted = _lock_open;
        } else {
            wanted = current - 1;
        }
    } while (cmpxchg(&_lock, current, wanted) != current);
    syscall(SYS_futex, &_lock, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
}

static void _rlock()
{
    unsigned current;
    while ((current = _lock) == _lock_wlocked || cmpxchg(&_lock, current, current + 1) != current) {
        while (syscall(SYS_futex, &_lock, FUTEX_WAIT_PRIVATE, current, NULL, NULL, 0) != 0) {
            cpu_relax();
            if (_lock >= _lock_open) break;
        }
        // will be able to acquire rlock no matter what unlock woke us
    }
}

static void _wlock()
{
    unsigned current;
    while ((current = cmpxchg(&_lock, _lock_open, _lock_wlocked)) != _lock_open) {
        while (syscall(SYS_futex, &_lock, FUTEX_WAIT_PRIVATE, current, NULL, NULL, 0) != 0) {
            cpu_relax();
            if (_lock == _lock_open) break;
        }
        if (_lock != _lock_open) {
            // in rlock - won't be able to acquire lock - wake someone else
            syscall(SYS_futex, &_lock, FUTEX_WAKE_PRIVATE, 1, NULL, NULL, 0);
        }
    }
}