Fix a livelock in the objcache blocking code. PCATCH was being improperly
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 14 Apr 2006 01:06:21 +0000 (01:06 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 14 Apr 2006 01:06:21 +0000 (01:06 +0000)
passed to tsleep.

Fix harmless but inefficient wakeups in the objcache code.  When a thread
blocks on the objcache it tsleep's on the depot.  When objects are returned
to the objcache a wakeup is performed on the depot.  However, objects can
be returned to the depot OR returned to the current cpu's cache.  When an
object is returned to the current cpu's cache, only wakeup threads blocked
on the depot originating from the current cpu, rather then all cpus.

Reported-by: Stefan Krueger <skrueger@meinberlikomm.de>
Also-thanks-to: Peter Holms filesystem and load testing suite (stress2).

sys/kern/kern_objcache.c

index def981a..2d88805 100644 (file)
@@ -29,7 +29,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/kern_objcache.c,v 1.4 2005/07/13 16:06:04 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_objcache.c,v 1.5 2006/04/14 01:06:21 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -343,7 +343,7 @@ retry:
        if ((ocflags & (M_WAITOK|M_NULLOK)) == M_WAITOK) {
                ++cpucache->waiting;
                ++depot->waiting;
-               tsleep(depot, PCATCH, "objcache_get", 0);
+               tsleep(depot, 0, "objcache_get", 0);
                --cpucache->waiting;
                --depot->waiting;
                lwkt_reltoken(&ilock);
@@ -428,7 +428,7 @@ retry:
        if (!MAGAZINE_FULL(loadedmag)) {
                loadedmag->objects[loadedmag->rounds++] = obj;
                if (cpucache->waiting)
-                       wakeup(&oc->depot[myclusterid]);
+                       wakeup_mycpu(&oc->depot[myclusterid]);
                crit_exit();
                return;
        }
@@ -441,7 +441,7 @@ retry:
                loadedmag = cpucache->loaded_magazine;
                loadedmag->objects[loadedmag->rounds++] = obj;
                if (cpucache->waiting)
-                       wakeup(&oc->depot[myclusterid]);
+                       wakeup_mycpu(&oc->depot[myclusterid]);
                crit_exit();
                return;
        }