svn commit: r327774 - in head: . sys/i386/bios
Warner Losh
imp at bsdimp.com
Sun Jan 14 03:53:12 UTC 2018
On Sat, Jan 13, 2018 at 6:17 AM, Bruce Evans <brde at optusnet.com.au> wrote:
> On Wed, 10 Jan 2018, Warner Losh wrote:
>
> Log:
>> inittodr(0) actually sets the time, so there's no need to call
>> tc_setclock(). It's redundant. Tweak UPDATING based on code review of
>> past releases.
>>
>
> No, tc_setclock() is not redundant (except for bugs). initodr(0) sets
> a raw RTC time (plus a racy timezone offset). tc_setclock() is supposed to
> fix this up to a less raw time using calculations done at suspend time.
> The calculations are still done, so are even more bogus then when the
> fixup was null under FIXME (then the FIXME a least indicated what
> needed to be done).
>
> Modified: head/UPDATING
>> ============================================================
>> ==================
>> --- head/UPDATING Wed Jan 10 16:56:02 2018 (r327773)
>> +++ head/UPDATING Wed Jan 10 17:25:08 2018 (r327774)
>> @@ -53,8 +53,9 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
>>
>> 20180110:
>> On i386, pmtimer has been removed. It's functionality has been
>> folded
>> - into apm. It was a nop on ACPI. Users may need to remove it from
>> kernel
>> - config files.
>> + into apm. It was a nop on ACPI in current for a while now (but
>> was still
>> + needed on i386 in FreeBSD 11 and earlier). Users may need to
>> remove it
>> + from kernel config files.
>>
>
> It is indeed still needed in FreeBSD-11. acpci resume is still broken
> there
> on all arches except amd64, by bogusly ifdefing acpi_resync_clock() to do
> nothing except on amd64 (and even on amd64, there is a sysctl to give the
> same brokenness).
>
> pmtimer was made a no-op if acpi is configured in the same commit that
> fixed
> acpi resume.
>
> Modified: head/sys/i386/bios/apm.c
>> ============================================================
>> ==================
>> --- head/sys/i386/bios/apm.c Wed Jan 10 16:56:02 2018 (r327773)
>> +++ head/sys/i386/bios/apm.c Wed Jan 10 17:25:08 2018 (r327774)
>> @@ -1086,7 +1086,6 @@ apm_rtc_resume(void *arg __unused)
>> {
>> u_int second, minute, hour;
>> struct timeval resume_time, tmp_time;
>> - struct timespec ts;
>>
>> /* modified for adjkerntz */
>> timer_restore(); /* restore the all timers */
>> @@ -1097,14 +1096,11 @@ apm_rtc_resume(void *arg __unused)
>> /* Calculate the delta time suspended */
>> timevalsub(&resume_time, &suspend_time);
>>
>> - second = ts.tv_sec = resume_time.tv_sec;
>> - ts.tv_nsec = 0;
>> - tc_setclock(&ts);
>> -
>>
>
> The carefully calculated tmp_time is no longer used. It wasn't used before
> either, since ts was initialized to a wrong value. tmp_time was last used
> under FIXME, but that shouldn't have compiled either since FIXME was
> undefineable -- tmp_time as a write-only auto variable in all cases.
> The non-use of some of the other timestamp variables is harder to detect
> since they are static.
>
> tc_setclock() takes a delta-time as an arg. resume_time is already a
> delta-time, but I think it is complete garbage. resume_time was initially
> actually the resume time, but is abused to hole the suspension interval
> (delta-time). inittodr(0) already advanced the timecounter by
> approximately
> the suspension interval, and inittodr(&ts) gives a garbage time by
> advancing
> by this again.
>
> I think the correct second advance is simply diff_time which was calculated
> earlier. The dead tmp_time is <initial resume time> + diff_time. This was
> only used in the unreachable FIXME code because the "API" for that needed
> an
> absolute time.
>
> Untested fixes:
>
> X Index: apm.c
> X ===================================================================
> X --- apm.c (revision 327911)
> X +++ apm.c (working copy)
> X @@ -1067,17 +1067,17 @@
> X } while (apm_event != PMEV_NOEVENT);
> X }
> X X -static struct timeval suspend_time;
> X -static struct timeval diff_time;
> X +static struct timespec diff_time;
> X +static struct timespec suspend_time;
> X X static int
> X apm_rtc_suspend(void *arg __unused)
> X {
> X X - microtime(&diff_time);
> X - inittodr(0);
> X - microtime(&suspend_time);
> X - timevalsub(&diff_time, &suspend_time);
> X + nanotime(&diff_time); /* not a difference yet */
> X + inittodr(0); /* set tc to raw time seen by RTC
> */
> X + nanotime(&suspend_time); /* record this raw time */
> X + timespecsub(&diff_time, &suspend_time); /* diff between tc and RTC
> */
> X return (0);
> X }
> X X @@ -1084,23 +1084,22 @@
> X static int
> X apm_rtc_resume(void *arg __unused)
> X {
> X + struct timespec resume_time, suspend_interval;
> X u_int second, minute, hour;
>
> This already changes too much, so I didn't fix blind truncation of tv_sec
> starting in 2038 or other type botches for second/minute/hour.
>
I suspect this code will no longer be running in 2028, let alone 2038.
> X - struct timeval resume_time, tmp_time;
> X X - /* modified for adjkerntz */
> X - timer_restore(); /* restore the all timers */
> X - inittodr(0); /* adjust time to RTC */
> X - microtime(&resume_time);
> X - getmicrotime(&tmp_time);
> X - timevaladd(&tmp_time, &diff_time);
> X + timer_restore();
> X + inittodr(0); /* set tc to new raw RTC time */
> X + nanotime(&resume_time); /* record this raw time */
> X + tc_setclock(&diff_time); /* restore old diff to tc */
>
> Fixing tc_setclock() is the easiest part
>
tc_setclock() sets the absolute time. It's not a phase shift.
> X +
> X /* Calculate the delta time suspended */
> X - timevalsub(&resume_time, &suspend_time);
> X + suspend_interval = resume_time;
> X + timevalsub(&suspend_interval, &suspend_time);
>
> There are to many comments. I forgot to remove the one above after
> unobfuscating resume_time.
>
OK.
> X X -#ifdef PMTIMER_FIXUP_CALLTODO
> X - /* Fixup the calltodo list with the delta time. */
> X - adjust_timeout_calltodo(&resume_time);
> X -#endif /* PMTIMER_FIXUP_CALLTODO */
> X - second = resume_time.tv_sec;
> X +#ifdef PMTIMER_FIXUP_CALLTODO /* XXX needed unconditionally, but never
> worked */
> X + adjust_timeout_calltodo(&suspend_interval);
> X +#endif
> X + second = suspend_interval.tv_sec;
> X hour = second / 3600;
> X second %= 3600;
> X minute = second / 60;
>
How is this then, it fixes the delta vs time setting in your version and
tweaks variable names to remove banal comments....
static struct timespec suspend_time; /* Saved RTC time at
suspend */
static struct timespec diff_interval; /* Delta between systime
and RTC */
static int
apm_rtc_suspend(void *arg __unused)
{
nanotime(&diff_interval);
inittodr(0); /* systime = RTC */
nanotime(&suspend_time);
timespecsub(&diff_interval, &suspend_time);
return (0);
}
static int
apm_rtc_resume(void *arg __unused)
{
struct timespec resume_time, new_time, suspend_interval;
u_int second, minute, hour;
timer_restore();
inittodr(0); /* Set to updated RTC time */
nanotime(&resume_time);
new_time = resume_time;
timespecadd(&new_time, &diff_interval);
tc_setclock(&new_time); /* Pre-suspend system time + sleep
time */
suspend_interval = resume_time;
timespecsub(&suspend_interval, &suspend_time);
second = suspend_interval.tv_sec;
#ifdef FIXUP_CALLTODO
/* Fixup the calltodo list with the delta time. */
adjust_timeout_calltodo(&suspend_interval);
#endif /* PMTIMER_FIXUP_CALLTODO */
hour = second / 3600;
second %= 3600;
minute = second / 60;
second %= 60;
log(LOG_NOTICE, "wakeup from sleeping state (slept
%02d:%02d:%02d)\n",
hour, minute, second);
return (0);
}
More information about the svn-src-head
mailing list