diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-12 15:51:29 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-06-12 15:51:29 +0200 |
commit | d0db975a9f399140ddb7dacdfffaf098df3e249b (patch) | |
tree | 4b9cbdad519a80e410dea6c2a917d77bd3209ad5 | |
parent | 58cdca3984beb4e1019ef5ccf1dd7361f032a9a6 (diff) | |
download | busybox-w32-d0db975a9f399140ddb7dacdfffaf098df3e249b.tar.gz busybox-w32-d0db975a9f399140ddb7dacdfffaf098df3e249b.tar.bz2 busybox-w32-d0db975a9f399140ddb7dacdfffaf098df3e249b.zip |
post-1.16.1 fixes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/cpio.c | 2 | ||||
-rw-r--r-- | editors/sed.c | 24 | ||||
-rw-r--r-- | include/platform.h | 2 | ||||
-rw-r--r-- | networking/dnsd.c | 14 | ||||
-rw-r--r-- | networking/httpd_indexcgi.c | 2 | ||||
-rw-r--r-- | networking/udhcp/leases.c | 2 | ||||
-rw-r--r-- | shell/ash.c | 6 | ||||
-rw-r--r-- | shell/hush.c | 2 | ||||
-rwxr-xr-x | testsuite/cpio.tests | 8 | ||||
-rwxr-xr-x | testsuite/sed.tests | 24 | ||||
-rw-r--r-- | util-linux/hwclock.c | 112 |
11 files changed, 149 insertions, 49 deletions
diff --git a/archival/cpio.c b/archival/cpio.c index 858e59b30..2698f0791 100644 --- a/archival/cpio.c +++ b/archival/cpio.c | |||
@@ -424,7 +424,7 @@ int cpio_main(int argc UNUSED_PARAM, char **argv) | |||
424 | if (archive_handle->cpio__blocks != (off_t)-1 | 424 | if (archive_handle->cpio__blocks != (off_t)-1 |
425 | && !(opt & CPIO_OPT_QUIET) | 425 | && !(opt & CPIO_OPT_QUIET) |
426 | ) { | 426 | ) { |
427 | printf("%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); | 427 | fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); |
428 | } | 428 | } |
429 | 429 | ||
430 | return EXIT_SUCCESS; | 430 | return EXIT_SUCCESS; |
diff --git a/editors/sed.c b/editors/sed.c index fd9dd1be6..4289aa646 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -487,7 +487,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
487 | static void add_cmd(const char *cmdstr) | 487 | static void add_cmd(const char *cmdstr) |
488 | { | 488 | { |
489 | sed_cmd_t *sed_cmd; | 489 | sed_cmd_t *sed_cmd; |
490 | int temp; | 490 | unsigned len, n; |
491 | 491 | ||
492 | /* Append this line to any unfinished line from last time. */ | 492 | /* Append this line to any unfinished line from last time. */ |
493 | if (G.add_cmd_line) { | 493 | if (G.add_cmd_line) { |
@@ -496,12 +496,14 @@ static void add_cmd(const char *cmdstr) | |||
496 | cmdstr = G.add_cmd_line = tp; | 496 | cmdstr = G.add_cmd_line = tp; |
497 | } | 497 | } |
498 | 498 | ||
499 | /* If this line ends with backslash, request next line. */ | 499 | /* If this line ends with unescaped backslash, request next line. */ |
500 | temp = strlen(cmdstr); | 500 | n = len = strlen(cmdstr); |
501 | if (temp && cmdstr[--temp] == '\\') { | 501 | while (n && cmdstr[n-1] == '\\') |
502 | n--; | ||
503 | if ((len - n) & 1) { /* if odd number of trailing backslashes */ | ||
502 | if (!G.add_cmd_line) | 504 | if (!G.add_cmd_line) |
503 | G.add_cmd_line = xstrdup(cmdstr); | 505 | G.add_cmd_line = xstrdup(cmdstr); |
504 | G.add_cmd_line[temp] = '\0'; | 506 | G.add_cmd_line[len-1] = '\0'; |
505 | return; | 507 | return; |
506 | } | 508 | } |
507 | 509 | ||
@@ -936,7 +938,15 @@ static void process_files(void) | |||
936 | /* Skip blocks of commands we didn't match */ | 938 | /* Skip blocks of commands we didn't match */ |
937 | if (sed_cmd->cmd == '{') { | 939 | if (sed_cmd->cmd == '{') { |
938 | if (sed_cmd->invert ? matched : !matched) { | 940 | if (sed_cmd->invert ? matched : !matched) { |
939 | while (sed_cmd->cmd != '}') { | 941 | unsigned nest_cnt = 0; |
942 | while (1) { | ||
943 | if (sed_cmd->cmd == '{') | ||
944 | nest_cnt++; | ||
945 | if (sed_cmd->cmd == '}') { | ||
946 | nest_cnt--; | ||
947 | if (nest_cnt == 0) | ||
948 | break; | ||
949 | } | ||
940 | sed_cmd = sed_cmd->next; | 950 | sed_cmd = sed_cmd->next; |
941 | if (!sed_cmd) | 951 | if (!sed_cmd) |
942 | bb_error_msg_and_die("unterminated {"); | 952 | bb_error_msg_and_die("unterminated {"); |
@@ -1031,7 +1041,7 @@ static void process_files(void) | |||
1031 | case 'c': | 1041 | case 'c': |
1032 | /* Only triggers on last line of a matching range. */ | 1042 | /* Only triggers on last line of a matching range. */ |
1033 | if (!sed_cmd->in_match) | 1043 | if (!sed_cmd->in_match) |
1034 | sed_puts(sed_cmd->string, NO_EOL_CHAR); | 1044 | sed_puts(sed_cmd->string, '\n'); |
1035 | goto discard_line; | 1045 | goto discard_line; |
1036 | 1046 | ||
1037 | /* Read file, append contents to output */ | 1047 | /* Read file, append contents to output */ |
diff --git a/include/platform.h b/include/platform.h index a41daa08c..804fab4e1 100644 --- a/include/platform.h +++ b/include/platform.h | |||
@@ -291,10 +291,12 @@ typedef unsigned smalluint; | |||
291 | #if 1 /* if needed: !defined(arch1) && !defined(arch2) */ | 291 | #if 1 /* if needed: !defined(arch1) && !defined(arch2) */ |
292 | # define ALIGN1 __attribute__((aligned(1))) | 292 | # define ALIGN1 __attribute__((aligned(1))) |
293 | # define ALIGN2 __attribute__((aligned(2))) | 293 | # define ALIGN2 __attribute__((aligned(2))) |
294 | # define ALIGN4 __attribute__((aligned(4))) | ||
294 | #else | 295 | #else |
295 | /* Arches which MUST have 2 or 4 byte alignment for everything are here */ | 296 | /* Arches which MUST have 2 or 4 byte alignment for everything are here */ |
296 | # define ALIGN1 | 297 | # define ALIGN1 |
297 | # define ALIGN2 | 298 | # define ALIGN2 |
299 | # define ALIGN4 | ||
298 | #endif | 300 | #endif |
299 | 301 | ||
300 | 302 | ||
diff --git a/networking/dnsd.c b/networking/dnsd.c index 56ede3fca..1a4ccb911 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c | |||
@@ -44,10 +44,15 @@ struct dns_head { | |||
44 | uint16_t nauth; | 44 | uint16_t nauth; |
45 | uint16_t nadd; | 45 | uint16_t nadd; |
46 | }; | 46 | }; |
47 | /* Structure used to access type and class fields. | ||
48 | * They are totally unaligned, but gcc 4.3.4 thinks that pointer of type uint16_t* | ||
49 | * is 16-bit aligned and replaces 16-bit memcpy (in move_from_unaligned16 macro) | ||
50 | * with aligned halfword access on arm920t! | ||
51 | * Oh well. Slapping PACKED everywhere seems to help: */ | ||
47 | struct dns_prop { | 52 | struct dns_prop { |
48 | uint16_t type; | 53 | uint16_t type PACKED; |
49 | uint16_t class; | 54 | uint16_t class PACKED; |
50 | }; | 55 | } PACKED; |
51 | /* element of known name, ip address and reversed ip address */ | 56 | /* element of known name, ip address and reversed ip address */ |
52 | struct dns_entry { | 57 | struct dns_entry { |
53 | struct dns_entry *next; | 58 | struct dns_entry *next; |
@@ -459,7 +464,8 @@ int dnsd_main(int argc UNUSED_PARAM, char **argv) | |||
459 | unsigned lsa_size; | 464 | unsigned lsa_size; |
460 | int udps, opts; | 465 | int udps, opts; |
461 | uint16_t port = 53; | 466 | uint16_t port = 53; |
462 | uint8_t buf[MAX_PACK_LEN + 1]; | 467 | /* Ensure buf is 32bit aligned (we need 16bit, but 32bit can't hurt) */ |
468 | uint8_t buf[MAX_PACK_LEN + 1] ALIGN4; | ||
463 | 469 | ||
464 | opts = getopt32(argv, "vi:c:t:p:d", &listen_interface, &fileconf, &sttl, &sport); | 470 | opts = getopt32(argv, "vi:c:t:p:d", &listen_interface, &fileconf, &sttl, &sport); |
465 | //if (opts & 0x1) // -v | 471 | //if (opts & 0x1) // -v |
diff --git a/networking/httpd_indexcgi.c b/networking/httpd_indexcgi.c index 9fa7c7481..af4338006 100644 --- a/networking/httpd_indexcgi.c +++ b/networking/httpd_indexcgi.c | |||
@@ -315,7 +315,7 @@ int main(int argc, char *argv[]) | |||
315 | if (S_ISREG(cdir->dl_mode)) | 315 | if (S_ISREG(cdir->dl_mode)) |
316 | fmt_ull(cdir->dl_size); | 316 | fmt_ull(cdir->dl_size); |
317 | fmt_str("<td class=dt>"); | 317 | fmt_str("<td class=dt>"); |
318 | tm = gmtime(&cdir->dl_mtime); | 318 | ptm = gmtime(&cdir->dl_mtime); |
319 | fmt_04u(1900 + ptm->tm_year); *dst++ = '-'; | 319 | fmt_04u(1900 + ptm->tm_year); *dst++ = '-'; |
320 | fmt_02u(ptm->tm_mon + 1); *dst++ = '-'; | 320 | fmt_02u(ptm->tm_mon + 1); *dst++ = '-'; |
321 | fmt_02u(ptm->tm_mday); *dst++ = ' '; | 321 | fmt_02u(ptm->tm_mday); *dst++ = ' '; |
diff --git a/networking/udhcp/leases.c b/networking/udhcp/leases.c index 78b0d0ade..7b6bb2066 100644 --- a/networking/udhcp/leases.c +++ b/networking/udhcp/leases.c | |||
@@ -64,6 +64,8 @@ struct dyn_lease* FAST_FUNC add_lease( | |||
64 | oldest->hostname[0] = '\0'; | 64 | oldest->hostname[0] = '\0'; |
65 | if (hostname) { | 65 | if (hostname) { |
66 | char *p; | 66 | char *p; |
67 | |||
68 | hostname_len++; /* include NUL */ | ||
67 | if (hostname_len > sizeof(oldest->hostname)) | 69 | if (hostname_len > sizeof(oldest->hostname)) |
68 | hostname_len = sizeof(oldest->hostname); | 70 | hostname_len = sizeof(oldest->hostname); |
69 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); | 71 | p = safe_strncpy(oldest->hostname, hostname, hostname_len); |
diff --git a/shell/ash.c b/shell/ash.c index 34f70ecfc..e018e877b 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -5059,7 +5059,7 @@ static int is_hidden_fd(struct redirtab *rp, int fd) | |||
5059 | return 0; | 5059 | return 0; |
5060 | pf = g_parsefile; | 5060 | pf = g_parsefile; |
5061 | while (pf) { | 5061 | while (pf) { |
5062 | if (fd == pf->fd) { | 5062 | if (pf->fd > 0 && fd == pf->fd) { |
5063 | return 1; | 5063 | return 1; |
5064 | } | 5064 | } |
5065 | pf = pf->prev; | 5065 | pf = pf->prev; |
@@ -5424,7 +5424,11 @@ rmescapes(char *str, int flag) | |||
5424 | size_t fulllen = len + strlen(p) + 1; | 5424 | size_t fulllen = len + strlen(p) + 1; |
5425 | 5425 | ||
5426 | if (flag & RMESCAPE_GROW) { | 5426 | if (flag & RMESCAPE_GROW) { |
5427 | int strloc = str - (char *)stackblock(); | ||
5427 | r = makestrspace(fulllen, expdest); | 5428 | r = makestrspace(fulllen, expdest); |
5429 | /* p and str may be invalidated by makestrspace */ | ||
5430 | str = (char *)stackblock() + strloc; | ||
5431 | p = str + len; | ||
5428 | } else if (flag & RMESCAPE_HEAP) { | 5432 | } else if (flag & RMESCAPE_HEAP) { |
5429 | r = ckmalloc(fulllen); | 5433 | r = ckmalloc(fulllen); |
5430 | } else { | 5434 | } else { |
diff --git a/shell/hush.c b/shell/hush.c index 2aeb8e440..78f0f7940 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -6944,7 +6944,7 @@ int hush_main(int argc, char **argv) | |||
6944 | /* -c 'script' (no params): prevent empty $0 */ | 6944 | /* -c 'script' (no params): prevent empty $0 */ |
6945 | G.global_argv--; /* points to argv[i] of 'script' */ | 6945 | G.global_argv--; /* points to argv[i] of 'script' */ |
6946 | G.global_argv[0] = argv[0]; | 6946 | G.global_argv[0] = argv[0]; |
6947 | G.global_argc--; | 6947 | G.global_argc++; |
6948 | } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ | 6948 | } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */ |
6949 | init_sigmasks(); | 6949 | init_sigmasks(); |
6950 | parse_and_run_string(optarg); | 6950 | parse_and_run_string(optarg); |
diff --git a/testsuite/cpio.tests b/testsuite/cpio.tests index e53ade925..325664d71 100755 --- a/testsuite/cpio.tests +++ b/testsuite/cpio.tests | |||
@@ -32,7 +32,7 @@ rm -rf cpio.testdir cpio.testdir2 2>/dev/null | |||
32 | # testing "test name" "command" "expected result" "file input" "stdin" | 32 | # testing "test name" "command" "expected result" "file input" "stdin" |
33 | 33 | ||
34 | testing "cpio extracts zero-sized hardlinks" \ | 34 | testing "cpio extracts zero-sized hardlinks" \ |
35 | "$ECHO -ne '$hexdump' | bzcat | cpio -i; echo \$?; | 35 | "$ECHO -ne '$hexdump' | bzcat | cpio -i 2>&1; echo \$?; |
36 | ls -ln cpio.testdir | $FILTER_LS" \ | 36 | ls -ln cpio.testdir | $FILTER_LS" \ |
37 | "\ | 37 | "\ |
38 | 1 blocks | 38 | 1 blocks |
@@ -45,7 +45,7 @@ ls -ln cpio.testdir | $FILTER_LS" \ | |||
45 | 45 | ||
46 | test x"$SKIP_KNOWN_BUGS" = x"" && { | 46 | test x"$SKIP_KNOWN_BUGS" = x"" && { |
47 | # Currently fails. Numerous buglets: "1 blocks" versus "1 block", | 47 | # Currently fails. Numerous buglets: "1 blocks" versus "1 block", |
48 | # "1 block" must go to stderr, does not list cpio.testdir/x and cpio.testdir/y | 48 | # does not list cpio.testdir/x and cpio.testdir/y |
49 | testing "cpio lists hardlinks" \ | 49 | testing "cpio lists hardlinks" \ |
50 | "$ECHO -ne '$hexdump' | bzcat | cpio -t 2>&1; echo \$?" \ | 50 | "$ECHO -ne '$hexdump' | bzcat | cpio -t 2>&1; echo \$?" \ |
51 | "\ | 51 | "\ |
@@ -70,7 +70,7 @@ ln cpio.testdir/nonempty cpio.testdir/nonempty1 | |||
70 | mkdir cpio.testdir2 | 70 | mkdir cpio.testdir2 |
71 | 71 | ||
72 | testing "cpio extracts zero-sized hardlinks 2" \ | 72 | testing "cpio extracts zero-sized hardlinks 2" \ |
73 | "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i); echo \$?; | 73 | "find cpio.testdir | cpio -H newc --create | (cd cpio.testdir2 && cpio -i 2>&1); echo \$?; |
74 | ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ | 74 | ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ |
75 | "\ | 75 | "\ |
76 | 2 blocks | 76 | 2 blocks |
@@ -87,7 +87,7 @@ ls -ln cpio.testdir2/cpio.testdir | $FILTER_LS" \ | |||
87 | # Was trying to create "/usr/bin", correct is "usr/bin". | 87 | # Was trying to create "/usr/bin", correct is "usr/bin". |
88 | rm -rf cpio.testdir | 88 | rm -rf cpio.testdir |
89 | testing "cpio -p with absolute paths" \ | 89 | testing "cpio -p with absolute paths" \ |
90 | "echo /usr/bin | cpio -dp cpio.testdir; echo \$?; | 90 | "echo /usr/bin | cpio -dp cpio.testdir 2>&1; echo \$?; |
91 | ls cpio.testdir" \ | 91 | ls cpio.testdir" \ |
92 | "\ | 92 | "\ |
93 | 1 blocks | 93 | 1 blocks |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 875c946be..5b0750cac 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -248,4 +248,28 @@ testing "sed beginning (^) matches only once" \ | |||
248 | ">/usr</>lib<\n" "" \ | 248 | ">/usr</>lib<\n" "" \ |
249 | "/usr/lib\n" | 249 | "/usr/lib\n" |
250 | 250 | ||
251 | testing "sed c" \ | ||
252 | "sed 'crepl'" \ | ||
253 | "repl\nrepl\n" "" \ | ||
254 | "first\nsecond\n" | ||
255 | |||
256 | testing "sed nested {}s" \ | ||
257 | "sed '/asd/ { p; /s/ { s/s/c/ }; p; q }'" \ | ||
258 | "qwe\nasd\nacd\nacd\n" "" \ | ||
259 | "qwe\nasd\nzxc\n" | ||
260 | |||
261 | testing "sed a cmd ended by double backslash" \ | ||
262 | "sed -e '/| one /a \\ | ||
263 | | three \\\\' -e '/| one-/a \\ | ||
264 | | three-* \\\\'" \ | ||
265 | ' | one \\ | ||
266 | | three \\ | ||
267 | | two \\ | ||
268 | ' '' \ | ||
269 | ' | one \\ | ||
270 | | two \\ | ||
271 | ' | ||
272 | |||
273 | # testing "description" "arguments" "result" "infile" "stdin" | ||
274 | |||
251 | exit $FAILCOUNT | 275 | exit $FAILCOUNT |
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index b8300570e..416271b31 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c | |||
@@ -109,10 +109,53 @@ static void to_sys_clock(const char **pp_rtcname, int utc) | |||
109 | 109 | ||
110 | static void from_sys_clock(const char **pp_rtcname, int utc) | 110 | static void from_sys_clock(const char **pp_rtcname, int utc) |
111 | { | 111 | { |
112 | #define TWEAK_USEC 200 | 112 | #if 1 |
113 | struct tm tm_time; | ||
114 | struct timeval tv; | 113 | struct timeval tv; |
114 | struct tm tm_time; | ||
115 | int rtc; | ||
116 | |||
117 | rtc = rtc_xopen(pp_rtcname, O_WRONLY); | ||
118 | gettimeofday(&tv, NULL); | ||
119 | /* Prepare tm_time */ | ||
120 | if (sizeof(time_t) == sizeof(tv.tv_sec)) { | ||
121 | if (utc) | ||
122 | gmtime_r((time_t*)&tv.tv_sec, &tm_time); | ||
123 | else | ||
124 | localtime_r((time_t*)&tv.tv_sec, &tm_time); | ||
125 | } else { | ||
126 | time_t t = tv.tv_sec; | ||
127 | if (utc) | ||
128 | gmtime_r(&t, &tm_time); | ||
129 | else | ||
130 | localtime_r(&t, &tm_time); | ||
131 | } | ||
132 | #else | ||
133 | /* Bloated code which tries to set hw clock with better precision. | ||
134 | * On x86, even though code does set hw clock within <1ms of exact | ||
135 | * whole seconds, apparently hw clock (at least on some machines) | ||
136 | * doesn't reset internal fractional seconds to 0, | ||
137 | * making all this a pointless excercise. | ||
138 | */ | ||
139 | /* If we see that we are N usec away from whole second, | ||
140 | * we'll sleep for N-ADJ usecs. ADJ corrects for the fact | ||
141 | * that CPU is not infinitely fast. | ||
142 | * On infinitely fast CPU, next wakeup would be | ||
143 | * on (exactly_next_whole_second - ADJ). On real CPUs, | ||
144 | * this difference between current time and whole second | ||
145 | * is less than ADJ (assuming system isn't heavily loaded). | ||
146 | */ | ||
147 | /* Small value of 256us gives very precise sync for 2+ GHz CPUs. | ||
148 | * Slower CPUs will fail to sync and will go to bigger | ||
149 | * ADJ values. qemu-emulated armv4tl with ~100 MHz | ||
150 | * performance ends up using ADJ ~= 4*1024 and it takes | ||
151 | * 2+ secs (2 tries with successively larger ADJ) | ||
152 | * to sync. Even straced one on the same qemu (very slow) | ||
153 | * takes only 4 tries. | ||
154 | */ | ||
155 | #define TWEAK_USEC 256 | ||
115 | unsigned adj = TWEAK_USEC; | 156 | unsigned adj = TWEAK_USEC; |
157 | struct tm tm_time; | ||
158 | struct timeval tv; | ||
116 | int rtc = rtc_xopen(pp_rtcname, O_WRONLY); | 159 | int rtc = rtc_xopen(pp_rtcname, O_WRONLY); |
117 | 160 | ||
118 | /* Try to catch the moment when whole second is close */ | 161 | /* Try to catch the moment when whole second is close */ |
@@ -124,55 +167,64 @@ static void from_sys_clock(const char **pp_rtcname, int utc) | |||
124 | 167 | ||
125 | t = tv.tv_sec; | 168 | t = tv.tv_sec; |
126 | rem_usec = 1000000 - tv.tv_usec; | 169 | rem_usec = 1000000 - tv.tv_usec; |
127 | if (rem_usec < 1024) { | 170 | if (rem_usec < adj) { |
128 | /* Less than 1ms to next second. Good enough */ | 171 | /* Close enough */ |
129 | small_rem: | 172 | small_rem: |
130 | t++; | 173 | t++; |
131 | } | 174 | } |
132 | 175 | ||
133 | /* Prepare tm */ | 176 | /* Prepare tm_time from t */ |
134 | if (utc) | 177 | if (utc) |
135 | gmtime_r(&t, &tm_time); /* may read /etc/xxx (it takes time) */ | 178 | gmtime_r(&t, &tm_time); /* may read /etc/xxx (it takes time) */ |
136 | else | 179 | else |
137 | localtime_r(&t, &tm_time); /* same */ | 180 | localtime_r(&t, &tm_time); /* same */ |
138 | tm_time.tm_isdst = 0; | 181 | |
182 | if (adj >= 32*1024) { | ||
183 | break; /* 32 ms diff and still no luck?? give up trying to sync */ | ||
184 | } | ||
139 | 185 | ||
140 | /* gmtime/localtime took some time, re-get cur time */ | 186 | /* gmtime/localtime took some time, re-get cur time */ |
141 | gettimeofday(&tv, NULL); | 187 | gettimeofday(&tv, NULL); |
142 | 188 | ||
143 | if (tv.tv_sec < t /* may happen if rem_usec was < 1024 */ | 189 | if (tv.tv_sec < t /* we are still in old second */ |
144 | || (tv.tv_sec == t && tv.tv_usec < 1024) | 190 | || (tv.tv_sec == t && tv.tv_usec < adj) /* not too far into next second */ |
145 | ) { | 191 | ) { |
146 | /* We are not too far into next second. Good. */ | 192 | break; /* good, we are in sync! */ |
147 | break; | ||
148 | } | ||
149 | adj += 32; /* 2^(10-5) = 2^5 = 32 iterations max */ | ||
150 | if (adj >= 1024) { | ||
151 | /* Give up trying to sync */ | ||
152 | break; | ||
153 | } | 193 | } |
154 | 194 | ||
155 | /* Try to sync up by sleeping */ | ||
156 | rem_usec = 1000000 - tv.tv_usec; | 195 | rem_usec = 1000000 - tv.tv_usec; |
157 | if (rem_usec < 1024) { | 196 | if (rem_usec < adj) { |
158 | goto small_rem; /* already close, don't sleep */ | 197 | t = tv.tv_sec; |
198 | goto small_rem; /* already close to next sec, don't sleep */ | ||
159 | } | 199 | } |
160 | /* Need to sleep. | ||
161 | * Note that small adj on slow processors can make us | ||
162 | * to always overshoot tv.tv_usec < 1024 check on next | ||
163 | * iteration. That's why adj is increased on each iteration. | ||
164 | * This also allows it to be reused as a loop limiter. | ||
165 | */ | ||
166 | usleep(rem_usec - adj); | ||
167 | } | ||
168 | 200 | ||
169 | xioctl(rtc, RTC_SET_TIME, &tm_time); | 201 | /* Try to sync up by sleeping */ |
202 | usleep(rem_usec - adj); | ||
170 | 203 | ||
171 | /* Debug aid to find "good" TWEAK_USEC. | 204 | /* Jump to 1ms diff, then increase fast (x2): EVERY loop |
205 | * takes ~1 sec, people won't like slowly converging code here! | ||
206 | */ | ||
207 | //bb_error_msg("adj:%d tv.tv_usec:%d", adj, (int)tv.tv_usec); | ||
208 | if (adj < 512) | ||
209 | adj = 512; | ||
210 | /* ... and if last "overshoot" does not look insanely big, | ||
211 | * just use it as adj increment. This makes convergence faster. | ||
212 | */ | ||
213 | if (tv.tv_usec < adj * 8) { | ||
214 | adj += tv.tv_usec; | ||
215 | continue; | ||
216 | } | ||
217 | adj *= 2; | ||
218 | } | ||
219 | /* Debug aid to find "optimal" TWEAK_USEC with nearly exact sync. | ||
172 | * Look for a value which makes tv_usec close to 999999 or 0. | 220 | * Look for a value which makes tv_usec close to 999999 or 0. |
173 | * for 2.20GHz Intel Core 2: TWEAK_USEC ~= 200 | 221 | * For 2.20GHz Intel Core 2: optimal TWEAK_USEC ~= 200 |
174 | */ | 222 | */ |
175 | //bb_error_msg("tv.tv_usec:%d adj:%d", (int)tv.tv_usec, adj); | 223 | //bb_error_msg("tv.tv_usec:%d", (int)tv.tv_usec); |
224 | #endif | ||
225 | |||
226 | tm_time.tm_isdst = 0; | ||
227 | xioctl(rtc, RTC_SET_TIME, &tm_time); | ||
176 | 228 | ||
177 | if (ENABLE_FEATURE_CLEAN_UP) | 229 | if (ENABLE_FEATURE_CLEAN_UP) |
178 | close(rtc); | 230 | close(rtc); |