ARM 事务性内存扩展有一个相当简单的使用说明:
我试图弄清楚的是,这些交易是否会因与代码其他部分中的交易发生冲突而被重放,并且它们是否会因与任何类型的访问发生冲突而被重放。为了详细说明,假设我们有这个例程:
sem_post:
TSTART X0 // Start of outer transaction
CBNZ test_fail // No reason for this routine to cancel or fail
LDR X1, [X2] // X2 points to semaphore
ADD X1, X1, #1 // Increment semaphore value
STR X1, [X2]. // Store incremented value
TCOMMIT // Commit transaction and exit
我试图弄清楚的是,这些交易是否会因与代码其他部分中的交易发生冲突而被重放,并且它们是否会因与任何类型的访问发生冲突而被重放。为了详细说明,假设我们有这个例程:
sem_wait:
TSTART X0 // Start of outer transaction
CBNZ retry_check // This routine checks for retry (RTRY) and restarts transaction
LDR X1, [X2] // X2 points to semaphore
CMP X1, #0 // Check if semaphore is already used
CBNZ decrement // If it's non-zero, we can decrement the semaphore
TCANCEL #0xFF // If it's zero, we gotta retry
decrement:
SUB X1, X1, #1 // Decrement semaphore value
STR X1, [X2]. // Store decremented value
TCOMMIT // Commit transaction and exit
因此,这个事务将在代码的另一个部分进行,但是将访问内存中的位置作为sem_post
事务。
我的第一个问题:执行sem_post
事务的线程是否可能由于同时执行sem_wait
事务的线程而重复执行?
对于我的第二个问题,假设我们有一个像这样简单的例程:
break_semaphore:
MOV X0, #0xFF
STR X0, [X1] // X1 points to semaphore
上述程序并不是一个事务,它只是在操作信号量。
我的第二个问题:执行 sem_post
事务的线程是否会由于对待更新和提交的位置进行的任何并发访问而重新播放?
为了明确起见,我完全理解这并不是 TME 指令的实际用法,锁更可能像这样实现: https://www.gem5.org/project/2020/10/27/tme.html
我更想知道的是事务实际上是如何线性化的:具有共同代码区域的两个事务,所有事务相互之间,还是与内存中的所有其他访问相关的事务?
volatile
变量相同),因此是的,这确实涉及到在事务状态下获取的任何地址(缓存块)的内存冲突。 - Sam Thomas