The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/ipl_funcs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1997 Bruce Evans.
    3  * All rights reserved.
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/sysctl.h>
   33 #include <machine/ipl.h>
   34 #include <machine/globals.h>
   35 #include <i386/isa/intr_machdep.h>
   36 
   37 /*
   38  * Bits in the ipending bitmap variable must be set atomically because
   39  * ipending may be manipulated by interrupts or other cpu's without holding 
   40  * any locks.
   41  *
   42  * Note: setbits uses a locked or, making simple cases MP safe.
   43  */
   44 #define DO_SETBITS(name, var, bits) \
   45 void name(void)                                 \
   46 {                                               \
   47         atomic_set_int(var, bits);              \
   48 }
   49 
   50 DO_SETBITS(setdelayed,   &ipending, loadandclear(&idelayed))
   51 
   52 DO_SETBITS(setsoftcamnet,&ipending, SWI_CAMNET_PENDING)
   53 DO_SETBITS(setsoftcambio,&ipending, SWI_CAMBIO_PENDING)
   54 DO_SETBITS(setsoftclock, &ipending, SWI_CLOCK_PENDING)
   55 DO_SETBITS(setsoftnet,   &ipending, SWI_NET_PENDING)
   56 DO_SETBITS(setsofttty,   &ipending, SWI_TTY_PENDING)
   57 DO_SETBITS(setsoftvm,    &ipending, SWI_VM_PENDING)
   58 DO_SETBITS(setsofttq,    &ipending, SWI_TQ_PENDING)
   59 DO_SETBITS(setsoftcrypto,&ipending, SWI_CRYPTO_PENDING)
   60 
   61 DO_SETBITS(schedsoftcamnet, &idelayed, SWI_CAMNET_PENDING)
   62 DO_SETBITS(schedsoftcambio, &idelayed, SWI_CAMBIO_PENDING)
   63 DO_SETBITS(schedsoftnet, &idelayed, SWI_NET_PENDING)
   64 DO_SETBITS(schedsofttty, &idelayed, SWI_TTY_PENDING)
   65 DO_SETBITS(schedsoftvm, &idelayed, SWI_VM_PENDING)
   66 DO_SETBITS(schedsofttq, &idelayed, SWI_TQ_PENDING)
   67 
   68 unsigned
   69 softclockpending(void)
   70 {
   71         return (ipending & SWI_CLOCK_PENDING);
   72 }
   73 
   74 /*
   75  * Support for SPL assertions.
   76  */
   77 
   78 #ifdef INVARIANT_SUPPORT
   79 
   80 #define SPLASSERT_IGNORE        0
   81 #define SPLASSERT_LOG           1
   82 #define SPLASSERT_PANIC         2
   83 
   84 static int splassertmode = SPLASSERT_LOG;
   85 SYSCTL_INT(_kern, OID_AUTO, splassertmode, CTLFLAG_RW,
   86         &splassertmode, 0, "Set the mode of SPLASSERT");
   87 TUNABLE_INT("kern.splassertmode", &splassertmode);
   88 
   89 static void
   90 splassertfail(char *str, const char *msg, char *name, int level)
   91 {
   92         switch (splassertmode) {
   93         case SPLASSERT_IGNORE:
   94                 break;
   95         case SPLASSERT_LOG:
   96                 printf(str, msg, name, level);
   97                 printf("\n");
   98                 break;
   99         case SPLASSERT_PANIC:
  100                 panic(str, msg, name, level);
  101                 break;
  102         }
  103 }
  104 
  105 #define GENSPLASSERT(NAME, MODIFIER)                    \
  106 void                                                    \
  107 NAME##assert(const char *msg)                           \
  108 {                                                       \
  109         if ((cpl & (MODIFIER)) != (MODIFIER))           \
  110                 splassertfail("%s: not %s, cpl == %#x", \
  111                     msg, __XSTRING(NAME) + 3, cpl);     \
  112 }
  113 #else
  114 #define GENSPLASSERT(NAME, MODIFIER)
  115 #endif
  116 
  117 /************************************************************************
  118  *                      GENERAL SPL CODE                                *
  119  ************************************************************************
  120  *
  121  *  Implement splXXX(), spl0(), splx(), and splq().  splXXX() disables a
  122  *  set of interrupts (e.g. splbio() disables interrupts relating to 
  123  *  device I/O) and returns the previous interrupt mask.  splx() restores
  124  *  the previous interrupt mask, spl0() is a special case which enables
  125  *  all interrupts and is typically used inside i386/i386 swtch.s and
  126  *  fork_trampoline.  splq() is a generic version of splXXX().
  127  *
  128  *  The SPL routines mess around with the 'cpl' global, which masks 
  129  *  interrupts.  Interrupts are not *actually* masked.  What happens is 
  130  *  that if an interrupt masked by the cpl occurs, the appropriate bit
  131  *  in 'ipending' is set and the interrupt is defered.  When we clear
  132  *  bits in the cpl we must check to see if any ipending interrupts have
  133  *  been unmasked and issue the synchronously, which is what the splz()
  134  *  call does.
  135  *
  136  *  Because the cpl is often saved and restored in a nested fashion, cpl
  137  *  modifications are only allowed in the SMP case when the MP lock is held
  138  *  to prevent multiple processes from tripping over each other's masks.
  139  *  The cpl is saved when you do a context switch (mi_switch()) and restored
  140  *  when your process gets cpu again.
  141  *
  142  *  An interrupt routine is allowed to modify the cpl as long as it restores
  143  *  it prior to returning (thus the interrupted mainline code doesn't notice
  144  *  anything amiss).  For the SMP case, the interrupt routine must hold 
  145  *  the MP lock for any cpl manipulation.
  146  *
  147  *  Likewise, due to the deterministic nature of cpl modifications, we do
  148  *  NOT need to use locked instructions to modify it.
  149  */
  150 
  151 #ifndef SMP
  152 
  153 #define GENSPL(NAME, OP, MODIFIER, PC)          \
  154 GENSPLASSERT(NAME, MODIFIER)                    \
  155 unsigned NAME(void)                             \
  156 {                                               \
  157         unsigned x;                             \
  158                                                 \
  159         x = cpl;                                \
  160         cpl OP MODIFIER;                        \
  161         return (x);                             \
  162 }
  163 
  164 void
  165 spl0(void)
  166 {
  167         cpl = 0;
  168         if (ipending)
  169                 splz();
  170 }
  171 
  172 void
  173 splx(unsigned ipl)
  174 {
  175         cpl = ipl;
  176         if (ipending & ~ipl)
  177                 splz();
  178 }
  179 
  180 intrmask_t
  181 splq(intrmask_t mask)
  182 { 
  183         intrmask_t tmp = cpl;
  184         cpl |= mask;
  185         return (tmp);
  186 }       
  187 
  188 #else /* !SMP */
  189 
  190 #include <machine/smp.h>
  191 #include <machine/smptests.h>
  192 
  193 /*
  194  *      SMP CASE
  195  *
  196  *      Mostly the same as the non-SMP case now, but it didn't used to be
  197  *      this clean.
  198  */
  199 
  200 #define GENSPL(NAME, OP, MODIFIER, PC)          \
  201 GENSPLASSERT(NAME, MODIFIER)                    \
  202 unsigned NAME(void)                             \
  203 {                                               \
  204         unsigned x;                             \
  205                                                 \
  206         x = cpl;                                \
  207         cpl OP MODIFIER;                        \
  208                                                 \
  209         return (x);                             \
  210 }
  211 
  212 /*
  213  * spl0() -     unmask all interrupts
  214  *
  215  *      The MP lock must be held on entry
  216  *      This routine may only be called from mainline code.
  217  */
  218 void
  219 spl0(void)
  220 {
  221         KASSERT(inside_intr == 0, ("spl0: called from interrupt"));
  222         cpl = 0;
  223         if (ipending)
  224                 splz();
  225 }
  226 
  227 /*
  228  * splx() -     restore previous interrupt mask
  229  *
  230  *      The MP lock must be held on entry
  231  */
  232 
  233 void
  234 splx(unsigned ipl)
  235 {
  236         cpl = ipl;
  237         if (inside_intr == 0 && (ipending & ~cpl) != 0)
  238                 splz();
  239 }
  240 
  241 
  242 /*
  243  * splq() -     blocks specified interrupts
  244  *
  245  *      The MP lock must be held on entry
  246  */
  247 intrmask_t
  248 splq(intrmask_t mask)
  249 {
  250         intrmask_t tmp = cpl;
  251         cpl |= mask;
  252         return (tmp);
  253 }
  254 
  255 #endif /* !SMP */
  256 
  257 /* Finally, generate the actual spl*() functions */
  258 
  259 /*    NAME:            OP:     MODIFIER:                                PC: */
  260 GENSPL(splbio,          |=,     bio_imask,                              2)
  261 GENSPL(splcam,          |=,     cam_imask,                              7)
  262 GENSPL(splclock,         =,     HWI_MASK | SWI_MASK,                    3)
  263 GENSPL(splhigh,          =,     HWI_MASK | SWI_MASK,                    4)
  264 GENSPL(splimp,          |=,     net_imask,                              5)
  265 GENSPL(splnet,          |=,     SWI_NET_MASK,                           6)
  266 GENSPL(splsoftcam,      |=,     SWI_CAMBIO_MASK | SWI_CAMNET_MASK,      8)
  267 GENSPL(splsoftcambio,   |=,     SWI_CAMBIO_MASK,                        9)
  268 GENSPL(splsoftcamnet,   |=,     SWI_CAMNET_MASK,                        10)
  269 GENSPL(splsoftclock,     =,     SWI_CLOCK_MASK,                         11)
  270 GENSPL(splsofttty,      |=,     SWI_TTY_MASK,                           12)
  271 GENSPL(splsoftvm,       |=,     SWI_VM_MASK,                            16)
  272 GENSPL(splsofttq,       |=,     SWI_TQ_MASK,                            17)
  273 GENSPL(splstatclock,    |=,     stat_imask,                             13)
  274 GENSPL(spltty,          |=,     tty_imask,                              14)
  275 GENSPL(splvm,           |=,     net_imask | bio_imask | cam_imask,      15)
  276 GENSPL(splcrypto,       |=,     net_imask | SWI_NET_MASK | SWI_CRYPTO_MASK,16)

Cache object: 212867e6c76abe85bfb69fd2fe14b90e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.