delay.c revision 302408
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org> 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz and Don Ahn. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 34 */ 35 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: stable/11/sys/x86/x86/delay.c 263008 2014-03-11 10:20:42Z royger $"); 38 39/* Generic x86 routines to handle delay */ 40 41#include <sys/param.h> 42#include <sys/systm.h> 43#include <sys/timetc.h> 44#include <sys/proc.h> 45#include <sys/kernel.h> 46#include <sys/sched.h> 47 48#include <machine/clock.h> 49#include <machine/cpu.h> 50#include <x86/init.h> 51 52static u_int 53get_tsc(__unused struct timecounter *tc) 54{ 55 56 return (rdtsc32()); 57} 58 59static int 60delay_tc(int n) 61{ 62 struct timecounter *tc; 63 timecounter_get_t *func; 64 uint64_t end, freq, now; 65 u_int last, mask, u; 66 67 tc = timecounter; 68 freq = atomic_load_acq_64(&tsc_freq); 69 if (tsc_is_invariant && freq != 0) { 70 func = get_tsc; 71 mask = ~0u; 72 } else { 73 if (tc->tc_quality <= 0) 74 return (0); 75 func = tc->tc_get_timecount; 76 mask = tc->tc_counter_mask; 77 freq = tc->tc_frequency; 78 } 79 now = 0; 80 end = freq * n / 1000000; 81 if (func == get_tsc) 82 sched_pin(); 83 last = func(tc) & mask; 84 do { 85 cpu_spinwait(); 86 u = func(tc) & mask; 87 if (u < last) 88 now += mask - last + u + 1; 89 else 90 now += u - last; 91 last = u; 92 } while (now < end); 93 if (func == get_tsc) 94 sched_unpin(); 95 return (1); 96} 97 98void 99DELAY(int n) 100{ 101 102 if (delay_tc(n)) 103 return; 104 105 init_ops.early_delay(n); 106} 107