Date: Tue, 26 Jan 2016 00:22:02 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r294755 - stable/10/sys/kern Message-ID: <201601260022.u0Q0M2AR094295@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Tue Jan 26 00:22:02 2016 New Revision: 294755 URL: https://svnweb.freebsd.org/changeset/base/294755 Log: MFC r293458: Prevent cv_waiters wraparound. Modified: stable/10/sys/kern/kern_condvar.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/kern/kern_condvar.c ============================================================================== --- stable/10/sys/kern/kern_condvar.c Mon Jan 25 23:04:40 2016 (r294754) +++ stable/10/sys/kern/kern_condvar.c Tue Jan 26 00:22:02 2016 (r294755) @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/limits.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/proc.h> @@ -47,6 +48,17 @@ __FBSDID("$FreeBSD$"); #endif /* + * A bound below which cv_waiters is valid. Once cv_waiters reaches this bound, + * cv_signal must manually check the wait queue for threads. + */ +#define CV_WAITERS_BOUND INT_MAX + +#define CV_WAITERS_INC(cvp) do { \ + if ((cvp)->cv_waiters < CV_WAITERS_BOUND) \ + (cvp)->cv_waiters++; \ +} while (0) + +/* * Common sanity checks for cv_wait* functions. */ #define CV_ASSERT(cvp, lock, td) do { \ @@ -122,7 +134,7 @@ _cv_wait(struct cv *cvp, struct lock_obj sleepq_lock(cvp); - cvp->cv_waiters++; + CV_WAITERS_INC(cvp); if (lock == &Giant.lock_object) mtx_assert(&Giant, MA_OWNED); DROP_GIANT(); @@ -184,7 +196,7 @@ _cv_wait_unlock(struct cv *cvp, struct l sleepq_lock(cvp); - cvp->cv_waiters++; + CV_WAITERS_INC(cvp); DROP_GIANT(); sleepq_add(cvp, lock, cvp->cv_description, SLEEPQ_CONDVAR, 0); @@ -240,7 +252,7 @@ _cv_wait_sig(struct cv *cvp, struct lock sleepq_lock(cvp); - cvp->cv_waiters++; + CV_WAITERS_INC(cvp); if (lock == &Giant.lock_object) mtx_assert(&Giant, MA_OWNED); DROP_GIANT(); @@ -307,7 +319,7 @@ _cv_timedwait_sbt(struct cv *cvp, struct sleepq_lock(cvp); - cvp->cv_waiters++; + CV_WAITERS_INC(cvp); if (lock == &Giant.lock_object) mtx_assert(&Giant, MA_OWNED); DROP_GIANT(); @@ -376,7 +388,7 @@ _cv_timedwait_sig_sbt(struct cv *cvp, st sleepq_lock(cvp); - cvp->cv_waiters++; + CV_WAITERS_INC(cvp); if (lock == &Giant.lock_object) mtx_assert(&Giant, MA_OWNED); DROP_GIANT(); @@ -422,8 +434,15 @@ cv_signal(struct cv *cvp) wakeup_swapper = 0; sleepq_lock(cvp); if (cvp->cv_waiters > 0) { - cvp->cv_waiters--; - wakeup_swapper = sleepq_signal(cvp, SLEEPQ_CONDVAR, 0, 0); + if (cvp->cv_waiters == CV_WAITERS_BOUND && + sleepq_lookup(cvp) == NULL) { + cvp->cv_waiters = 0; + } else { + if (cvp->cv_waiters < CV_WAITERS_BOUND) + cvp->cv_waiters--; + wakeup_swapper = sleepq_signal(cvp, SLEEPQ_CONDVAR, 0, + 0); + } } sleepq_release(cvp); if (wakeup_swapper)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601260022.u0Q0M2AR094295>