summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2017-05-25 10:01:44 -0700
committerGitHub <[email protected]>2017-05-25 10:01:44 -0700
commit2ded1c7eff76f9f53b179659f25f3868b6a354ec (patch)
tree6146f1345fca220a0539a9ec6dd13a205579f8a9
parent8f87971e1fd11e3bca034dff2cbc0e884381c350 (diff)
Fix cv_timedwait timeout
Perform the already past expiration time check before updating cvp->cv_mutex with the provided mutex. This check only depends on local state. Doing it first ensures that cvp->cv_mutex will not be updated in the timeout case or if it's ever called with an expire_time <= now. Reviewed-by: Tim Chase <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #616
-rw-r--r--module/spl/spl-condvar.c30
1 files changed, 12 insertions, 18 deletions
diff --git a/module/spl/spl-condvar.c b/module/spl/spl-condvar.c
index 479bbfd12..80c2ef090 100644
--- a/module/spl/spl-condvar.c
+++ b/module/spl/spl-condvar.c
@@ -166,22 +166,19 @@ __cv_timedwait_common(kcondvar_t *cvp, kmutex_t *mp, clock_t expire_time,
ASSERT(mp);
ASSERT(cvp->cv_magic == CV_MAGIC);
ASSERT(mutex_owned(mp));
- atomic_inc(&cvp->cv_refs);
+ /* XXX - Does not handle jiffie wrap properly */
+ time_left = expire_time - jiffies;
+ if (time_left <= 0)
+ return (-1);
+
+ atomic_inc(&cvp->cv_refs);
m = ACCESS_ONCE(cvp->cv_mutex);
if (!m)
m = xchg(&cvp->cv_mutex, mp);
/* Ensure the same mutex is used by all callers */
ASSERT(m == NULL || m == mp);
- /* XXX - Does not handle jiffie wrap properly */
- time_left = expire_time - jiffies;
- if (time_left <= 0) {
- /* XXX - doesn't reset cv_mutex */
- atomic_dec(&cvp->cv_refs);
- return (-1);
- }
-
prepare_to_wait_exclusive(&cvp->cv_event, &wait, state);
atomic_inc(&cvp->cv_waiters);
@@ -238,28 +235,25 @@ __cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t expire_time,
{
DEFINE_WAIT(wait);
kmutex_t *m;
- hrtime_t time_left, now;
+ hrtime_t time_left;
ktime_t ktime_left;
ASSERT(cvp);
ASSERT(mp);
ASSERT(cvp->cv_magic == CV_MAGIC);
ASSERT(mutex_owned(mp));
- atomic_inc(&cvp->cv_refs);
+ time_left = expire_time - gethrtime();
+ if (time_left <= 0)
+ return (-1);
+
+ atomic_inc(&cvp->cv_refs);
m = ACCESS_ONCE(cvp->cv_mutex);
if (!m)
m = xchg(&cvp->cv_mutex, mp);
/* Ensure the same mutex is used by all callers */
ASSERT(m == NULL || m == mp);
- now = gethrtime();
- time_left = expire_time - now;
- if (time_left <= 0) {
- atomic_dec(&cvp->cv_refs);
- return (-1);
- }
-
prepare_to_wait_exclusive(&cvp->cv_event, &wait, state);
atomic_inc(&cvp->cv_waiters);