spl.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright (c) 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /* Make sure to build out-of-line versions of spl inline functions */
  30. #define SPL_INLINE /* empty */
  31. #include <types.h>
  32. #include <lib.h>
  33. #include <cpu.h>
  34. #include <spl.h>
  35. #include <thread.h>
  36. #include <current.h>
  37. /*
  38. * Machine-independent interrupt handling functions.
  39. *
  40. * Traditionally, all this code is machine-dependent.
  41. *
  42. * However.
  43. *
  44. * Since on OS/161 we don't support interrupt levels on any platform,
  45. * all we require under this logic is cpu_irqoff() and cpu_irqon()
  46. * that explicitly turn interrupts off and on.
  47. *
  48. * If we had multiple interrupt levels, the number of levels would in
  49. * general be different on different platforms (depending on hardware
  50. * requirements and hardware capabilities) so things would get more
  51. * complicated -- but nearly all of this code could remain MI.
  52. */
  53. /*
  54. * Raise and lower the interrupt priority level.
  55. *
  56. * Each spinlock acquisition can raise and lower the priority level
  57. * independently. The spl calls also raise and lower the priority
  58. * level independently of the spinlocks. This is necessary because in
  59. * general spinlock acquisitions and releases don't nest perfectly,
  60. * and don't necessarily nest with respect to spl calls either.
  61. *
  62. * For example:
  63. *
  64. * struct spinlock red, blue;
  65. * int s;
  66. *
  67. * spinlock_acquire(&red);
  68. * s = splhigh();
  69. * spinlock_acquire(&blue);
  70. * splx(s);
  71. * spinlock_release(&red);
  72. * spinlock_release(&blue);
  73. *
  74. * In order to make this work we need to count the number of times
  75. * IPL_HIGH (or, if we had multiple interrupt priority levels, each
  76. * level independently) has been raised. Interrupts go off on the
  77. * first raise, and go on again only on the last lower.
  78. *
  79. * curthread->t_iplhigh_count is used to track this.
  80. */
  81. void
  82. splraise(int oldspl, int newspl)
  83. {
  84. struct thread *cur = curthread;
  85. /* only one priority level, only one valid args configuration */
  86. KASSERT(oldspl == IPL_NONE);
  87. KASSERT(newspl == IPL_HIGH);
  88. if (!CURCPU_EXISTS()) {
  89. /* before curcpu initialization; interrupts are off anyway */
  90. return;
  91. }
  92. if (cur->t_iplhigh_count == 0) {
  93. cpu_irqoff();
  94. }
  95. cur->t_iplhigh_count++;
  96. }
  97. void
  98. spllower(int oldspl, int newspl)
  99. {
  100. struct thread *cur = curthread;
  101. /* only one priority level, only one valid args configuration */
  102. KASSERT(oldspl == IPL_HIGH);
  103. KASSERT(newspl == IPL_NONE);
  104. if (!CURCPU_EXISTS()) {
  105. /* before curcpu initialization; interrupts are off anyway */
  106. return;
  107. }
  108. cur->t_iplhigh_count--;
  109. if (cur->t_iplhigh_count == 0) {
  110. cpu_irqon();
  111. }
  112. }
  113. /*
  114. * Disable or enable interrupts and adjust curspl setting. Return old
  115. * spl level.
  116. */
  117. int
  118. splx(int spl)
  119. {
  120. struct thread *cur = curthread;
  121. int ret;
  122. if (cur->t_curspl < spl) {
  123. /* turning interrupts off */
  124. splraise(cur->t_curspl, spl);
  125. ret = cur->t_curspl;
  126. cur->t_curspl = spl;
  127. }
  128. else if (cur->t_curspl > spl) {
  129. /* turning interrupts on */
  130. ret = cur->t_curspl;
  131. cur->t_curspl = spl;
  132. spllower(ret, spl);
  133. }
  134. else {
  135. /* do nothing */
  136. ret = spl;
  137. }
  138. return ret;
  139. }