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

时间:2018-12-17 03:16:46

标签: c logic bare-metal

我在裸机环境中操作,因此任何回答,仅使用您已有的内容都不适用,因为我没有任何内容。我正在编写系统驱动程序,但是我需要递归互斥体,但是我不知道如何实现它们。我目前只有一个自旋锁的计数信号量。是否可以根据信号量创建递归互斥体,还是必须创建另一个同步原语?不需要代码,我只想知道这些步骤。

1 个答案:

答案 0 :(得分:1)

如果您对数据争用下发生的事情有一些较弱的好特性,那么它就轻而易举,本质上是:

/* 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类型;在裸机上您将定义这种类型),则可以使{ {1}}成员tid_t owner并替换测试:

_Atomic

具有:

if (m->owner == self)

if (atomic_load_explicit(&m->owner, memory_order_relaxed) == self) 限定符(基本上没有必要,但是向编译器发出信号,它不应拆分或合并负载,这有助于我在没有原子的情况下实现的“弱好特性” )可以删除。