tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: memcpy of struct buf, or similar?



Chris Gilbert wrote:
> Attached is a slightly revised patch, to get rid of the changes to
> whitespace and sleeptab_lookup being moved.
> 
> I also added the KASSERT back to the cv_unsleep, as the lwp lock should
> be held at that point, and the lwp lock will be set to the sleepq lock,
> so it's safe to look at the sleepq.
> 
> Note there is an assumption that cv_has_waiters will be called with the
> mutex used to access the cv held, and so locking the sleepq lock will
> make sure we get a consistent state.

I've now checked that patch in, as it fixes the issue.

I've also produced that attached patch, which brings back cv_waiters.
However, I'm not seeing any performance gain with it using build.sh,
perhaps a specific benchmark would show a gain.  In theory there should
be some gain as we don't have to lock the sleepq if it's empty, but it's
probably lost in the noise of build.sh

Thanks,
Chris
Index: kern/kern_condvar.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_condvar.c,v
retrieving revision 1.23
diff -u -p -r1.23 kern_condvar.c
--- kern/kern_condvar.c 15 Jun 2008 09:56:18 -0000      1.23
+++ kern/kern_condvar.c 15 Jun 2008 13:40:34 -0000
@@ -96,6 +96,7 @@ cv_init(kcondvar_t *cv, const char *wmes
        KASSERT(wmesg != NULL);
        cv->cv_wmesg = wmesg;
        sleepq_init(CV_SLEEPQ(cv));
+       cv->cv_waiters = 0;
 }
 
 /*
@@ -111,6 +112,7 @@ cv_destroy(kcondvar_t *cv)
 #ifdef DIAGNOSTIC
        KASSERT(cv_is_valid(cv));
        cv->cv_wmesg = deadcv;
+       cv->cv_waiters = -3;
 #endif
 }
 
@@ -131,6 +133,7 @@ cv_enter(kcondvar_t *cv, kmutex_t *mtx, 
 
        LOCKDEBUG_LOCKED(CV_DEBUG_P(cv), cv, mtx, CV_RA, 0);
 
+       cv->cv_waiters++;
        l->l_kpriority = true;
        (void)sleeptab_lookup(&sleeptab, cv, &mp);
        sq = CV_SLEEPQ(cv);
@@ -278,8 +281,8 @@ cv_signal(kcondvar_t *cv)
 
        /* LOCKDEBUG_WAKEUP(CV_DEBUG_P(cv), cv, CV_RA); */
        KASSERT(cv_is_valid(cv));
-
-       cv_wakeup_one(cv);
+       if (__predict_false(cv->cv_waiters > 0))
+               cv_wakeup_one(cv);
 }
 
 static void __noinline
@@ -292,6 +295,8 @@ cv_wakeup_one(kcondvar_t *cv)
 
        KASSERT(cv_is_valid(cv));
 
+       cv->cv_waiters--;
+
        sq = CV_SLEEPQ(cv);
        (void)sleeptab_lookup(&sleeptab, cv, &mp);
        l = TAILQ_FIRST(sq);
@@ -328,7 +333,8 @@ cv_broadcast(kcondvar_t *cv)
        /* LOCKDEBUG_WAKEUP(CV_DEBUG_P(cv), cv, CV_RA); */
        KASSERT(cv_is_valid(cv));
 
-       cv_wakeup_all(cv);
+       if (__predict_false(cv->cv_waiters > 0))
+               cv_wakeup_all(cv);
 }
 
 static void __noinline
@@ -341,6 +347,8 @@ cv_wakeup_all(kcondvar_t *cv)
 
        KASSERT(cv_is_valid(cv));
 
+       cv->cv_waiters = 0;
+
        sq = CV_SLEEPQ(cv);
        (void)sleeptab_lookup(&sleeptab, cv, &mp);
        swapin = 0;
@@ -387,18 +395,7 @@ cv_wakeup(kcondvar_t *cv)
 bool
 cv_has_waiters(kcondvar_t *cv)
 {
-       bool result;
-       kmutex_t *mp;
-       sleepq_t *sq;
-
-       sq = CV_SLEEPQ(cv);
-       (void)sleeptab_lookup(&sleeptab, cv, &mp);
-
-       /* we can only get a valid result with the sleepq locked */
-       result = !TAILQ_EMPTY(sq);
-
-       mutex_spin_exit(mp);
-       return result;
+       return (cv->cv_waiters > 0);
 }
 
 /*
@@ -411,5 +408,11 @@ bool
 cv_is_valid(kcondvar_t *cv)
 {
 
-       return cv->cv_wmesg != deadcv && cv->cv_wmesg != NULL;
+       if (cv->cv_wmesg == deadcv || cv->cv_wmesg == NULL)
+               return false;
+
+       if (cv->cv_waiters < 0)
+               return false;
+
+       return true;
 }
Index: sys/condvar.h
===================================================================
RCS file: /cvsroot/src/sys/sys/condvar.h,v
retrieving revision 1.10
diff -u -p -r1.10 condvar.h
--- sys/condvar.h       31 May 2008 13:36:25 -0000      1.10
+++ sys/condvar.h       15 Jun 2008 13:40:35 -0000
@@ -44,6 +44,7 @@
 typedef struct kcondvar {
        void            *cv_opaque[2];  /* sleep queue */
        const char      *cv_wmesg;      /* description for /bin/ps */
+       int             cv_waiters;     /* number of waiters */
 } kcondvar_t;
 
 #ifdef _KERNEL


Home | Main Index | Thread Index | Old Index