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.

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.

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.

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;

Bruce
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to