diff options
author | Brian Behlendorf <[email protected]> | 2017-05-25 10:01:44 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2017-05-25 10:01:44 -0700 |
commit | 2ded1c7eff76f9f53b179659f25f3868b6a354ec (patch) | |
tree | 6146f1345fca220a0539a9ec6dd13a205579f8a9 | |
parent | 8f87971e1fd11e3bca034dff2cbc0e884381c350 (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.c | 30 |
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); |