第17章 互斥量的设计与实现

当所有的任务在同个单一地址空间下,使用共享资源时,必然涉及到共享资源的竞争。只有多个任务互斥地访问共享资源时才不会发生错误。只有提供互斥或信号量才能保证内核并发机制。

任何互斥尝试必须基于一些基础硬件互斥机制。最常见的这种约束是某一时刻对内存的一次访问。(intel处理器可以查看《IA-32架构软件开发人员指南 卷3 系统编程指南》中7.1节 加锁的原子操作)

x86上实现互斥,需要硬件的支持:

  1. 中断禁用。代价高,在单CPU上能使用。在多CPU上不能使用(多处理器中,是对等关系,没有支持互斥的中断机制)。
  2. 专用机器指令:在一个指令的执行周期内对一个存储单元的读和写(xchg) 或 测试和设置(testset)。在该指令的执行过程中,任何其他指令访问内存将被阻止。

IA-32处理器提供了LOCK#信号。这个信号会在某些内存操作过程中被自动发出。当做这个输出信号发出的时候,来自其他处理器或总线代理的总线控制请求将被阻塞。软件能够利用在指令前添加LOCK前缀来指定,在其他情况下也需要LOCK语义(LOCK semantices)。

在Intel 386 ,Intel 486,Pentium处理器中,直接调用加锁的指令会导致LOCK#信号的产生。硬件的设计者需要保证系统硬件中LOCK#信号的有效性,以控制多个处理器对内存的访问。对与Pentium 4,Intel Xeon,以及P6系列处理器,如果被访问的内存区域存在于处理器内部的高速缓存中,那么LOCK#信号通常不被发出;但是处理器的缓存却要被锁定。

xchg指令会自动的带有LOCK 语义。

mutex.h源代码如下所示

#ifndef _MUTEX_H_  
#define _MUTEX_H_  
  
typedef unsigned long mutex_t;  
  
static inline unsigned long xchgl(unsigned long x, unsigned long *ptr)  
{  
    __asm__ __volatile__("xchgl %0,%1\n\t"  
        :"=r"(x)  
        :"m"(*ptr),"0"(x)  
        :"memory"  
        );  
    return x;  
}  
  
/*mptr是mutex_t的指针*/  
#define lock(mptr) ({\  
    while(xchgl(1,(mptr)));\  
})  
  
/*mptr是mutex_t的指针*/  
#define unlock(mptr) xchgl(0,(mptr))  
  
  
/*mptr是mutex_t的指针*/  
#define init_mutex(mptr) ({*mptr = 0;})  
  
  
#endif 

Leave a Reply

Your email address will not be published. Required fields are marked *