diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-06 18:16:39 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-01-06 18:16:39 +0100 |
commit | 695fa51c80047eb25cc82e6e1630b4545a6bc0b6 (patch) | |
tree | aaee37e1b947c40dd660dc2ccb77ac20895e13f8 /util-linux/hwclock.c | |
parent | 06667f21d6d28bf3acbc12474cf52c9bc20c884b (diff) | |
download | busybox-w32-695fa51c80047eb25cc82e6e1630b4545a6bc0b6.tar.gz busybox-w32-695fa51c80047eb25cc82e6e1630b4545a6bc0b6.tar.bz2 busybox-w32-695fa51c80047eb25cc82e6e1630b4545a6bc0b6.zip |
hwclock: fix sizeof bug (used it on pointer, not array); make --systohc exact
function old new delta
hwclock_main 329 428 +99
rtc_adjtime_is_utc 138 134 -4
edir 365 354 -11
read_rtc 39 23 -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 99/-31) Total: 68 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux/hwclock.c')
-rw-r--r-- | util-linux/hwclock.c | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 6dff57f09..08e5bd701 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c | |||
@@ -27,27 +27,12 @@ static time_t read_rtc(int utc) | |||
27 | 27 | ||
28 | fd = rtc_xopen(&rtcname, O_RDONLY); | 28 | fd = rtc_xopen(&rtcname, O_RDONLY); |
29 | ret = rtc_read_time(fd, utc); | 29 | ret = rtc_read_time(fd, utc); |
30 | close(fd); | 30 | if (ENABLE_FEATURE_CLEAN_UP) |
31 | close(fd); | ||
31 | 32 | ||
32 | return ret; | 33 | return ret; |
33 | } | 34 | } |
34 | 35 | ||
35 | static void write_rtc(time_t t, int utc) | ||
36 | { | ||
37 | struct tm tm; | ||
38 | int rtc = rtc_xopen(&rtcname, O_WRONLY); | ||
39 | |||
40 | if (utc) | ||
41 | gmtime_r(&t, &tm); | ||
42 | else | ||
43 | localtime_r(&t, &tm); | ||
44 | tm.tm_isdst = 0; | ||
45 | |||
46 | xioctl(rtc, RTC_SET_TIME, &tm); | ||
47 | |||
48 | close(rtc); | ||
49 | } | ||
50 | |||
51 | static void show_clock(int utc) | 36 | static void show_clock(int utc) |
52 | { | 37 | { |
53 | //struct tm *ptm; | 38 | //struct tm *ptm; |
@@ -58,10 +43,10 @@ static void show_clock(int utc) | |||
58 | //ptm = localtime(&t); /* Sets 'tzname[]' */ | 43 | //ptm = localtime(&t); /* Sets 'tzname[]' */ |
59 | 44 | ||
60 | cp = ctime(&t); | 45 | cp = ctime(&t); |
61 | if (cp[0]) | 46 | strchrnul(cp, '\n')[0] = '\0'; |
62 | cp[strlen(cp) - 1] = '\0'; | ||
63 | 47 | ||
64 | //printf("%s %.6f seconds %s\n", cp, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0])); | 48 | //printf("%s 0.000000 seconds %s\n", cp, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0])); |
49 | /* 0.000000 stand for unimplemented difference between RTC and system clock */ | ||
65 | printf("%s 0.000000 seconds\n", cp); | 50 | printf("%s 0.000000 seconds\n", cp); |
66 | } | 51 | } |
67 | 52 | ||
@@ -81,12 +66,73 @@ static void to_sys_clock(int utc) | |||
81 | 66 | ||
82 | static void from_sys_clock(int utc) | 67 | static void from_sys_clock(int utc) |
83 | { | 68 | { |
69 | #define TWEAK_USEC 200 | ||
70 | struct tm tm; | ||
84 | struct timeval tv; | 71 | struct timeval tv; |
72 | unsigned adj = TWEAK_USEC; | ||
73 | int rtc = rtc_xopen(&rtcname, O_WRONLY); | ||
74 | |||
75 | /* Try to catch the moment when whole second is close */ | ||
76 | while (1) { | ||
77 | unsigned rem_usec; | ||
78 | time_t t; | ||
79 | |||
80 | gettimeofday(&tv, NULL); | ||
81 | |||
82 | rem_usec = 1000000 - tv.tv_usec; | ||
83 | if (rem_usec < 1024) { | ||
84 | /* Less than 1ms to next second. Good enough */ | ||
85 | small_rem: | ||
86 | tv.tv_sec++; | ||
87 | } | ||
88 | |||
89 | /* Prepare tm */ | ||
90 | t = tv.tv_sec; | ||
91 | if (utc) | ||
92 | gmtime_r(&t, &tm); /* may read /etc/xxx (it takes time) */ | ||
93 | else | ||
94 | localtime_r(&t, &tm); /* same */ | ||
95 | tm.tm_isdst = 0; | ||
96 | |||
97 | /* gmtime/localtime took some time, re-get cur time */ | ||
98 | gettimeofday(&tv, NULL); | ||
99 | |||
100 | if (tv.tv_sec < t /* may happen if rem_usec was < 1024 */ | ||
101 | || (tv.tv_sec == t && tv.tv_usec < 1024) | ||
102 | ) { | ||
103 | /* We are not too far into next second. Good. */ | ||
104 | break; | ||
105 | } | ||
106 | adj += 32; /* 2^(10-5) = 2^5 = 32 iterations max */ | ||
107 | if (adj >= 1024) { | ||
108 | /* Give up trying to sync */ | ||
109 | break; | ||
110 | } | ||
111 | |||
112 | /* Try to sync up by sleeping */ | ||
113 | rem_usec = 1000000 - tv.tv_usec; | ||
114 | if (rem_usec < 1024) { | ||
115 | goto small_rem; /* already close, don't sleep */ | ||
116 | } | ||
117 | /* Need to sleep. | ||
118 | * Note that small adj on slow processors can make us | ||
119 | * to always overshoot tv.tv_usec < 1024 check on next | ||
120 | * iteration. That's why adj is increased on each iteration. | ||
121 | * This also allows it to be reused as a loop limiter. | ||
122 | */ | ||
123 | usleep(rem_usec - adj); | ||
124 | } | ||
125 | |||
126 | xioctl(rtc, RTC_SET_TIME, &tm); | ||
127 | |||
128 | /* Debug aid to find "good" TWEAK_USEC. | ||
129 | * Look for a value which makes tv_usec close to 999999 or 0. | ||
130 | * for 2.20GHz Intel Core 2: TWEAK_USEC ~= 200 | ||
131 | */ | ||
132 | //bb_error_msg("tv.tv_usec:%d adj:%d", (int)tv.tv_usec, adj); | ||
85 | 133 | ||
86 | gettimeofday(&tv, NULL); | 134 | if (ENABLE_FEATURE_CLEAN_UP) |
87 | //if (gettimeofday(&tv, NULL)) | 135 | close(rtc); |
88 | // bb_perror_msg_and_die("gettimeofday() failed"); | ||
89 | write_rtc(tv.tv_sec, utc); | ||
90 | } | 136 | } |
91 | 137 | ||
92 | #define HWCLOCK_OPT_LOCALTIME 0x01 | 138 | #define HWCLOCK_OPT_LOCALTIME 0x01 |