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/i386/microtime.s

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 /* -*- Fundamental -*- keep Emacs from f***ing up the formatting */
    2 /*
    3  * Copyright (c) 1993 The Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by the University of
   17  *      California, Berkeley and its contributors.
   18  * 4. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  *
   34  *      from: Steve McCanne's microtime code
   35  * $FreeBSD: src/sys/i386/i386/microtime.s,v 1.18.2.1 1999/09/05 08:11:13 peter Exp $
   36  */
   37 
   38 #include "opt_cpu.h"
   39 
   40 #include <machine/asmacros.h>
   41 
   42 #include <i386/isa/icu.h>
   43 #include <i386/isa/isa.h>
   44 #include <i386/isa/timerreg.h>
   45 
   46 ENTRY(microtime)
   47 
   48 #if defined(I586_CPU) || defined(I686_CPU)
   49         movl    _i586_ctr_freq, %ecx
   50         testl   %ecx, %ecx
   51         jne     pentium_microtime
   52 #else
   53         xorl    %ecx, %ecx      /* clear ecx */
   54 #endif
   55 
   56         movb    $TIMER_SEL0|TIMER_LATCH, %al    /* prepare to latch */
   57 
   58         pushfl
   59         cli                     /* disable interrupts */
   60 
   61         outb    %al, $TIMER_MODE        /* latch timer 0's counter */
   62         inb     $TIMER_CNTR0, %al       /* read counter value, LSB first */
   63         movb    %al, %cl
   64         inb     $TIMER_CNTR0, %al
   65         movb    %al, %ch
   66 
   67         /*
   68          * Now check for counter overflow.  This is tricky because the
   69          * timer chip doesn't let us atomically read the current counter
   70          * value and the output state (i.e., overflow state).  We have
   71          * to read the ICU interrupt request register (IRR) to see if the
   72          * overflow has occured.  Because we lack atomicity, we use
   73          * the (very accurate) heuristic that we only check for
   74          * overflow if the value read is close to the interrupt period.
   75          * E.g., if we just checked the IRR, we might read a non-overflowing
   76          * value close to 0, experience overflow, then read this overflow
   77          * from the IRR, and mistakenly add a correction to the "close
   78          * to zero" value.
   79          *
   80          * We compare the counter value to the prepared overflow threshold.
   81          * If the counter value is less than this, we assume the counter
   82          * didn't overflow between disabling timer interrupts and latching
   83          * the counter value above.  For example, we assume that interrupts
   84          * are enabled when we are called (or were disabled just a few
   85          * cycles before we are called and that the instructions before the
   86          * "cli" are fast) and that the "cli" and "outb" instructions take
   87          * less than 10 timer cycles to execute.  The last assumption is
   88          * very safe.
   89          *
   90          * Otherwise, the counter might have overflowed.  We check for this
   91          * condition by reading the interrupt request register out of the ICU.
   92          * If it overflowed, we add in one clock period.
   93          *
   94          * The heuristic is "very accurate" because it works 100% if we're
   95          * called with interrupts enabled.  Otherwise, it might not work.
   96          * Currently, only siointrts() calls us with interrupts disabled, so
   97          * the problem can be avoided at some cost to the general case.  The
   98          * costs are complications in callers to disable interrupts in
   99          * IO_ICU1 and extra reads of the IRR forced by a conservative
  100          * overflow threshold.
  101          *
  102          * In 2.0, we are called at splhigh() from mi_switch(), so we have
  103          * to allow for the overflow bit being in ipending instead of in
  104          * the IRR.  Our caller may have executed many instructions since
  105          * ipending was set, so the heuristic for the IRR is inappropriate
  106          * for ipending.  However, we don't need another heuristic, since
  107          * the "cli" suffices to lock ipending.
  108          */
  109 
  110         movl    _timer0_max_count, %edx /* prepare for 2 uses */
  111 
  112         testb   $IRQ0, _ipending        /* is a soft timer interrupt pending? */
  113         jne     overflow
  114 
  115         /* Do we have a possible overflow condition? */
  116         cmpl    _timer0_overflow_threshold, %ecx
  117         jbe     1f
  118 
  119         inb     $IO_ICU1, %al   /* read IRR in ICU */
  120         testb   $IRQ0, %al      /* is a hard timer interrupt pending? */
  121         je      1f
  122 overflow:
  123         subl    %edx, %ecx      /* some intr pending, count timer down through 0 */
  124 1:
  125 
  126         /*
  127          * Subtract counter value from max count since it is a count-down value.
  128          */
  129         subl    %ecx, %edx
  130 
  131         /* Adjust for partial ticks. */
  132         addl    _timer0_prescaler_count, %edx
  133 
  134         /*
  135          * To divide by 1.193200, we multiply by 27465 and shift right by 15.
  136          *
  137          * The multiplier was originally calculated to be
  138          *
  139          *      2^18 * 1000000 / 1193200 = 219698.
  140          *
  141          * The frequency is 1193200 to be compatible with rounding errors in
  142          * the calculation of the usual maximum count.  2^18 is the largest
  143          * power of 2 such that multiplying `i' by it doesn't overflow for i
  144          * in the range of interest ([0, 11932 + 5)).  We adjusted the
  145          * multiplier a little to minimise the average of
  146          *
  147          *      fabs(i / 1.1193200 - ((multiplier * i) >> 18))
  148          *
  149          * for i in the range and then removed powers of 2 to speed up the
  150          * multiplication and to avoid overflow for i outside the range
  151          * (i may be as high as 2^17 if the timer is programmed to its
  152          * maximum maximum count).  The absolute error is less than 1 for
  153          * all i in the range.
  154          */
  155 
  156 #if 0
  157         imul    $27465, %edx                            /* 25 cycles on a 486 */
  158 #else
  159         leal    (%edx,%edx,2), %eax     /* a = 3        2 cycles on a 486   */
  160         leal    (%edx,%eax,4), %eax     /* a = 13       2                   */
  161         movl    %eax, %ecx              /* c = 13       1                   */
  162         shl     $5, %eax                /* a = 416      2                   */
  163         addl    %ecx, %eax              /* a = 429      1                   */
  164         leal    (%edx,%eax,8), %eax     /* a = 3433     2                   */
  165         leal    (%edx,%eax,8), %eax     /* a = 27465    2 (total 12 cycles) */
  166 #endif /* 0 */
  167         shr     $15, %eax
  168 
  169 common_microtime:
  170         addl    _time+4, %eax   /* usec += time.tv_sec */
  171         movl    _time, %edx     /* sec = time.tv_sec */
  172 
  173         popfl                   /* restore interrupt mask */
  174 
  175         cmpl    $1000000, %eax  /* usec valid? */
  176         jb      1f
  177         subl    $1000000, %eax  /* adjust usec */
  178         incl    %edx            /* bump sec */
  179 1:
  180         movl    4(%esp), %ecx   /* load timeval pointer arg */
  181         movl    %edx, (%ecx)    /* tvp->tv_sec = sec */
  182         movl    %eax, 4(%ecx)   /* tvp->tv_usec = usec */
  183 
  184         ret
  185 
  186 #if defined(I586_CPU) || defined(I686_CPU)
  187         ALIGN_TEXT
  188 pentium_microtime:
  189         pushfl
  190         cli
  191         .byte   0x0f, 0x31      /* RDTSC */
  192         subl    _i586_ctr_bias, %eax
  193         mull    _i586_ctr_multiplier
  194         movl    %edx, %eax
  195         jmp     common_microtime
  196 #endif

Cache object: f5036706dbf9e3092c05eee1560a50f5


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