[EMAIL PROTECTED] wrote:
> 
>     Neither hwclock nor the /dev/rtc driver takes the following comment from
> set_rtc_mmss() in arch/i386/kernel/time.c into account.  As a result, using
> hwclock --systohc or --adjust always leaves the Hardware Clock 500 ms ahead of
> the System Clock:

[...]

> Shouldn't there be some kernel interface that hides this machine-dependency
> from user-level code; i.e., that sets time more precisely?

I don't have a problem with the rtc driver delaying 500ms before setting the
time since that is in fact a feature of the hardware, and it probably should
have done this from the beginning.  However I would have a problem with the 
rtc driver using system time (kernel xtime) to synchronize the start of that
delay - the user may want to synchronize the rtc with some external source.

Simple patch (2.4.0) to add the delay follows, along with a $0.02 test prog 
I used to make sure things behave as desired.  (I guess hwclock will still
require its own delay for when /dev/rtc isn't present and it goes direct.)

Paul.

--- drivers/char/rtc.c~ Sat Jan  6 05:40:24 2001
+++ drivers/char/rtc.c  Sun Jan  7 07:17:39 2001
@@ -40,6 +40,7 @@
  *     1.10b   Andrew Morton: SMP lock fix
  *     1.10c   Cesar Barros: SMP locking fixes and cleanup
  *     1.10d   Paul Gortmaker: delete paranoia check in rtc_exit
+ *     1.10e   Paul Gortmaker: wait 0.5s before writing time to rtc.
  */
 
 #define RTC_VERSION            "1.10d"
@@ -414,6 +415,13 @@
                        BIN_TO_BCD(mon);
                        BIN_TO_BCD(yrs);
                }
+
+               /* The second for which the clock is set is only 0.5s long */
+               spin_unlock_irq(&rtc_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(HZ/2);
+               set_current_state(TASK_RUNNING);
+               spin_lock_irq(&rtc_lock);
 
                save_control = CMOS_READ(RTC_CONTROL);
                CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);

   ----------------------8<-------------------8<-----------------------
/* 
 * set RTC when system time ticks over, and then read system time on
 * ten RTC interrupts.  An offset of 500,000 usec (0.5sec) will appear
 * for rtc drivers that don't schedule_timeout(HZ/2) before setting rtc
 * time, since the second for which the rtc is set is only 1/2 sec long.
 * With schedule_timeout(), it will be between (n-1)990,000 and (n)10,000
 * (Assumes RTC=UTC; change gmtime() to localtime() if not the case)
 */

#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
 
void main(void)

{

int i, fd, retval;
unsigned long data;
struct tm *tm;

struct timezone tz = {0,};
struct timeval start, now;

fd = open ("/dev/rtc", O_RDONLY);

if (fd ==  -1) {
        perror("/dev/rtc");
        exit(errno);
}
 
printf("ZZZzzz. Waiting for next second...\n");
gettimeofday(&start, &tz);
do {
        gettimeofday(&now, &tz);
} while (now.tv_sec == start.tv_sec);

tm = gmtime(&start.tv_sec);

retval = ioctl(fd, RTC_SET_TIME, tm);   /* need root */
if (retval == -1) {
        perror("ioctl");
        exit(errno);
}

ioctl(fd, RTC_UIE_ON);
printf("10 gettimeofday values (sec, usec) exactly when RTC updates:\n");

gettimeofday(&start, &tz);
for (i=0;i<10;i++){
        read(fd, &data, sizeof(unsigned long));    /* this blocks */
        gettimeofday(&now, &tz);
        printf("\t%ld\t%ld\n", now.tv_sec-start.tv_sec, now.tv_usec);
}

}
 





_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to