当所有的任务在同个单一地址空间下,使用共享资源时,必然涉及到共享资源的竞争。只有多个任务互斥地访问共享资源时才不会发生错误。只有提供互斥或信号量才能保证内核并发机制。
任何互斥尝试必须基于一些基础硬件互斥机制。最常见的这种约束是某一时刻对内存的一次访问。(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
本文探讨了x86架构中实现互斥的方法,包括禁用中断和使用专用机器指令如xchg和testset指令。介绍了IA-32处理器如何通过LOCK#信号确保内存操作期间的互斥,并展示了如何利用xchg指令实现简单的互斥锁。
935

被折叠的 条评论
为什么被折叠?



