我在裸金属环境中操作,所以任何说只使用你所拥有的答案都不适用,因为我什么都没有。我正在编写一个系统驱动程序,但我需要递归互斥,但我不知道如何实现它们。我目前只有一个计数信号量,它作为一个spinlock操作。有可能从信号量创建递归互斥体吗?或者我必须创建另一个同步原语吗?如果有,如何创建?不需要代码,我只是想知道步骤。
如果你对数据竞赛下发生的事情有一些相当弱的好属性,那么它就很简单,本质上是:
/* 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
限定符(基本上是不必要的,但向编译器发出了一个信号,即它不应该拆分或组合负载,这有助于在没有原子的情况下实现我所追求的"弱良好属性"(可以被删除。