使用计数信号量如何创建递归互斥量

Using a counting semaphore how do I create a recursive mutex

我在裸机环境中操作,所以任何回答说只使用你拥有的东西都不适用,因为我什么都没有。我正在编写一个系统驱动程序,但我需要递归互斥锁,但我不知道如何实现它们。我目前只有一个作为自旋锁运行的计数信号量。是否可以从信号量创建递归互斥锁,或者我是否必须创建另一个同步原语,如果可以,如何创建?不需要代码我只是想知道步骤。

如果你对数据竞争下发生的事情有一些相当薄弱的好属性,它很简单,本质上:

/* data structure */
struct my_mutex {
    sem_t sem;
    volatile tid_t owner;
    unsigned count;
} m;

/* lock operation */
if (m->owner == self) { // formally a race
    m->cnt++;
} else {
    sem_wait(&m->sem);
    m->owner = self; // where self is tid of calling thread
}

/* unlock operation */
if (m->count > 0) {
    m->count--;
} else {
    m->owner = 0;
    sem_post(&m->sem);
}

请注意,假设赛车阅读从某些可能的排序中读取了一些价值,没有任何顺序可以让您在自己是所有者时不将自己视为所有者,或者在您不是所有者时也不会将自己视为所有者。但是,如果您将它们视为正式未定义,则无效。

如果你不能这样做,你通常需要一个普通的互斥锁 + condvar 来模拟递归互斥锁,所以首先要弄清楚如何从信号量中创建一个 condvar。

如果你的编译器有 _Atomic 并且支持线程 ID 大小合适的原子(上面的抽象 tid_t 类型;在裸机上这是你定义的类型),你可以tid_t owner 成员 _Atomic 并替换测试:

if (m->owner == self)

与:

if (atomic_load_explicit(&m->owner, memory_order_relaxed) == self)

volatile 限定符(在很大程度上是不必要的,但它向编译器发出信号,表明它不应拆分或合并负载,这有助于 "weak nice properties" 我在缺席时的目标原子数)可以删除。