[git commit] libbb: make rtc_xopen try harder on EBUSY

Denys Vlasenko vda.linux at googlemail.com
Fri May 2 07:05:03 UTC 2014


commit: http://git.busybox.net/busybox/commit/?id=528808fa7b0778931fb624e95c38cf8cbc2fff90
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
rtc_xopen                                             77     139     +62

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/rtc.c |   52 ++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/libbb/rtc.c b/libbb/rtc.c
index 97455e8..f84da09 100644
--- a/libbb/rtc.c
+++ b/libbb/rtc.c
@@ -33,23 +33,55 @@ int FAST_FUNC rtc_adjtime_is_utc(void)
 	return utc;
 }
 
+/* rtc opens are exclusive.
+ * Try to run two "hwclock -w" at the same time to see it.
+ * Users wouldn't expect that to fail merely because /dev/rtc
+ * was momentarily busy, let's try a bit harder on errno == EBUSY.
+ */
+static int open_loop_on_busy(const char *name, int flags)
+{
+	int rtc;
+	/*
+	 * Tested with two parallel "hwclock -w" loops.
+	 * With try = 10, no failures with 2x1000000 loop iterations.
+	 */
+	int try = 1000 / 20;
+ again:
+	errno = 0;
+	rtc = open(name, flags);
+	if (errno == EBUSY) {
+		usleep(20 * 1000);
+		if (--try != 0)
+			goto again;
+		/* EBUSY. Last try, exit on error instead of returning -1 */
+		return xopen(name, flags);
+	}
+	return rtc;
+}
+
+/* Never fails */
 int FAST_FUNC rtc_xopen(const char **default_rtc, int flags)
 {
 	int rtc;
+	const char *name =
+		"/dev/rtc""\0"
+		"/dev/rtc0""\0"
+		"/dev/misc/rtc""\0";
 
-	if (!*default_rtc) {
-		*default_rtc = "/dev/rtc";
-		rtc = open(*default_rtc, flags);
-		if (rtc >= 0)
-			return rtc;
-		*default_rtc = "/dev/rtc0";
-		rtc = open(*default_rtc, flags);
+	if (!*default_rtc)
+		goto try_name;
+	name = ""; /*else: we have rtc name, don't try other names */
+
+	for (;;) {
+		rtc = open_loop_on_busy(*default_rtc, flags);
 		if (rtc >= 0)
 			return rtc;
-		*default_rtc = "/dev/misc/rtc";
+		name += strlen(name) + 1;
+		if (!name[0])
+			return xopen(*default_rtc, flags);
+ try_name:
+		*default_rtc = name;
 	}
-
-	return xopen(*default_rtc, flags);
 }
 
 void FAST_FUNC rtc_read_tm(struct tm *ptm, int fd)


More information about the busybox-cvs mailing list