kernel - Fix excessive kprintf()s during refcount_wait()
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 21 Feb 2013 07:01:20 +0000 (23:01 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 21 Feb 2013 07:01:20 +0000 (23:01 -0800)
* _refcount_wait() can do itself in with excessive kprintf()s
  on large multi-way machines, causing the machine to become
  unresponsive.

* Rewrite the code to use a ticks test and only kprintf()
  a warning when it takes more than 60 seconds.

* Used by vm_object_pip_wait().  Long I/O queues are possible.

sys/kern/kern_refcount.c

index ba0aeff..aad1a7e 100644 (file)
@@ -65,23 +65,22 @@ void
 _refcount_wait(volatile u_int *countp, const char *wstr)
 {
        u_int n;
-       int loops = 0;
-       int threshold = 5;
+       int base_ticks = ticks;
 
        for (;;) {
                n = *countp;
                cpu_ccfence();
                if (n == 0)
                        break;
-               if (loops > threshold) {
-                       kprintf("refcount_wait %s long wait\n", wstr);
-                       loops = 0;
+               if ((int)(ticks - base_ticks) >= hz*60 - 1) {
+                       kprintf("warning: refcount_wait %s: long wait\n",
+                               wstr);
+                       base_ticks = ticks;
                }
                KKASSERT(n != REFCNTF_WAITING); /* impossible state */
                tsleep_interlock(countp, 0);
                if (atomic_cmpset_int(countp, n, n | REFCNTF_WAITING))
                        tsleep(countp, PINTERLOCKED, wstr, hz*10);
-               loops++;
        }
 }