cpu.c 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-10-30 Bernard The first version
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #ifdef RT_USING_SMP
  13. static struct rt_cpu rt_cpus[RT_CPUS_NR];
  14. rt_hw_spinlock_t _cpus_lock;
  15. /**
  16. * This fucntion will return current cpu.
  17. */
  18. struct rt_cpu *rt_cpu_self(void)
  19. {
  20. return &rt_cpus[rt_hw_cpu_id()];
  21. }
  22. struct rt_cpu *rt_cpu_index(int index)
  23. {
  24. return &rt_cpus[index];
  25. }
  26. /**
  27. * This function will lock all cpus's scheduler and disable local irq.
  28. */
  29. rt_base_t rt_cpus_lock(void)
  30. {
  31. rt_base_t level;
  32. struct rt_cpu* pcpu;
  33. level = rt_hw_local_irq_disable();
  34. pcpu = rt_cpu_self();
  35. if (pcpu->current_thread != RT_NULL)
  36. {
  37. register rt_uint16_t lock_nest = pcpu->current_thread->cpus_lock_nest;
  38. pcpu->current_thread->cpus_lock_nest++;
  39. if (lock_nest == 0)
  40. {
  41. pcpu->current_thread->scheduler_lock_nest++;
  42. rt_hw_spin_lock(&_cpus_lock);
  43. }
  44. }
  45. return level;
  46. }
  47. RTM_EXPORT(rt_cpus_lock);
  48. /**
  49. * This function will restore all cpus's scheduler and restore local irq.
  50. */
  51. void rt_cpus_unlock(rt_base_t level)
  52. {
  53. struct rt_cpu* pcpu = rt_cpu_self();
  54. if (pcpu->current_thread != RT_NULL)
  55. {
  56. pcpu->current_thread->cpus_lock_nest--;
  57. if (pcpu->current_thread->cpus_lock_nest == 0)
  58. {
  59. pcpu->current_thread->scheduler_lock_nest--;
  60. rt_hw_spin_unlock(&_cpus_lock);
  61. }
  62. }
  63. rt_hw_local_irq_enable(level);
  64. }
  65. RTM_EXPORT(rt_cpus_unlock);
  66. /**
  67. * This function is invoked by scheduler.
  68. * It will restore the lock state to whatever the thread's counter expects.
  69. * If target thread not locked the cpus then unlock the cpus lock.
  70. */
  71. void rt_cpus_lock_status_restore(struct rt_thread *thread)
  72. {
  73. struct rt_cpu* pcpu = rt_cpu_self();
  74. pcpu->current_thread = thread;
  75. if (!thread->cpus_lock_nest)
  76. {
  77. rt_hw_spin_unlock(&_cpus_lock);
  78. }
  79. }
  80. RTM_EXPORT(rt_cpus_lock_status_restore);
  81. #endif