summaryrefslogtreecommitdiffstats
path: root/sys/x86
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2013-02-21 15:35:48 +0000
committerimp <imp@FreeBSD.org>2013-02-21 15:35:48 +0000
commit0e93b8cbe63f40b8199f451dd9059aa862ebe342 (patch)
tree713c1a971b39a76baeae926c0fe9ceb573f05157 /sys/x86
parent323dc265fee59e32efcba8259f0481a82dab15f6 (diff)
downloadFreeBSD-src-0e93b8cbe63f40b8199f451dd9059aa862ebe342.zip
FreeBSD-src-0e93b8cbe63f40b8199f451dd9059aa862ebe342.tar.gz
Use critical_enter/critical_exit around the time sensitive part of
this code to depessimize the worst case we've lived with silently and uneventfully for the past 12 years. Add a comment about a refinement for those needing more assurance of accuracy. Fix ddb's show rtc command deadlock potential when debugging rtc code by not taking the lock if we're in the debugger. If you need a thumb to count the number of people that have encountered this, I'd be surprised. Submitted by: bde
Diffstat (limited to 'sys/x86')
-rw-r--r--sys/x86/isa/atrtc.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/x86/isa/atrtc.c b/sys/x86/isa/atrtc.c
index b42beac..c6a6f8c 100644
--- a/sys/x86/isa/atrtc.c
+++ b/sys/x86/isa/atrtc.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/clock.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/proc.h>
@@ -52,8 +53,8 @@ __FBSDID("$FreeBSD$");
#include <machine/intr_machdep.h>
#include "clock_if.h"
-#define RTC_LOCK mtx_lock_spin(&clock_lock)
-#define RTC_UNLOCK mtx_unlock_spin(&clock_lock)
+#define RTC_LOCK do { if (!kdb_active) mtx_lock_spin(&clock_lock); } while (0)
+#define RTC_UNLOCK do { if (!kdb_active) mtx_unlock_spin(&clock_lock); } while (0)
int atrtcclock_disable = 0;
@@ -335,10 +336,16 @@ atrtc_gettime(device_t dev, struct timespec *ts)
return (EINVAL);
}
- /* wait for time update to complete */
- /* If RTCSA_TUP is zero, we have at least 244us before next update */
+ /*
+ * wait for time update to complete
+ * If RTCSA_TUP is zero, we have at least 244us before next update.
+ * This is fast enough on most hardware, but a refinement would be
+ * to make sure that no more than 240us pass after we start reading,
+ * and try again if so.
+ */
while (rtcin(RTC_STATUSA) & RTCSA_TUP)
continue;
+ critical_enter();
ct.nsec = 0;
ct.sec = readrtc(RTC_SEC);
ct.min = readrtc(RTC_MIN);
@@ -352,6 +359,7 @@ atrtc_gettime(device_t dev, struct timespec *ts)
#else
ct.year += 2000;
#endif
+ critical_exit();
/* Set dow = -1 because some clocks don't set it correctly. */
ct.dow = -1;
return (clock_ct_to_ts(&ct, ts));
OpenPOWER on IntegriCloud