From 244aad9bd14bc816ee1a7c3bd4abdf123e0066f4 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 30 Apr 2007 06:57:38 +0000 Subject: [PATCH] Store the frequency and cputimer used to initialize a periodic systimer. If the system cputimer changes, periodic systimers will be adjusted at the next timeout. This allows the cputimer to be changed with only minor glitches, which in turn will allow us to initialize with the 8254 and then later change over to the ACPI timer. Theoretically this allows the cputimer to be changed on the fly, after the system has booted, but the sysctl is read-only for now. --- sys/kern/kern_systimer.c | 30 +++++++++++++++++++++++++++++- sys/sys/systimer.h | 6 +++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_systimer.c b/sys/kern/kern_systimer.c index 72df27d40..a341dc97f 100644 --- a/sys/kern/kern_systimer.c +++ b/sys/kern/kern_systimer.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/kern/kern_systimer.c,v 1.8 2005/10/25 17:26:54 dillon Exp $ + * $DragonFly: src/sys/kern/kern_systimer.c,v 1.9 2007/04/30 06:57:38 dillon Exp $ */ /* @@ -43,6 +43,10 @@ * is sufficiently disconnected from this code to support both per-cpu * hardware timers or a single system-wide hardware timer. * + * WARNING! During early boot if a new system timer is selected, existing + * timeouts will not be effected and will thus occur slower or faster. + * periodic timers will be adjusted at the next periodic load. + * * Notes on machine-dependant code (in arch/arch/systimer.c) * * cputimer_intr_reload() Reload the one-shot (per-cpu basis) @@ -104,6 +108,11 @@ systimer_intr(sysclock_t *timep, int dummy, struct intrframe *frame) * multiples of the periodic rate. */ if (info->periodic) { + if (info->which != sys_cputimer) { + info->periodic = sys_cputimer->fromhz(info->freq); + info->which = sys_cputimer; + kprintf("readjusted systimer freq %p\n", info); + } info->time += info->periodic; if ((info->flags & SYSTF_NONQUEUED) && (int)(info->time - time) <= 0 @@ -205,6 +214,8 @@ systimer_init_periodic(systimer_t info, void *func, void *data, int hz) info->time = base_count + info->periodic; info->func = func; info->data = data; + info->freq = hz; + info->which = sys_cputimer; info->gd = mycpu; systimer_add(info); } @@ -221,12 +232,28 @@ systimer_init_periodic_nq(systimer_t info, void *func, void *data, int hz) info->time = base_count + info->periodic; info->func = func; info->data = data; + info->freq = hz; + info->which = sys_cputimer; info->gd = mycpu; info->flags |= SYSTF_NONQUEUED; systimer_add(info); } /* + * Adjust the periodic interval for a periodic timer which is already + * running. The current timeout is not effected. + */ +void +systimer_adjust_periodic(systimer_t info, int hz) +{ + crit_enter(); + info->periodic = sys_cputimer->fromhz(hz); + info->freq = hz; + info->which = sys_cputimer; + crit_exit(); +} + +/* * systimer_init_oneshot() * * Initialize a periodic timer at the specified frequency and add @@ -239,6 +266,7 @@ systimer_init_oneshot(systimer_t info, void *func, void *data, int us) info->time = sys_cputimer->count() + sys_cputimer->fromus(us); info->func = func; info->data = data; + info->which = sys_cputimer; info->gd = mycpu; systimer_add(info); } diff --git a/sys/sys/systimer.h b/sys/sys/systimer.h index fe4c3e8a9..e5fde5595 100644 --- a/sys/sys/systimer.h +++ b/sys/sys/systimer.h @@ -33,7 +33,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/sys/systimer.h,v 1.12 2007/01/07 00:44:33 dillon Exp $ + * $DragonFly: src/sys/sys/systimer.h,v 1.13 2007/04/30 06:57:36 dillon Exp $ */ #ifndef _SYS_SYSTIMER_H_ @@ -61,6 +61,8 @@ typedef struct systimer { systimer_func2_t func; void *data; int flags; + int freq; /* frequency if periodic */ + struct cputimer *which; /* which timer was used? */ struct globaldata *gd; /* cpu owning structure */ } *systimer_t; @@ -73,7 +75,9 @@ void systimer_add(systimer_t); void systimer_del(systimer_t); void systimer_init_periodic(systimer_t, void *, void *, int); void systimer_init_periodic_nq(systimer_t, void *, void *, int); +void systimer_adjust_periodic(systimer_t, int); void systimer_init_oneshot(systimer_t, void *, void *, int); +void systimer_changed(void); /* * cputimer interface. This provides a free-running (non-interrupt) -- 2.11.4.GIT