root/kern/thread/spl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. splraise
  2. spllower
  3. splx

   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 
  30 /* Make sure to build out-of-line versions of spl inline functions */
  31 #define SPL_INLINE      /* empty */
  32 
  33 #include <types.h>
  34 #include <lib.h>
  35 #include <cpu.h>
  36 #include <spl.h>
  37 #include <thread.h>
  38 #include <current.h>
  39 
  40 /*
  41  * Machine-independent interrupt handling functions.
  42  *
  43  * Traditionally, all this code is machine-dependent.
  44  *
  45  * However.
  46  *
  47  * Since on OS/161 we don't support interrupt levels on any platform,
  48  * all we require under this logic is cpu_irqoff() and cpu_irqon()
  49  * that explicitly turn interrupts off and on.
  50  *
  51  * If we had multiple interrupt levels, the number of levels would in
  52  * general be different on different platforms (depending on hardware
  53  * requirements and hardware capabilities) so things would get more
  54  * complicated -- but nearly all of this code could remain MI.
  55  */
  56 
  57 
  58 /*
  59  * Raise and lower the interrupt priority level.
  60  *
  61  * Each spinlock acquisition can raise and lower the priority level
  62  * independently. The spl calls also raise and lower the priority
  63  * level independently of the spinlocks. This is necessary because in
  64  * general spinlock acquisitions and releases don't nest perfectly,
  65  * and don't necessarily nest with respect to spl calls either.
  66  *
  67  * For example:
  68  *
  69  *    struct spinlock red, blue;
  70  *    int s;
  71  *
  72  *    spinlock_acquire(&red);
  73  *    s = splhigh();
  74  *    spinlock_acquire(&blue);
  75  *    splx(s);
  76  *    spinlock_release(&red);
  77  *    spinlock_release(&blue);
  78  *
  79  * In order to make this work we need to count the number of times
  80  * IPL_HIGH (or, if we had multiple interrupt priority levels, each
  81  * level independently) has been raised. Interrupts go off on the
  82  * first raise, and go on again only on the last lower.
  83  *
  84  * curthread->t_iplhigh_count is used to track this.
  85  */
  86 void
  87 splraise(int oldspl, int newspl)
  88 {
  89         struct thread *cur = curthread;
  90 
  91         /* only one priority level, only one valid args configuration */
  92         KASSERT(oldspl == IPL_NONE);
  93         KASSERT(newspl == IPL_HIGH);
  94 
  95         if (!CURCPU_EXISTS()) {
  96                 /* before curcpu initialization; interrupts are off anyway */
  97                 return;
  98         }
  99 
 100         if (cur->t_iplhigh_count == 0) {
 101                 cpu_irqoff();
 102         }
 103         cur->t_iplhigh_count++;
 104 }
 105 
 106 void
 107 spllower(int oldspl, int newspl)
 108 {
 109         struct thread *cur = curthread;
 110 
 111         /* only one priority level, only one valid args configuration */
 112         KASSERT(oldspl == IPL_HIGH);
 113         KASSERT(newspl == IPL_NONE);
 114 
 115         if (!CURCPU_EXISTS()) {
 116                 /* before curcpu initialization; interrupts are off anyway */
 117                 return;
 118         }
 119 
 120         cur->t_iplhigh_count--;
 121         if (cur->t_iplhigh_count == 0) {
 122                 cpu_irqon();
 123         }
 124 }
 125 
 126 
 127 /*
 128  * Disable or enable interrupts and adjust curspl setting. Return old
 129  * spl level.
 130  */
 131 int
 132 splx(int spl)
 133 {
 134         struct thread *cur = curthread;
 135         int ret;
 136 
 137         if (cur->t_curspl < spl) {
 138                 /* turning interrupts off */
 139                 splraise(cur->t_curspl, spl);
 140                 ret = cur->t_curspl;
 141                 cur->t_curspl = spl;
 142         }
 143         else if (cur->t_curspl > spl) {
 144                 /* turning interrupts on */
 145                 ret = cur->t_curspl;
 146                 cur->t_curspl = spl;
 147                 spllower(ret, spl);
 148         }
 149         else {
 150                 /* do nothing */
 151                 ret = spl;
 152         }
 153 
 154         return ret;
 155 }

/* [<][>][^][v][top][bottom][index][help] */