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/sparc64/sparc64/tick.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) 2001 Jake Burkholder.
    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 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/kernel.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/interrupt.h>
   35 #include <sys/pcpu.h>
   36 #include <sys/sysctl.h>
   37 #include <sys/timetc.h>
   38 
   39 #include <machine/clock.h>
   40 #include <machine/cpu.h>
   41 #include <machine/frame.h>
   42 #include <machine/intr_machdep.h>
   43 #include <machine/tick.h>
   44 #include <machine/ver.h>
   45 
   46 #define TICK_GRACE      10000
   47 
   48 SYSCTL_NODE(_machdep, OID_AUTO, tick, CTLFLAG_RD, 0, "tick statistics");
   49 
   50 static int adjust_edges = 0;
   51 SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_edges, CTLFLAG_RD, &adjust_edges,
   52     0, "total number of times tick interrupts got more than 12.5% behind");
   53 
   54 static int adjust_excess = 0;
   55 SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_excess, CTLFLAG_RD, &adjust_excess,
   56     0, "total number of ignored tick interrupts");
   57 
   58 static int adjust_missed = 0;
   59 SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_missed, CTLFLAG_RD, &adjust_missed,
   60     0, "total number of missed tick interrupts");
   61 
   62 static int adjust_ticks = 0;
   63 SYSCTL_INT(_machdep_tick, OID_AUTO, adjust_ticks, CTLFLAG_RD, &adjust_ticks,
   64     0, "total number of tick interrupts with adjustment");
   65 
   66 static void tick_hardclock(struct trapframe *);
   67 
   68 static uint64_t
   69 tick_cputicks(void)
   70 {
   71 
   72         return (rd(tick));
   73 }
   74 
   75 void
   76 cpu_initclocks(void)
   77 {
   78 
   79         stathz = hz;
   80         tick_start();
   81 }
   82 
   83 static __inline void
   84 tick_process(struct trapframe *tf)
   85 {
   86 
   87         if (PCPU_GET(cpuid) == 0)
   88                 hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf));
   89         else
   90                 hardclock_cpu(TRAPF_USERMODE(tf));
   91         if (profprocs != 0)
   92                 profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf));
   93         statclock(TRAPF_USERMODE(tf));
   94 }
   95 
   96 static void
   97 tick_hardclock(struct trapframe *tf)
   98 {
   99         u_long adj, s, tick, ref;
  100         long delta;
  101         int count;
  102 
  103         /*
  104          * The sequence of reading the TICK register, calculating the value
  105          * of the next tick and writing it to the TICK_CMPR register must not
  106          * be interrupted, not even by an IPI, otherwise a value that is in
  107          * the past could be written in the worst case, causing hardclock to
  108          * stop.
  109          */
  110         critical_enter();
  111         adj = PCPU_GET(tickadj);
  112         s = intr_disable();
  113         tick = rd(tick);
  114         wrtickcmpr(tick + tick_increment - adj, 0);
  115         intr_restore(s);
  116         ref = PCPU_GET(tickref);
  117         delta = tick - ref;
  118         count = 0;
  119         while (delta >= tick_increment) {
  120                 tick_process(tf);
  121                 delta -= tick_increment;
  122                 ref += tick_increment;
  123                 if (adj != 0)
  124                         adjust_ticks++;
  125                 count++;
  126         }
  127         if (count > 0) {
  128                 adjust_missed += count - 1;
  129                 if (delta > (tick_increment >> 3)) {
  130                         if (adj == 0)
  131                                 adjust_edges++;
  132                         adj = tick_increment >> 4;
  133                 } else
  134                         adj = 0;
  135         } else {
  136                 adj = 0;
  137                 adjust_excess++;
  138         }
  139         PCPU_SET(tickref, ref);
  140         PCPU_SET(tickadj, adj);
  141         critical_exit();
  142 }
  143 
  144 void
  145 tick_init(u_long clock)
  146 {
  147 
  148         tick_freq = clock;
  149         tick_MHz = clock / 1000000;
  150         tick_increment = clock / hz;
  151 
  152         /*
  153          * UltraSparc II[e,i] based systems come up with the tick interrupt
  154          * enabled and a handler that resets the tick counter, causing DELAY()
  155          * to not work properly when used early in boot.
  156          * UltraSPARC III based systems come up with the system tick interrupt
  157          * enabled, causing an interrupt storm on startup since they are not
  158          * handled.
  159          */
  160         tick_stop();
  161 
  162         set_cputicker(tick_cputicks, tick_freq, 0);
  163 }
  164 
  165 void
  166 tick_start(void)
  167 {
  168         u_long base, s;
  169 
  170         /*
  171          * Avoid stopping of hardclock in terms of a lost tick interrupt
  172          * by ensuring that the tick period is at least TICK_GRACE ticks.
  173          * This check would be better placed in tick_init(), however we
  174          * have to call tick_init() before cninit() in order to provide
  175          * the low-level console drivers with a working DELAY() which in
  176          * turn means we cannot use panic() in tick_init().
  177          */
  178         if (tick_increment < TICK_GRACE)
  179                 panic("%s: HZ too high, decrease to at least %ld", __func__,
  180                     tick_freq / TICK_GRACE);
  181 
  182         if (PCPU_GET(cpuid) == 0)
  183                 intr_setup(PIL_TICK, tick_hardclock, -1, NULL, NULL);
  184 
  185         /*
  186          * Try to make the tick interrupts as synchronously as possible on
  187          * all CPUs to avoid inaccuracies for migrating processes. Leave out
  188          * one tick to make sure that it is not missed.
  189          */
  190         PCPU_SET(tickadj, 0);
  191         s = intr_disable();
  192         base = rd(tick);
  193         base = roundup(base, tick_increment);
  194         PCPU_SET(tickref, base);
  195         wrtickcmpr(base + tick_increment, 0);
  196         intr_restore(s);
  197 }
  198 
  199 void
  200 tick_stop(void)
  201 {
  202 
  203         if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
  204                 wr(asr25, 1L << 63, 0);
  205         wrtickcmpr(1L << 63, 0);
  206 }

Cache object: 9bf0929f32296c4dbf607f83f76fd7be


[ 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.