diff options
| author | Oliver Fromme <olli@FreeBSD.org> | 2008-06-16 17:04:04 +0000 |
|---|---|---|
| committer | Oliver Fromme <olli@FreeBSD.org> | 2008-06-16 17:04:04 +0000 |
| commit | 25eed6867e77af33c3a09e21f167d1b534e18ac8 (patch) | |
| tree | a0de29cec6795e8433864a2ad0ce4bece0b24909 /sys/boot | |
| parent | 0cf1d3bf739a99f23bd8142a0d321fff6a112de4 (diff) | |
Notes
Diffstat (limited to 'sys/boot')
| -rw-r--r-- | sys/boot/i386/libi386/time.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/sys/boot/i386/libi386/time.c b/sys/boot/i386/libi386/time.c index 1db9a4a60688..183ac3c9ccb9 100644 --- a/sys/boot/i386/libi386/time.c +++ b/sys/boot/i386/libi386/time.c @@ -32,18 +32,16 @@ __FBSDID("$FreeBSD$"); #include "bootstrap.h" #include "libi386.h" +static int bios_seconds(void); + /* - * Return the time in seconds since the beginning of the day. - * - * If we pass midnight, don't wrap back to 0. + * Return the BIOS time-of-day value. * * XXX uses undocumented BCD support from libstand. */ - -time_t -time(time_t *t) +static int +bios_seconds(void) { - static time_t lasttime, now; int hr, minute, sec; v86.ctl = 0; @@ -55,7 +53,33 @@ time(time_t *t) minute = bcd2bin(v86.ecx & 0xff); /* minute in %cl */ sec = bcd2bin((v86.edx & 0xff00) >> 8); /* second in %dh */ - now = hr * 3600 + minute * 60 + sec; + return (hr * 3600 + minute * 60 + sec); +} + +/* + * Return the time in seconds since the beginning of the day. + * + * Some BIOSes (notably qemu) don't correctly read the RTC + * registers in an atomic way, sometimes returning bogus values. + * Therefore we "debounce" the reading by accepting it only when + * we got two identical values in succession. + * + * If we pass midnight, don't wrap back to 0. + */ +time_t +time(time_t *t) +{ + static time_t lasttime; + time_t now, check; + int try; + + try = 0; + check = bios_seconds(); + do { + now = check; + check = bios_seconds(); + } while (now != check && ++try < 1000); + if (now < lasttime) now += 24 * 3600; lasttime = now; |
