Deleted Added
full compact
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", "");