【问题标题】:spinlock in Assembly confusion装配混乱中的自旋锁
【发布时间】:2014-11-15 08:00:01
【问题描述】:

尝试使用自旋锁方法在英特尔伽利略板上调度进程,文档显示 mutex_lock 是这样的函数;

    /*------------------------------------------------------------------------
  * mutex_lock(uint32 *lock)  --  Acquire a lock
  *------------------------------------------------------------------------
 */
mutex_lock:

/* Save registers that will be modified */

pushl   %eax
pushl   %ebx
pushl   %ecx

movl    $1, %ebx    /* Place the "locked" value in ebx  */
movl    16(%esp), %ecx  /* Place the address of the lock in ecx */

spinloop:
movl    $0, %eax    /* Place the "unlocked" value in eax    */
lock    cmpxchg %ebx, (%ecx)  
/* Atomic compare-and-exchange: */
/* Compare eax with memory (%ecx)   */
/* if equal             */
/*  load %ebx in memory (%ecx), ZF=1*/
/* else                 */
/*  load memory in %eax, ZF=0   */

/* If ZF = 0, the mutex was locked, so continue the spin loop   */

jnz spinloop

/* We hold the lock now, so pop the saved registers and return  */
popl    %ecx
popl    %ebx
popl    %eax
ret

1 为什么变量 uint32*lock in 传入函数中,却从未在函数中使用?

2。代码部分是否以与我们传入的 *lock 相关的 lock 开头?如果是,那是什么意思?

3.感谢@wallyk,我明白为什么会有一个 16(esp),但是,我仍然不确定 lock 的指针是如何自动放到那个位置的,代码的哪一部分是这样做的?

非常感谢!

【问题讨论】:

  • 这是二十年前的代码,那时处理器的工作方式非常不同。不要使用它。千万不要自己写,如果绝对需要,请使用 PAUSE 指令。

标签: assembly process operating-system spinlock


【解决方案1】:
  1. 指令中使用参数lock

    movl 16(%esp), %ecx

参数位于堆栈顶部的偏移量 16 处。注意入口处的三个push 指令,并回想一条call 指令(这就是激活此代码的方式)推送返回的EIP 地址。

有更好的方法在汇编中对此进行编码,但这是一种不使用结构的方法。如果不进行一些调整就移植到非 32 位架构,也可能会造成麻烦。

  1. 不,lock 指令是一个 x86 CPU 指令前缀,用于管理同一内存系统和相关缓存上的多个 CPU(和内核)之间的并发访问。在这种情况下,它确保cmpxchg %ebx, (%ecx)(这是一条读/修改/写指令)自动执行,而不管其他内核、CPU 和缓存对该内存位置执行什么操作。

【讨论】:

  • 我不确定我是否正确理解了你的观点,所以从堆栈的顶部,EIP、eax、ebx、ecx 的值被推入。因此为 *lock 保留 16 的偏移量。但是lock的指针放入16(esp)的过程是如何工作的呢?
  • @javarookie:为了让它成功工作,锁的地址在调用函数之前由调用者压入堆栈。调用者还必须在返回后从堆栈中弹出一个值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 2021-07-17
  • 2020-05-21
  • 1970-01-01
相关资源
最近更新 更多