diff options
-rw-r--r-- | sys/i386/apm/apm.c | 18 | ||||
-rw-r--r-- | sys/i386/bios/apm.c | 18 | ||||
-rw-r--r-- | sys/kern/kern_clock.c | 69 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 69 | ||||
-rw-r--r-- | sys/kern/kern_timeout.c | 69 |
5 files changed, 236 insertions, 7 deletions
diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index 372efdf..59067c3 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -15,7 +15,7 @@ * * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm.c,v 1.65 1997/11/12 04:12:43 jdp Exp $ + * $Id: apm.c,v 1.66 1997/12/04 02:40:00 imp Exp $ */ #include <sys/param.h> @@ -365,8 +365,22 @@ apm_default_resume(void *arg) tmp_time = time; /* because 'time' is volatile */ timevaladd(&tmp_time, &diff_time); time = tmp_time; +#ifdef APM_FIXUP_CALLTODO + /* Calculate the delta time suspended */ + timevalsub(&resume_time, &suspend_time); + /* Fixup the calltodo list with the delta time. */ + adjust_timeout_calltodo(&resume_time); +#endif /* APM_FIXUP_CALLTODOK */ splx(pl); - second = resume_time.tv_sec - suspend_time.tv_sec; +#ifndef APM_FIXUP_CALLTODO + second = resume_time.tv_sec - suspend_time.tv_sec; +#else /* APM_FIXUP_CALLTODO */ + /* + * We've already calculated resume_time to be the delta between + * the suspend and the resume. + */ + second = resume_time.tv_sec; +#endif /* APM_FIXUP_CALLTODO */ hour = second / 3600; second %= 3600; minute = second / 60; diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index 372efdf..59067c3 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -15,7 +15,7 @@ * * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm.c,v 1.65 1997/11/12 04:12:43 jdp Exp $ + * $Id: apm.c,v 1.66 1997/12/04 02:40:00 imp Exp $ */ #include <sys/param.h> @@ -365,8 +365,22 @@ apm_default_resume(void *arg) tmp_time = time; /* because 'time' is volatile */ timevaladd(&tmp_time, &diff_time); time = tmp_time; +#ifdef APM_FIXUP_CALLTODO + /* Calculate the delta time suspended */ + timevalsub(&resume_time, &suspend_time); + /* Fixup the calltodo list with the delta time. */ + adjust_timeout_calltodo(&resume_time); +#endif /* APM_FIXUP_CALLTODOK */ splx(pl); - second = resume_time.tv_sec - suspend_time.tv_sec; +#ifndef APM_FIXUP_CALLTODO + second = resume_time.tv_sec - suspend_time.tv_sec; +#else /* APM_FIXUP_CALLTODO */ + /* + * We've already calculated resume_time to be the delta between + * the suspend and the resume. + */ + second = resume_time.tv_sec; +#endif /* APM_FIXUP_CALLTODO */ hour = second / 3600; second %= 3600; minute = second / 60; diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 220e4b5..4d28fd5 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.45 1997/11/24 15:15:27 bde Exp $ + * $Id: kern_clock.c,v 1.46 1997/12/08 22:56:10 fsmp Exp $ */ /* Portions of this software are covered by the following: */ @@ -1358,3 +1358,70 @@ hardpps(tvp, usec) pps_intcnt++; } #endif /* PPS_SYNC */ + +#ifdef APM_FIXUP_CALLTODO +/* + * Adjust the kernel calltodo timeout list. This routine is used after + * an APM resume to recalculate the calltodo timer list values with the + * number of hz's we have been sleeping. The next hardclock() will detect + * that there are fired timers and run softclock() to execute them. + * + * Please note, I have not done an exhaustive analysis of what code this + * might break. I am motivated to have my select()'s and alarm()'s that + * have expired during suspend firing upon resume so that the applications + * which set the timer can do the maintanence the timer was for as close + * as possible to the originally intended time. Testing this code for a + * week showed that resuming from a suspend resulted in 22 to 25 timers + * firing, which seemed independant on whether the suspend was 2 hours or + * 2 days. Your milage may vary. - Ken Key <key@cs.utk.edu> + */ +void +adjust_timeout_calltodo(time_change) + struct timeval *time_change; +{ + register struct callout *p; + unsigned long delta_ticks; + int s; + + /* + * How many ticks were we asleep? + * (stolen from hzto()). + */ + + /* Don't do anything */ + if (time_change->tv_sec < 0) + return; + else if (time_change->tv_sec <= LONG_MAX / 1000000) + delta_ticks = (time_change->tv_sec * 1000000 + + time_change->tv_usec + (tick - 1)) / tick + 1; + else if (time_change->tv_sec <= LONG_MAX / hz) + delta_ticks = time_change->tv_sec * hz + + (time_change->tv_usec + (tick - 1)) / tick + 1; + else + delta_ticks = LONG_MAX; + + if (delta_ticks > INT_MAX) + delta_ticks = INT_MAX; + + /* + * Now rip through the timer calltodo list looking for timers + * to expire. + */ + + /* don't collide with softclock() */ + s = splhigh(); + for (p = calltodo.c_next; p != NULL; p = p->c_next) { + p->c_time -= delta_ticks; + + /* Break if the timer had more time on it than delta_ticks */ + if (p->c_time > 0) + break; + + /* take back the ticks the timer didn't use (p->c_time <= 0) */ + delta_ticks = -p->c_time; + } + splx(s); + + return; +} +#endif /* APM_FIXUP_CALLTODO */ diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 220e4b5..4d28fd5 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.45 1997/11/24 15:15:27 bde Exp $ + * $Id: kern_clock.c,v 1.46 1997/12/08 22:56:10 fsmp Exp $ */ /* Portions of this software are covered by the following: */ @@ -1358,3 +1358,70 @@ hardpps(tvp, usec) pps_intcnt++; } #endif /* PPS_SYNC */ + +#ifdef APM_FIXUP_CALLTODO +/* + * Adjust the kernel calltodo timeout list. This routine is used after + * an APM resume to recalculate the calltodo timer list values with the + * number of hz's we have been sleeping. The next hardclock() will detect + * that there are fired timers and run softclock() to execute them. + * + * Please note, I have not done an exhaustive analysis of what code this + * might break. I am motivated to have my select()'s and alarm()'s that + * have expired during suspend firing upon resume so that the applications + * which set the timer can do the maintanence the timer was for as close + * as possible to the originally intended time. Testing this code for a + * week showed that resuming from a suspend resulted in 22 to 25 timers + * firing, which seemed independant on whether the suspend was 2 hours or + * 2 days. Your milage may vary. - Ken Key <key@cs.utk.edu> + */ +void +adjust_timeout_calltodo(time_change) + struct timeval *time_change; +{ + register struct callout *p; + unsigned long delta_ticks; + int s; + + /* + * How many ticks were we asleep? + * (stolen from hzto()). + */ + + /* Don't do anything */ + if (time_change->tv_sec < 0) + return; + else if (time_change->tv_sec <= LONG_MAX / 1000000) + delta_ticks = (time_change->tv_sec * 1000000 + + time_change->tv_usec + (tick - 1)) / tick + 1; + else if (time_change->tv_sec <= LONG_MAX / hz) + delta_ticks = time_change->tv_sec * hz + + (time_change->tv_usec + (tick - 1)) / tick + 1; + else + delta_ticks = LONG_MAX; + + if (delta_ticks > INT_MAX) + delta_ticks = INT_MAX; + + /* + * Now rip through the timer calltodo list looking for timers + * to expire. + */ + + /* don't collide with softclock() */ + s = splhigh(); + for (p = calltodo.c_next; p != NULL; p = p->c_next) { + p->c_time -= delta_ticks; + + /* Break if the timer had more time on it than delta_ticks */ + if (p->c_time > 0) + break; + + /* take back the ticks the timer didn't use (p->c_time <= 0) */ + delta_ticks = -p->c_time; + } + splx(s); + + return; +} +#endif /* APM_FIXUP_CALLTODO */ diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 220e4b5..4d28fd5 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.45 1997/11/24 15:15:27 bde Exp $ + * $Id: kern_clock.c,v 1.46 1997/12/08 22:56:10 fsmp Exp $ */ /* Portions of this software are covered by the following: */ @@ -1358,3 +1358,70 @@ hardpps(tvp, usec) pps_intcnt++; } #endif /* PPS_SYNC */ + +#ifdef APM_FIXUP_CALLTODO +/* + * Adjust the kernel calltodo timeout list. This routine is used after + * an APM resume to recalculate the calltodo timer list values with the + * number of hz's we have been sleeping. The next hardclock() will detect + * that there are fired timers and run softclock() to execute them. + * + * Please note, I have not done an exhaustive analysis of what code this + * might break. I am motivated to have my select()'s and alarm()'s that + * have expired during suspend firing upon resume so that the applications + * which set the timer can do the maintanence the timer was for as close + * as possible to the originally intended time. Testing this code for a + * week showed that resuming from a suspend resulted in 22 to 25 timers + * firing, which seemed independant on whether the suspend was 2 hours or + * 2 days. Your milage may vary. - Ken Key <key@cs.utk.edu> + */ +void +adjust_timeout_calltodo(time_change) + struct timeval *time_change; +{ + register struct callout *p; + unsigned long delta_ticks; + int s; + + /* + * How many ticks were we asleep? + * (stolen from hzto()). + */ + + /* Don't do anything */ + if (time_change->tv_sec < 0) + return; + else if (time_change->tv_sec <= LONG_MAX / 1000000) + delta_ticks = (time_change->tv_sec * 1000000 + + time_change->tv_usec + (tick - 1)) / tick + 1; + else if (time_change->tv_sec <= LONG_MAX / hz) + delta_ticks = time_change->tv_sec * hz + + (time_change->tv_usec + (tick - 1)) / tick + 1; + else + delta_ticks = LONG_MAX; + + if (delta_ticks > INT_MAX) + delta_ticks = INT_MAX; + + /* + * Now rip through the timer calltodo list looking for timers + * to expire. + */ + + /* don't collide with softclock() */ + s = splhigh(); + for (p = calltodo.c_next; p != NULL; p = p->c_next) { + p->c_time -= delta_ticks; + + /* Break if the timer had more time on it than delta_ticks */ + if (p->c_time > 0) + break; + + /* take back the ticks the timer didn't use (p->c_time <= 0) */ + delta_ticks = -p->c_time; + } + splx(s); + + return; +} +#endif /* APM_FIXUP_CALLTODO */ |