嵌入式操作系统
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

7.6 Power PC下关键区段的实现

在单CPU环境下,Power PC关键区段也可以采用关闭中断的方式来实现。在Power PC CPU中,通过清除MSR(机器状态寄存器)中的EE bit(External Exception),可以禁止外部可屏蔽中断,以达到同步的目的。但对于多CPU环境下的同步,Power PC提供了与IA32不一样的机制来完成。本节我们简单介绍这种机制,并给出几个实例。

7.6.1 Power PC提供的互斥访问机制

Power PC提供了几个用于互斥操作的指令,采用这些指令可以完成多CPU环境下的同步操作。最典型的是下列两个指令:

1.lwarx(Load word and reserve index)指令

该指令的作用是读取内存中的一个特定字(在Power PC中,字的长度是32 bit的,而在IA32中,字的长度定义为16 bit)到一个特定的寄存器,然后设置一个Reserve位,并启动内存窥探机制,对上述内存位置进行监控。一旦该内存位置被修改(可能是其他的CPU),则清除Reserve bit,否则一直保持Reserve bit。该指令的格式为:lwarx rD,rA,rB (其中,rA和rB寄存器给出了Effective地址,该指令把Effective地址位置的字读入rD寄存器,该Effective地址也是内存窥探机制作用的目标地址)。

2.stwcx(Store word conditional indexed)指令

该指令与上述lwarx指令对应,用来协同完成同步机制。该指令的作用是判断Reserve bit是否为1,若为1,则设置指定地址位置的字为指定字(由该指令的操作数寄存器指定内存位置和指定字,一般情况下,指定的内存位置与lwarx指令指定的有效地址相同),清除Reserve标志,并设置一个成功标志(CR0寄存器的特定bit);若Reserve标志为0,则该指令不做任何其他操作,仅仅设置一个失败标志(CR0寄存器的特定bit)。该指令的格式与lwarx类似:stwcx rS,rA,rB,其中,rA和rB两个通用寄存器指定Effective地址,rS寄存器指定要存储的值。

上述简单的描述仅仅是这两个指令的基本用途,这两个指令还有一些其他的用途,在此不再详述。

许多较复杂的原子操作和同步操作都可以采用上述两条指令实现。比如下列代码实现了一个简单的Test-and-set例程:

loop: lwarx r5,0,r3
    cmpwi r5,0
    bne $+12
    stwcx r4,0,r3
    bne-loop
continue:
    … …

上述代码中,假设r3寄存器存放了要测试的内存位置(Effective地址),lwarx执行后,把该位置的一个字读入r5寄存器,并设置Reserve bit。第二条指令(cmpwi),用于比较r5寄存器的值是否为0(即原内存位置的字是否为0),若不为0,则跳转到continue标号处执行,若为0,则继续执行。这时候,stwcx指令根据Reserve bit的值来确定是否把r4寄存器的值(非0)存放到上述内存位置。若成功(Reserve bit为1,成功地把r4寄存器的值,存放到r3指定的有效地址处),则跳出循环,继续执行,否则跳转到loop标号处,重新执行上述操作。

上述操作是一个原子操作,考虑在多CPU的环境下,一种访问冲突的情况:假设有两个CPU(CPU1和CPU2)试图同时对同一个位置进行Test and set操作,则表7-2所示的情况可能发生。

表7-2 一个产生访问冲突的指令序列(双CPU)

在上述序列下,CPU1和CPU2会把r3指定的内存位置处的数字,读入r5寄存器,由于这时该位置还没有被修改,所以cmpwi指令的执行结果都会比较成功,从而导致stwcx指令的执行。这时候,CPU2可以成功执行该指令,因为在CPU2执行前,该位置尚未被修改;但CPU1却执行失败,因为在CPU1执行stwcx执行前,CPU2已经修改了该位置(CPU1通过内存窥探机制得知),从而导致Reserve标志被清除。这样目标为同一位置的test操作和set操作,只有一个CPU设置成功,其他CPU都没有设置成功,从而实现了共享资源的同步和保护。