Deleted Added
full compact
kern_tc.c (29179) kern_tc.c (29680)
1/*-
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.

--- 22 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
1/*-
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.

--- 22 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
39 * $Id: kern_clock.c,v 1.39 1997/09/02 20:05:37 bde Exp $
39 * $Id: kern_clock.c,v 1.40 1997/09/07 05:25:43 bde Exp $
40 */
41
42/* Portions of this software are covered by the following: */
43/******************************************************************************
44 * *
45 * Copyright (c) David L. Mills 1993, 1994 *
46 * *
47 * Permission to use, copy, modify, and distribute this software and its *

--- 33 unchanged lines hidden (view full) ---

81#ifdef GPROF
82#include <sys/gmon.h>
83#endif
84
85static void initclocks __P((void *dummy));
86SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
87
88/* Exported to machdep.c. */
40 */
41
42/* Portions of this software are covered by the following: */
43/******************************************************************************
44 * *
45 * Copyright (c) David L. Mills 1993, 1994 *
46 * *
47 * Permission to use, copy, modify, and distribute this software and its *

--- 33 unchanged lines hidden (view full) ---

81#ifdef GPROF
82#include <sys/gmon.h>
83#endif
84
85static void initclocks __P((void *dummy));
86SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
87
88/* Exported to machdep.c. */
89struct callout *callfree, *callout;
89struct callout *callout;
90struct callout_list callfree;
91int callwheelsize, callwheelbits, callwheelmask;
92struct callout_tailq *callwheel;
90
93
91static struct callout calltodo;
92
93/* Some of these don't belong here, but it's easiest to concentrate them. */
94static long cp_time[CPUSTATES];
95long dk_seek[DK_NDRIVE];
96static long dk_time[DK_NDRIVE]; /* time busy (in statclock ticks) */
97long dk_wds[DK_NDRIVE];
98long dk_wpms[DK_NDRIVE];
99long dk_xfer[DK_NDRIVE];

--- 49 unchanged lines hidden (view full) ---

149 tp->tv_sec++; \
150 } \
151}
152
153int stathz;
154int profhz;
155static int profprocs;
156int ticks;
94
95/* Some of these don't belong here, but it's easiest to concentrate them. */
96static long cp_time[CPUSTATES];
97long dk_seek[DK_NDRIVE];
98static long dk_time[DK_NDRIVE]; /* time busy (in statclock ticks) */
99long dk_wds[DK_NDRIVE];
100long dk_wpms[DK_NDRIVE];
101long dk_xfer[DK_NDRIVE];

--- 49 unchanged lines hidden (view full) ---

151 tp->tv_sec++; \
152 } \
153}
154
155int stathz;
156int profhz;
157static int profprocs;
158int ticks;
157static int psdiv, pscnt; /* prof => stat divider */
158int psratio; /* ratio: prof / stat */
159static int softticks; /* Like ticks, but for softclock(). */
160static struct callout *nextsoftcheck; /* Next callout to be checked. */
161static int psdiv, pscnt; /* prof => stat divider */
162int psratio; /* ratio: prof / stat */
159
160volatile struct timeval time;
161volatile struct timeval mono_time;
162
163/*
164 * Phase/frequency-lock loop (PLL/FLL) definitions
165 *
166 * The following variables are read and set by the ntp_adjtime() system

--- 280 unchanged lines hidden (view full) ---

447 * The real-time timer, interrupting hz times per second.
448 */
449void
450hardclock(frame)
451 register struct clockframe *frame;
452{
453 register struct callout *p1;
454 register struct proc *p;
163
164volatile struct timeval time;
165volatile struct timeval mono_time;
166
167/*
168 * Phase/frequency-lock loop (PLL/FLL) definitions
169 *
170 * The following variables are read and set by the ntp_adjtime() system

--- 280 unchanged lines hidden (view full) ---

451 * The real-time timer, interrupting hz times per second.
452 */
453void
454hardclock(frame)
455 register struct clockframe *frame;
456{
457 register struct callout *p1;
458 register struct proc *p;
455 register int needsoft;
456
459
457 /*
458 * Update real-time timeout queue.
459 * At front of queue are some number of events which are ``due''.
460 * The time to these is <= 0 and if negative represents the
461 * number of ticks which have passed since it was supposed to happen.
462 * The rest of the q elements (times > 0) are events yet to happen,
463 * where the time for each is given as a delta from the previous.
464 * Decrementing just the first of these serves to decrement the time
465 * to all events.
466 */
467 needsoft = 0;
468 for (p1 = calltodo.c_next; p1 != NULL; p1 = p1->c_next) {
469 if (--p1->c_time > 0)
470 break;
471 needsoft = 1;
472 if (p1->c_time == 0)
473 break;
474 }
475
476 p = curproc;
477 if (p) {
478 register struct pstats *pstats;
479
480 /*
481 * Run current process's virtual and profile time, as needed.
482 */
483 pstats = p->p_stats;

--- 188 unchanged lines hidden (view full) ---

672 }
673 CPU_CLOCKUPDATE(&time, &newtime);
674 }
675
676 /*
677 * Process callouts at a very low cpu priority, so we don't keep the
678 * relatively high clock interrupt priority any longer than necessary.
679 */
460 p = curproc;
461 if (p) {
462 register struct pstats *pstats;
463
464 /*
465 * Run current process's virtual and profile time, as needed.
466 */
467 pstats = p->p_stats;

--- 188 unchanged lines hidden (view full) ---

656 }
657 CPU_CLOCKUPDATE(&time, &newtime);
658 }
659
660 /*
661 * Process callouts at a very low cpu priority, so we don't keep the
662 * relatively high clock interrupt priority any longer than necessary.
663 */
680 if (needsoft) {
664 if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) {
681 if (CLKF_BASEPRI(frame)) {
682 /*
683 * Save the overhead of a software interrupt;
684 * it will happen as soon as we return, so do it now.
685 */
686 (void)splsoftclock();
687 softclock();
688 } else
689 setsoftclock();
665 if (CLKF_BASEPRI(frame)) {
666 /*
667 * Save the overhead of a software interrupt;
668 * it will happen as soon as we return, so do it now.
669 */
670 (void)splsoftclock();
671 softclock();
672 } else
673 setsoftclock();
674 } else if (softticks + 1 == ticks) {
675 ++softticks;
690 }
691}
692
693/*
676 }
677}
678
679/*
680 * The callout mechanism is based on the work of Adam M. Costello and
681 * George Varghese, published in a technical report entitled "Redesigning
682 * the BSD Callout and Timer Facilities" and modified slightly for inclusion
683 * in FreeBSD by Justin T. Gibbs. The original work on the data structures
684 * used in this implementation was published by G.Varghese and A. Lauck in
685 * the paper "Hashed and Hierarchical Timing Wheels: Data Structures for
686 * the Efficient Implementation of a Timer Facility" in the Proceedings of
687 * the 11th ACM Annual Symposium on Operating Systems Principles,
688 * Austin, Texas Nov 1987.
689 */
690/*
694 * Software (low priority) clock interrupt.
695 * Run periodic events from timeout queue.
696 */
697/*ARGSUSED*/
698void
699softclock()
700{
701 register struct callout *c;
691 * Software (low priority) clock interrupt.
692 * Run periodic events from timeout queue.
693 */
694/*ARGSUSED*/
695void
696softclock()
697{
698 register struct callout *c;
702 register void *arg;
703 register void (*func) __P((void *));
704 register int s;
699 register int s;
700 register int steps; /*
701 * Number of steps taken since
702 * we last allowed interrupts.
703 */
705
704
705 #ifndef MAX_SOFTCLOCK_STEPS
706 #define MAX_SOFTCLOCK_STEPS 100 /* Maximum allowed value of steps. */
707 #endif /* MAX_SOFTCLOCK_STEPS */
708
709 steps = 0;
706 s = splhigh();
710 s = splhigh();
707 while ((c = calltodo.c_next) != NULL && c->c_time <= 0) {
708 func = c->c_func;
709 arg = c->c_arg;
710 calltodo.c_next = c->c_next;
711 c->c_next = callfree;
712 callfree = c;
713 splx(s);
714 (*func)(arg);
715 (void) splhigh();
711 while (softticks != ticks) {
712 c = TAILQ_FIRST(&callwheel[++softticks & callwheelmask]);
713 while (c) {
714 if (c->c_time > 0) {
715 c->c_time--;
716 c = TAILQ_NEXT(c, c_links.tqe);
717 ++steps;
718 if (steps >= MAX_SOFTCLOCK_STEPS) {
719 nextsoftcheck = c;
720 splx(s);
721 /* Give hardclock() a chance. */
722 s = splhigh();
723 c = nextsoftcheck;
724 steps = 0;
725 }
726 } else {
727 void (*c_func)(void *);
728 void *c_arg;
729
730 nextsoftcheck = TAILQ_NEXT(c, c_links.tqe);
731 TAILQ_REMOVE(c->c_bucket, c, c_links.tqe);
732 c_func = c->c_func;
733 c_arg = c->c_arg;
734 c->c_func = NULL;
735 SLIST_INSERT_HEAD(&callfree, c, c_links.sle);
736 splx(s);
737 c_func(c_arg);
738 s = splhigh();
739 steps = 0;
740 c = nextsoftcheck;
741 }
742 }
716 }
743 }
744 nextsoftcheck = NULL;
717 splx(s);
718}
719
720/*
721 * timeout --
722 * Execute a function after a specified length of time.
723 *
724 * untimeout --
725 * Cancel previous timeout function call.
726 *
745 splx(s);
746}
747
748/*
749 * timeout --
750 * Execute a function after a specified length of time.
751 *
752 * untimeout --
753 * Cancel previous timeout function call.
754 *
755 * callout_handle_init --
756 * Initialize a handle so that using it with untimeout is benign.
757 *
727 * See AT&T BCI Driver Reference Manual for specification. This
758 * See AT&T BCI Driver Reference Manual for specification. This
728 * implementation differs from that one in that no identification
729 * value is returned from timeout, rather, the original arguments
730 * to timeout are used to identify entries for untimeout.
759 * implementation differs from that one in that although an
760 * identification value is returned from timeout, the original
761 * arguments to timeout as well as the identifier are used to
762 * identify entries for untimeout.
731 */
763 */
732void
733timeout(ftn, arg, ticks)
764struct callout_handle
765timeout(ftn, arg, to_ticks)
734 timeout_t ftn;
735 void *arg;
766 timeout_t ftn;
767 void *arg;
736 register int ticks;
768 register int to_ticks;
737{
769{
738 register struct callout *new, *p, *t;
739 register int s;
770 int s;
771 struct callout *new;
772 struct callout_handle handle;
740
773
741 if (ticks <= 0)
742 ticks = 1;
774 if (to_ticks <= 0)
775 to_ticks = 1;
743
744 /* Lock out the clock. */
745 s = splhigh();
746
747 /* Fill in the next free callout structure. */
776
777 /* Lock out the clock. */
778 s = splhigh();
779
780 /* Fill in the next free callout structure. */
748 if (callfree == NULL)
781 new = SLIST_FIRST(&callfree);
782 if (new == NULL)
783 /* XXX Attempt to malloc first */
749 panic("timeout table full");
784 panic("timeout table full");
750 new = callfree;
751 callfree = new->c_next;
785
786 SLIST_REMOVE_HEAD(&callfree, c_links.sle);
752 new->c_arg = arg;
753 new->c_func = ftn;
787 new->c_arg = arg;
788 new->c_func = ftn;
789 new->c_time = to_ticks >> callwheelbits;
790 new->c_bucket = &callwheel[(ticks + to_ticks) & callwheelmask];
791 TAILQ_INSERT_TAIL(new->c_bucket, new, c_links.tqe);
754
792
755 /*
756 * The time for each event is stored as a difference from the time
757 * of the previous event on the queue. Walk the queue, correcting
758 * the ticks argument for queue entries passed. Correct the ticks
759 * value for the queue entry immediately after the insertion point
760 * as well. Watch out for negative c_time values; these represent
761 * overdue events.
762 */
763 for (p = &calltodo;
764 (t = p->c_next) != NULL && ticks > t->c_time; p = t)
765 if (t->c_time > 0)
766 ticks -= t->c_time;
767 new->c_time = ticks;
768 if (t != NULL)
769 t->c_time -= ticks;
770
771 /* Insert the new entry into the queue. */
772 p->c_next = new;
773 new->c_next = t;
774 splx(s);
793 splx(s);
794 handle.callout = new;
795 return (handle);
775}
776
777void
796}
797
798void
778untimeout(ftn, arg)
799untimeout(ftn, arg, handle)
779 timeout_t ftn;
780 void *arg;
800 timeout_t ftn;
801 void *arg;
802 struct callout_handle handle;
781{
782 register struct callout *p, *t;
783 register int s;
784
803{
804 register struct callout *p, *t;
805 register int s;
806
785 s = splhigh();
786 for (p = &calltodo; (t = p->c_next) != NULL; p = t)
787 if (t->c_func == ftn && t->c_arg == arg) {
788 /* Increment next entry's tick count. */
789 if (t->c_next && t->c_time > 0)
790 t->c_next->c_time += t->c_time;
807 /*
808 * Check for a handle that was initialized
809 * by callout_handle_init, but never used
810 * for a real timeout.
811 */
812 if (handle.callout == NULL)
813 return;
791
814
792 /* Move entry from callout queue to callfree queue. */
793 p->c_next = t->c_next;
794 t->c_next = callfree;
795 callfree = t;
796 break;
815 s = splhigh();
816 if ((handle.callout->c_func == ftn)
817 && (handle.callout->c_arg == arg)) {
818 if (nextsoftcheck == handle.callout) {
819 nextsoftcheck = TAILQ_NEXT(handle.callout, c_links.tqe);
797 }
820 }
821 TAILQ_REMOVE(handle.callout->c_bucket,
822 handle.callout, c_links.tqe);
823 handle.callout->c_func = NULL;
824 SLIST_INSERT_HEAD(&callfree, handle.callout, c_links.sle);
825 }
798 splx(s);
799}
800
801void
826 splx(s);
827}
828
829void
830callout_handle_init(struct callout_handle *handle)
831{
832 handle->callout = NULL;
833}
834
835void
802gettime(struct timeval *tvp)
803{
804 int s;
805
806 s = splclock();
807 /* XXX should use microtime() iff tv_usec is used. */
808 *tvp = time;
809 splx(s);

--- 494 unchanged lines hidden ---
836gettime(struct timeval *tvp)
837{
838 int s;
839
840 s = splclock();
841 /* XXX should use microtime() iff tv_usec is used. */
842 *tvp = time;
843 splx(s);

--- 494 unchanged lines hidden ---