Author: imp
Date: Thu Feb 21 15:35:48 2013
New Revision: 247101
URL: http://svnweb.freebsd.org/changeset/base/247101

Log:
  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

Modified:
  head/sys/x86/isa/atrtc.c

Modified: head/sys/x86/isa/atrtc.c
==============================================================================
--- head/sys/x86/isa/atrtc.c    Thu Feb 21 15:26:26 2013        (r247100)
+++ head/sys/x86/isa/atrtc.c    Thu Feb 21 15:35:48 2013        (r247101)
@@ -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 times
                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 times
 #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));
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to