irq_spinlock.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /****************************************************************************
  2. * sched/irq/irq_spinlock.c
  3. *
  4. * Copyright 2017,2018 Sony Video & Sound Products Inc.
  5. * Author: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <nuttx/spinlock.h>
  40. #include <sys/types.h>
  41. #include <arch/irq.h>
  42. #include "sched/sched.h"
  43. #if defined(CONFIG_SMP) && defined (CONFIG_SPINLOCK_IRQ) && \
  44. defined(CONFIG_ARCH_GLOBAL_IRQDISABLE)
  45. /****************************************************************************
  46. * Public Data
  47. ****************************************************************************/
  48. /* Used for access control */
  49. static volatile spinlock_t g_irq_spin SP_SECTION = SP_UNLOCKED;
  50. /* Handles nested calls to spin_lock_irqsave and spin_unlock_irqrestore */
  51. static volatile uint8_t g_irq_spin_count[CONFIG_SMP_NCPUS];
  52. /****************************************************************************
  53. * Public Functions
  54. ****************************************************************************/
  55. /****************************************************************************
  56. * Name: spin_lock_irqsave
  57. *
  58. * Description:
  59. * If SMP and SPINLOCK_IRQ are enabled:
  60. * Disable local interrupts and take the global spinlock (g_irq_spin)
  61. * if the call counter (g_irq_spin_count[cpu]) equals to 0. Then the
  62. * counter on the CPU is increment to allow nested call.
  63. *
  64. * NOTE: This API is very simple to protect data (e.g. H/W register
  65. * or internal data structure) in SMP mode. But do not use this API
  66. * with kernel APIs which suspend a caller thread. (e.g. nxsem_wait)
  67. *
  68. * If SMP and SPINLOCK_IRQ are not enabled:
  69. * This function is equivalent to enter_critical_section().
  70. *
  71. * Input Parameters:
  72. * None
  73. *
  74. * Returned Value:
  75. * An opaque, architecture-specific value that represents the state of
  76. * the interrupts prior to the call to spin_lock_irqsave();
  77. *
  78. ****************************************************************************/
  79. irqstate_t spin_lock_irqsave(void)
  80. {
  81. irqstate_t ret;
  82. ret = up_irq_save();
  83. int me = this_cpu();
  84. if (0 == g_irq_spin_count[me])
  85. {
  86. spin_lock(&g_irq_spin);
  87. }
  88. g_irq_spin_count[me]++;
  89. DEBUGASSERT(0 != g_irq_spin_count[me]);
  90. return ret;
  91. }
  92. /****************************************************************************
  93. * Name: spin_unlock_irqrestore
  94. *
  95. * Description:
  96. * If SMP and SPINLOCK_IRQ are enabled:
  97. * Decrement the call counter (g_irq_spin_count[cpu]) and if it
  98. * decrements to zero then release the spinlock (g_irq_spin) and
  99. * restore the interrupt state as it was prior to the previous call to
  100. * spin_lock_irqsave().
  101. *
  102. * If SMP and SPINLOCK_IRQ are not enabled:
  103. * This function is equivalent to leave_critical_section().
  104. *
  105. * Input Parameters:
  106. * flags - The architecture-specific value that represents the state of
  107. * the interrupts prior to the call to spin_lock_irqsave();
  108. *
  109. * Returned Value:
  110. * None
  111. *
  112. ****************************************************************************/
  113. void spin_unlock_irqrestore(irqstate_t flags)
  114. {
  115. int me = this_cpu();
  116. DEBUGASSERT(0 < g_irq_spin_count[me]);
  117. g_irq_spin_count[me]--;
  118. if (0 == g_irq_spin_count[me])
  119. {
  120. spin_unlock(&g_irq_spin);
  121. }
  122. up_irq_restore(flags);
  123. }
  124. #endif /* CONFIG_SMP && CONFIG_SPINLOCK_IRQ && CONFIG_ARCH_GLOBAL_IRQDISABLE */