spinlock.c 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #include <common/spinlock.h>
  2. #include <process/preempt.h>
  3. void __arch_spin_lock(spinlock_t *lock)
  4. {
  5. __asm__ __volatile__("1: \n\t"
  6. "lock decb %0 \n\t" // 尝试-1
  7. "jns 3f \n\t" // 加锁成功,跳转到步骤3
  8. "2: \n\t" // 加锁失败,稍后再试
  9. "pause \n\t"
  10. "cmpb $0, %0 \n\t"
  11. "jle 2b \n\t" // 若锁被占用,则继续重试
  12. "jmp 1b \n\t" // 尝试加锁
  13. "3:"
  14. : "=m"(lock->lock)::"memory");
  15. rs_preempt_disable();
  16. }
  17. void __arch_spin_unlock(spinlock_t *lock)
  18. {
  19. __asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory");
  20. rs_preempt_enable();
  21. }
  22. void __arch_spin_lock_no_preempt(spinlock_t *lock)
  23. {
  24. __asm__ __volatile__("1: \n\t"
  25. "lock decb %0 \n\t" // 尝试-1
  26. "jns 3f \n\t" // 加锁成功,跳转到步骤3
  27. "2: \n\t" // 加锁失败,稍后再试
  28. "pause \n\t"
  29. "cmpb $0, %0 \n\t"
  30. "jle 2b \n\t" // 若锁被占用,则继续重试
  31. "jmp 1b \n\t" // 尝试加锁
  32. "3:"
  33. : "=m"(lock->lock)::"memory");
  34. }
  35. void __arch_spin_unlock_no_preempt(spinlock_t *lock)
  36. {
  37. __asm__ __volatile__("movb $1, %0 \n\t" : "=m"(lock->lock)::"memory");
  38. }
  39. long __arch_spin_trylock(spinlock_t *lock)
  40. {
  41. uint64_t tmp_val = 0;
  42. rs_preempt_disable();
  43. // 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功
  44. asm volatile("lock xchg %%bx, %1 \n\t" // 确保只有1个进程能得到锁
  45. : "=q"(tmp_val), "=m"(lock->lock)
  46. : "b"(0)
  47. : "memory");
  48. if (!tmp_val)
  49. rs_preempt_enable();
  50. return tmp_val;
  51. }