spinlock.h 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. /**
  2. * @file spinlock.h
  3. * @author fslongjin (longjin@RinGoTek.cn)
  4. * @brief 自旋锁
  5. * @version 0.1
  6. * @date 2022-04-07
  7. *
  8. * @copyright Copyright (c) 2022
  9. *
  10. */
  11. #pragma once
  12. #include <common/glib.h>
  13. #include <process/preempt.h>
  14. /**
  15. * @brief 定义自旋锁结构体
  16. *
  17. */
  18. typedef struct
  19. {
  20. __volatile__ char lock; // 1:unlocked 0:locked
  21. } spinlock_t;
  22. /**
  23. * @brief 初始化自旋锁
  24. *
  25. * @param lock
  26. */
  27. void spin_init(spinlock_t *lock)
  28. {
  29. lock->lock = 1;
  30. }
  31. /**
  32. * @brief 自旋锁加锁
  33. *
  34. * @param lock
  35. */
  36. void spin_lock(spinlock_t *lock)
  37. {
  38. preempt_disable();
  39. __asm__ __volatile__("1: \n\t"
  40. "lock decq %0 \n\t" // 尝试-1
  41. "jns 3f \n\t" // 加锁成功,跳转到步骤3
  42. "2: \n\t" // 加锁失败,稍后再试
  43. "pause \n\t"
  44. "cmpq $0, %0 \n\t"
  45. "jle 2b \n\t" // 若锁被占用,则继续重试
  46. "jmp 1b \n\t" // 尝试加锁
  47. "3:"
  48. : "=m"(lock->lock)::"memory");
  49. }
  50. void spin_unlock(spinlock_t *lock)
  51. {
  52. __asm__ __volatile__("movq $1, %0 \n\t"
  53. : "=m"(lock->lock)::"memory");
  54. preempt_enable();
  55. }
  56. /**
  57. * @brief 尝试加锁
  58. *
  59. * @param lock
  60. * @return long 锁变量的值(1为成功加锁,0为加锁失败)
  61. */
  62. long spin_trylock(spinlock_t *lock)
  63. {
  64. uint64_t tmp_val = 0;
  65. preempt_disable();
  66. // 交换tmp_val和lock的值,若tmp_val==1则证明加锁成功
  67. asm volatile("lock xchgq %0, %1 \n\t" // 确保只有1个进程能得到锁
  68. : "=q"(tmp_val), "=m"(lock->lock)
  69. : "0"(0)
  70. : "memory");
  71. if (!tmp_val)
  72. preempt_enable();
  73. return tmp_val;
  74. }