diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2014-05-02 09:05:03 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2014-05-02 09:05:03 +0200 |
commit | 528808fa7b0778931fb624e95c38cf8cbc2fff90 (patch) | |
tree | d66730c8a6cdbff37c69bd88a511bb486ed55d71 | |
parent | fe33683c8bad841a1b5e947fcc6a502b85ca53cf (diff) | |
download | busybox-w32-528808fa7b0778931fb624e95c38cf8cbc2fff90.tar.gz busybox-w32-528808fa7b0778931fb624e95c38cf8cbc2fff90.tar.bz2 busybox-w32-528808fa7b0778931fb624e95c38cf8cbc2fff90.zip |
libbb: make rtc_xopen try harder on EBUSY
function old new delta
rtc_xopen 77 139 +62
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | libbb/rtc.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/libbb/rtc.c b/libbb/rtc.c index 97455e86a..f84da09bb 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c | |||
@@ -33,23 +33,55 @@ int FAST_FUNC rtc_adjtime_is_utc(void) | |||
33 | return utc; | 33 | return utc; |
34 | } | 34 | } |
35 | 35 | ||
36 | /* rtc opens are exclusive. | ||
37 | * Try to run two "hwclock -w" at the same time to see it. | ||
38 | * Users wouldn't expect that to fail merely because /dev/rtc | ||
39 | * was momentarily busy, let's try a bit harder on errno == EBUSY. | ||
40 | */ | ||
41 | static int open_loop_on_busy(const char *name, int flags) | ||
42 | { | ||
43 | int rtc; | ||
44 | /* | ||
45 | * Tested with two parallel "hwclock -w" loops. | ||
46 | * With try = 10, no failures with 2x1000000 loop iterations. | ||
47 | */ | ||
48 | int try = 1000 / 20; | ||
49 | again: | ||
50 | errno = 0; | ||
51 | rtc = open(name, flags); | ||
52 | if (errno == EBUSY) { | ||
53 | usleep(20 * 1000); | ||
54 | if (--try != 0) | ||
55 | goto again; | ||
56 | /* EBUSY. Last try, exit on error instead of returning -1 */ | ||
57 | return xopen(name, flags); | ||
58 | } | ||
59 | return rtc; | ||
60 | } | ||
61 | |||
62 | /* Never fails */ | ||
36 | int FAST_FUNC rtc_xopen(const char **default_rtc, int flags) | 63 | int FAST_FUNC rtc_xopen(const char **default_rtc, int flags) |
37 | { | 64 | { |
38 | int rtc; | 65 | int rtc; |
66 | const char *name = | ||
67 | "/dev/rtc""\0" | ||
68 | "/dev/rtc0""\0" | ||
69 | "/dev/misc/rtc""\0"; | ||
39 | 70 | ||
40 | if (!*default_rtc) { | 71 | if (!*default_rtc) |
41 | *default_rtc = "/dev/rtc"; | 72 | goto try_name; |
42 | rtc = open(*default_rtc, flags); | 73 | name = ""; /*else: we have rtc name, don't try other names */ |
43 | if (rtc >= 0) | 74 | |
44 | return rtc; | 75 | for (;;) { |
45 | *default_rtc = "/dev/rtc0"; | 76 | rtc = open_loop_on_busy(*default_rtc, flags); |
46 | rtc = open(*default_rtc, flags); | ||
47 | if (rtc >= 0) | 77 | if (rtc >= 0) |
48 | return rtc; | 78 | return rtc; |
49 | *default_rtc = "/dev/misc/rtc"; | 79 | name += strlen(name) + 1; |
80 | if (!name[0]) | ||
81 | return xopen(*default_rtc, flags); | ||
82 | try_name: | ||
83 | *default_rtc = name; | ||
50 | } | 84 | } |
51 | |||
52 | return xopen(*default_rtc, flags); | ||
53 | } | 85 | } |
54 | 86 | ||
55 | void FAST_FUNC rtc_read_tm(struct tm *ptm, int fd) | 87 | void FAST_FUNC rtc_read_tm(struct tm *ptm, int fd) |