kern_tc.c (33391) | kern_tc.c (33690) |
---|---|
1/*- | 1/*- |
2 * Copyright (c) 1997, 1998 Poul-Henning Kamp <phk@FreeBSD.org> |
|
2 * Copyright (c) 1982, 1986, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * --- 21 unchanged lines hidden (view full) --- 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 | 3 * Copyright (c) 1982, 1986, 1991, 1993 4 * The Regents of the University of California. All rights reserved. 5 * (c) UNIX System Laboratories, Inc. 6 * All or some portions of this file are derived from material licensed 7 * to the University of California by American Telephone and Telegraph 8 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 9 * the permission of UNIX System Laboratories, Inc. 10 * --- 21 unchanged lines hidden (view full) --- 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 |
39 * $Id: kern_clock.c,v 1.55 1998/02/06 12:13:22 eivind Exp $ | 40 * $Id: kern_clock.c,v 1.56 1998/02/15 13:55:06 phk Exp $ |
40 */ 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/dkstat.h> 45#include <sys/callout.h> 46#include <sys/kernel.h> 47#include <sys/proc.h> 48#include <sys/resourcevar.h> 49#include <sys/signalvar.h> 50#include <sys/timex.h> 51#include <vm/vm.h> 52#include <sys/lock.h> 53#include <vm/pmap.h> 54#include <vm/vm_map.h> 55#include <sys/sysctl.h> 56 57#include <machine/cpu.h> | 41 */ 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/dkstat.h> 46#include <sys/callout.h> 47#include <sys/kernel.h> 48#include <sys/proc.h> 49#include <sys/resourcevar.h> 50#include <sys/signalvar.h> 51#include <sys/timex.h> 52#include <vm/vm.h> 53#include <sys/lock.h> 54#include <vm/pmap.h> 55#include <vm/vm_map.h> 56#include <sys/sysctl.h> 57 58#include <machine/cpu.h> |
58#define CLOCK_HAIR /* XXX */ | |
59#include <machine/clock.h> 60#include <machine/limits.h> 61 62#ifdef GPROF 63#include <sys/gmon.h> 64#endif 65 66#if defined(SMP) && defined(BETTER_CLOCK) 67#include <machine/smp.h> 68#endif 69 70static void initclocks __P((void *dummy)); 71SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) 72 | 59#include <machine/clock.h> 60#include <machine/limits.h> 61 62#ifdef GPROF 63#include <sys/gmon.h> 64#endif 65 66#if defined(SMP) && defined(BETTER_CLOCK) 67#include <machine/smp.h> 68#endif 69 70static void initclocks __P((void *dummy)); 71SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) 72 |
73static void tco_forward __P((void)); 74static void tco_setscales __P((struct timecounter *tc)); 75 |
|
73/* Some of these don't belong here, but it's easiest to concentrate them. */ 74#if defined(SMP) && defined(BETTER_CLOCK) 75long cp_time[CPUSTATES]; 76#else 77static long cp_time[CPUSTATES]; 78#endif 79long dk_seek[DK_NDRIVE]; 80static long dk_time[DK_NDRIVE]; /* time busy (in statclock ticks) */ --- 5 unchanged lines hidden (view full) --- 86int dk_ndrive = 0; 87char dk_names[DK_NDRIVE][DK_NAMELEN]; 88 89long tk_cancc; 90long tk_nin; 91long tk_nout; 92long tk_rawcc; 93 | 76/* Some of these don't belong here, but it's easiest to concentrate them. */ 77#if defined(SMP) && defined(BETTER_CLOCK) 78long cp_time[CPUSTATES]; 79#else 80static long cp_time[CPUSTATES]; 81#endif 82long dk_seek[DK_NDRIVE]; 83static long dk_time[DK_NDRIVE]; /* time busy (in statclock ticks) */ --- 5 unchanged lines hidden (view full) --- 89int dk_ndrive = 0; 90char dk_names[DK_NDRIVE][DK_NAMELEN]; 91 92long tk_cancc; 93long tk_nin; 94long tk_nout; 95long tk_rawcc; 96 |
97struct timecounter *timecounter; 98 |
|
94/* 95 * Clock handling routines. 96 * | 99/* 100 * Clock handling routines. 101 * |
97 * This code is written to operate with two timers that run independently of 98 * each other. The main clock, running hz times per second, is used to keep 99 * track of real time. The second timer handles kernel and user profiling, 100 * and does resource use estimation. If the second timer is programmable, 101 * it is randomized to avoid aliasing between the two clocks. For example, 102 * the randomization prevents an adversary from always giving up the cpu 103 * just before its quantum expires. Otherwise, it would never accumulate 104 * cpu ticks. The mean frequency of the second timer is stathz. | 102 * This code is written to operate with two timers that run independently 103 * of each other. |
105 * | 104 * |
106 * If no second timer exists, stathz will be zero; in this case we drive 107 * profiling and statistics off the main clock. This WILL NOT be accurate; 108 * do not do it unless absolutely necessary. | 105 * The main clock, running hz times per second, is used to trigger 106 * interval timers, timeouts and rescheduling as needed. |
109 * | 107 * |
108 * The second timer handles kernel and user profiling, and does resource 109 * use estimation. If the second timer is programmable, it is randomized 110 * to avoid aliasing between the two clocks. For example, the 111 * randomization prevents an adversary from always giving up the cpu 112 * just before its quantum expires. Otherwise, it would never accumulate 113 * cpu ticks. The mean frequency of the second timer is stathz. 114 * If no second timer exists, stathz will be zero; in this case we 115 * drive profiling and statistics off the main clock. This WILL NOT 116 * be accurate; do not do it unless absolutely necessary. |
|
110 * The statistics clock may (or may not) be run at a higher rate while | 117 * The statistics clock may (or may not) be run at a higher rate while |
111 * profiling. This profile clock runs at profhz. We require that profhz 112 * be an integral multiple of stathz. | 118 * profiling. This profile clock runs at profhz. We require that 119 * profhz be an integral multiple of stathz. If the statistics clock 120 * is running fast, it must be divided by the ratio profhz/stathz for 121 * statistics. (For profiling, every tick counts.) |
113 * | 122 * |
114 * If the statistics clock is running fast, it must be divided by the ratio 115 * profhz/stathz for statistics. (For profiling, every tick counts.) | 123 * Time-of-day is maintained using a "timecounter", which may or may 124 * not be related to the hardware generating the above mentioned 125 * interrupts. |
116 */ 117 | 126 */ 127 |
118/* 119 * TODO: 120 * allocate more timeout table slots when table overflows. 121 */ 122 123/* 124 * Bump a timeval by a small number of usec's. 125 */ 126#define BUMPTIME(t, usec) { \ 127 register volatile struct timeval *tp = (t); \ 128 register long us; \ 129 \ 130 tp->tv_usec = us = tp->tv_usec + (usec); \ 131 if (us >= 1000000) { \ 132 tp->tv_usec = us - 1000000; \ 133 tp->tv_sec++; \ 134 } \ 135} 136 | |
137int stathz; 138int profhz; 139static int profprocs; 140int ticks; 141static int psdiv, pscnt; /* prof => stat divider */ | 128int stathz; 129int profhz; 130static int profprocs; 131int ticks; 132static int psdiv, pscnt; /* prof => stat divider */ |
142int psratio; /* ratio: prof / stat */ | 133int psratio; /* ratio: prof / stat */ |
143 144volatile struct timeval time; 145volatile struct timeval mono_time; 146 147/* 148 * Initialize clock frequencies and start both clocks running. 149 */ 150/* ARGSUSED*/ --- 22 unchanged lines hidden (view full) --- 173/* 174 * The real-time timer, interrupting hz times per second. 175 */ 176void 177hardclock(frame) 178 register struct clockframe *frame; 179{ 180 register struct proc *p; | 134 135volatile struct timeval time; 136volatile struct timeval mono_time; 137 138/* 139 * Initialize clock frequencies and start both clocks running. 140 */ 141/* ARGSUSED*/ --- 22 unchanged lines hidden (view full) --- 164/* 165 * The real-time timer, interrupting hz times per second. 166 */ 167void 168hardclock(frame) 169 register struct clockframe *frame; 170{ 171 register struct proc *p; |
181 int time_update; 182 struct timeval newtime = time; 183 long ltemp; | |
184 185 p = curproc; 186 if (p) { 187 register struct pstats *pstats; 188 189 /* 190 * Run current process's virtual and profile time, as needed. 191 */ --- 11 unchanged lines hidden (view full) --- 203 forward_hardclock(pscnt); 204#endif 205 /* 206 * If no separate statistics clock is available, run it from here. 207 */ 208 if (stathz == 0) 209 statclock(frame); 210 | 172 173 p = curproc; 174 if (p) { 175 register struct pstats *pstats; 176 177 /* 178 * Run current process's virtual and profile time, as needed. 179 */ --- 11 unchanged lines hidden (view full) --- 191 forward_hardclock(pscnt); 192#endif 193 /* 194 * If no separate statistics clock is available, run it from here. 195 */ 196 if (stathz == 0) 197 statclock(frame); 198 |
211 /* 212 * Increment the time-of-day. 213 */ | 199 tco_forward(); 200 |
214 ticks++; 215 | 201 ticks++; 202 |
216 if (timedelta == 0) { 217 time_update = CPU_THISTICKLEN(tick); 218 } else { 219 time_update = CPU_THISTICKLEN(tick) + tickdelta; 220 timedelta -= tickdelta; 221 } 222 BUMPTIME(&mono_time, time_update); 223 224 /* 225 * Compute the phase adjustment. If the low-order bits 226 * (time_phase) of the update overflow, bump the high-order bits 227 * (time_update). 228 */ 229 time_phase += time_adj; 230 if (time_phase <= -FINEUSEC) { 231 ltemp = -time_phase >> SHIFT_SCALE; 232 time_phase += ltemp << SHIFT_SCALE; 233 time_update -= ltemp; 234 } 235 else if (time_phase >= FINEUSEC) { 236 ltemp = time_phase >> SHIFT_SCALE; 237 time_phase -= ltemp << SHIFT_SCALE; 238 time_update += ltemp; 239 } 240 241 newtime.tv_usec += time_update; 242 /* 243 * On rollover of the second the phase adjustment to be used for 244 * the next second is calculated. Also, the maximum error is 245 * increased by the tolerance. If the PPS frequency discipline 246 * code is present, the phase is increased to compensate for the 247 * CPU clock oscillator frequency error. 248 * 249 * On a 32-bit machine and given parameters in the timex.h 250 * header file, the maximum phase adjustment is +-512 ms and 251 * maximum frequency offset is a tad less than) +-512 ppm. On a 252 * 64-bit machine, you shouldn't need to ask. 253 */ 254 if (newtime.tv_usec >= 1000000) { 255 newtime.tv_usec -= 1000000; 256 newtime.tv_sec++; 257 ntp_update_second(&newtime.tv_sec); 258 } 259 CPU_CLOCKUPDATE(&time, &newtime); 260 | |
261 if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) 262 setsoftclock(); 263} 264 265void 266gettime(struct timeval *tvp) 267{ 268 int s; --- 41 unchanged lines hidden (view full) --- 310 usec = tv->tv_usec - time.tv_usec; 311 splx(s); 312 if (usec < 0) { 313 sec--; 314 usec += 1000000; 315 } 316 if (sec < 0) { 317#ifdef DIAGNOSTIC | 203 if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) 204 setsoftclock(); 205} 206 207void 208gettime(struct timeval *tvp) 209{ 210 int s; --- 41 unchanged lines hidden (view full) --- 252 usec = tv->tv_usec - time.tv_usec; 253 splx(s); 254 if (usec < 0) { 255 sec--; 256 usec += 1000000; 257 } 258 if (sec < 0) { 259#ifdef DIAGNOSTIC |
260 if (sec == -1 && usec > 0) { 261 sec++; 262 usec -= 1000000; 263 } |
|
318 printf("hzto: negative time difference %ld sec %ld usec\n", 319 sec, usec); 320#endif 321 ticks = 1; 322 } else if (sec <= LONG_MAX / 1000000) 323 ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) 324 / tick + 1; 325 else if (sec <= LONG_MAX / hz) --- 198 unchanged lines hidden (view full) --- 524 clkinfo.stathz = stathz ? stathz : hz; 525 return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); 526} 527 528SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD, 529 0, 0, sysctl_kern_clockrate, "S,clockinfo",""); 530 531void | 264 printf("hzto: negative time difference %ld sec %ld usec\n", 265 sec, usec); 266#endif 267 ticks = 1; 268 } else if (sec <= LONG_MAX / 1000000) 269 ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1)) 270 / tick + 1; 271 else if (sec <= LONG_MAX / hz) --- 198 unchanged lines hidden (view full) --- 470 clkinfo.stathz = stathz ? stathz : hz; 471 return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req)); 472} 473 474SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD, 475 0, 0, sysctl_kern_clockrate, "S,clockinfo",""); 476 477void |
532nanotime(ts) 533 struct timespec *ts; | 478microtime(struct timeval *tv) |
534{ | 479{ |
535 struct timeval tv; 536 microtime(&tv); 537 ts->tv_sec = tv.tv_sec; 538 ts->tv_nsec = tv.tv_usec * 1000; | 480 struct timecounter *tc; 481 482 tc = (struct timecounter *)timecounter; 483 tv->tv_sec = tc->offset_sec; 484 tv->tv_usec = tc->offset_micro; 485 tv->tv_usec += 486 ((u_int64_t)tc->get_timedelta(tc) * tc->scale_micro) >> 32; 487 if (tv->tv_usec >= 1000000) { 488 tv->tv_usec -= 1000000; 489 tv->tv_sec++; 490 } |
539} | 491} |
492 493void 494nanotime(struct timespec *tv) 495{ 496 u_int32_t count; 497 u_int64_t delta; 498 struct timecounter *tc; 499 500 tc = (struct timecounter *)timecounter; 501 tv->tv_sec = tc->offset_sec; 502 count = tc->get_timedelta(tc); 503 delta = tc->offset_nano; 504 delta += ((u_int64_t)count * tc->scale_nano_f); 505 delta += ((u_int64_t)count * tc->scale_nano_i) << 32; 506 delta >>= 32; 507 if (delta >= 1000000000) { 508 delta -= 1000000000; 509 tv->tv_sec++; 510 } 511 tv->tv_nsec = delta; 512} 513 514static void 515tco_setscales(struct timecounter *tc) 516{ 517 u_int64_t scale; 518 519 scale = 1000000000LL << 32; 520 if (tc->adjustment > 0) 521 scale += (tc->adjustment * 1000LL) << 10; 522 else 523 scale -= (-tc->adjustment * 1000LL) << 10; 524 /* scale += tc->frequency >> 1; */ /* XXX do we want to round ? */ 525 scale /= tc->frequency; 526 tc->scale_micro = scale / 1000; 527 tc->scale_nano_f = scale & 0xffffffff; 528 tc->scale_nano_i = scale >> 32; 529} 530 531static u_int 532delta_timecounter(struct timecounter *tc) 533{ 534 return((tc->get_timecount() - tc->offset_count) & tc->counter_mask); 535} 536 537void 538init_timecounter(struct timecounter *tc) 539{ 540 struct timespec ts0, ts1; 541 int i; 542 543 if (!tc->get_timedelta) 544 tc->get_timedelta = delta_timecounter; 545 tc->adjustment = 0; 546 tco_setscales(tc); 547 tc->offset_count = tc->get_timecount(); 548 tc[0].tweak = &tc[0]; 549 tc[2] = tc[1] = tc[0]; 550 tc[1].other = &tc[2]; 551 tc[2].other = &tc[1]; 552 if (!timecounter) 553 timecounter = &tc[2]; 554 tc = &tc[1]; 555 556 /* 557 * Figure out the cost of calling this timecounter. 558 * XXX: The 1:15 ratio is a guess at reality. 559 */ 560 nanotime(&ts0); 561 for (i = 0; i < 16; i ++) 562 tc->get_timecount(); 563 for (i = 0; i < 240; i ++) 564 tc->get_timedelta(tc); 565 nanotime(&ts1); 566 ts1.tv_sec -= ts0.tv_sec; 567 tc->cost = ts1.tv_sec * 1000000000 + ts1.tv_nsec - ts0.tv_nsec; 568 tc->cost >>= 8; 569 printf("Timecounter \"%s\" frequency %lu Hz cost %u ns\n", 570 tc->name, tc->frequency, tc->cost); 571 572 /* XXX: For now always start using the counter. */ 573 tc->offset_count = tc->get_timecount(); 574 nanotime(&ts1); 575 tc->offset_nano = (u_int64_t)ts1.tv_nsec << 32; 576 tc->offset_micro = ts1.tv_nsec / 1000; 577 tc->offset_sec = ts1.tv_sec; 578 timecounter = tc; 579} 580 581void 582set_timecounter(struct timespec *ts) 583{ 584 struct timecounter *tc, *tco; 585 int s; 586 587 s = splclock(); 588 tc=timecounter->other; 589 tco = tc->other; 590 *tc = *timecounter; 591 tc->other = tco; 592 tc->offset_sec = ts->tv_sec; 593 tc->offset_nano = (u_int64_t)ts->tv_nsec << 32; 594 tc->offset_micro = ts->tv_nsec / 1000; 595 tc->offset_count = tc->get_timecount(); 596 time.tv_sec = tc->offset_sec; 597 time.tv_usec = tc->offset_micro; 598 timecounter = tc; 599 splx(s); 600} 601 602static struct timecounter * 603sync_other_counter(int flag) 604{ 605 struct timecounter *tc, *tco; 606 u_int32_t delta; 607 608 tc = timecounter->other; 609 tco = tc->other; 610 *tc = *timecounter; 611 tc->other = tco; 612 delta = tc->get_timedelta(tc); 613 tc->offset_count += delta; 614 tc->offset_count &= tc->counter_mask; 615 tc->offset_nano += (u_int64_t)delta * tc->scale_nano_f; 616 tc->offset_nano += (u_int64_t)delta * tc->scale_nano_i << 32; 617 if (flag) 618 return (tc); 619 if (tc->offset_nano > 1000000000ULL << 32) { 620 tc->offset_sec++; 621 tc->offset_nano -= 1000000000ULL << 32; 622 } 623 tc->offset_micro = (tc->offset_nano / 1000) >> 32; 624 return (tc); 625} 626 627static void 628tco_forward(void) 629{ 630 struct timecounter *tc; 631 u_int32_t time_update; 632 633 tc = sync_other_counter(1); 634 time_update = 0; 635 636 if (timedelta) { 637 time_update += tickdelta; 638 timedelta -= tickdelta; 639 } 640 mono_time.tv_usec += time_update + tick; 641 if (mono_time.tv_usec >= 1000000) { 642 mono_time.tv_usec -= 1000000; 643 mono_time.tv_sec++; 644 } 645 time_update *= 1000; 646 tc->offset_nano += (u_int64_t)time_update << 32; 647 if (tc->offset_nano >= 1000000000ULL << 32) { 648 tc->offset_nano -= 1000000000ULL << 32; 649 tc->offset_sec++; 650 tc->frequency = tc->tweak->frequency; 651 tc->adjustment = tc->tweak->adjustment; /* XXX remove this ? */ 652 ntp_update_second(tc); /* XXX only needed if xntpd runs */ 653 tco_setscales(tc); 654 } 655 /* 656 * Find the usec from the nsec. This is just as fast (one 657 * multiplication) and prevents skew between the two due 658 * to rounding errors. (2^32/1000 = 4294967.296) 659 */ 660 tc->offset_micro = (tc->offset_nano / 1000) >> 32; 661 time.tv_usec = tc->offset_micro; 662 time.tv_sec = tc->offset_sec; 663 timecounter = tc; 664} 665 666static int 667sysctl_kern_timecounter_frequency SYSCTL_HANDLER_ARGS 668{ 669 return (sysctl_handle_opaque(oidp, &timecounter->tweak->frequency, 670 sizeof(timecounter->tweak->frequency), req)); 671} 672 673static int 674sysctl_kern_timecounter_adjustment SYSCTL_HANDLER_ARGS 675{ 676 return (sysctl_handle_opaque(oidp, &timecounter->tweak->adjustment, 677 sizeof(timecounter->tweak->adjustment), req)); 678} 679 680SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); 681 682SYSCTL_PROC(_kern_timecounter, OID_AUTO, frequency, CTLTYPE_INT|CTLFLAG_RW, 683 0, sizeof(u_int) , sysctl_kern_timecounter_frequency, "I", ""); 684 685SYSCTL_PROC(_kern_timecounter, OID_AUTO, adjustment, CTLTYPE_INT|CTLFLAG_RW, 686 0, sizeof(int) , sysctl_kern_timecounter_adjustment, "I", ""); |
|