Skip to content

Commit

Permalink
Merge pull request #2670 from wiredtiger/wt-2566
Browse files Browse the repository at this point in the history
WT-2566 Lock/unlock operations should imply memory barriers.
(cherry picked from commit 05cfbc2)
  • Loading branch information
michaelcahill committed Apr 20, 2016
1 parent 7bcf6fc commit eaa7b5f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 11 deletions.
12 changes: 12 additions & 0 deletions src/include/mutex.i
Expand Up @@ -306,6 +306,12 @@ __wt_fair_lock(WT_SESSION_IMPL *session, WT_FAIR_LOCK *lock)
__wt_sleep(0, 10);
}

/*
* Applications depend on a barrier here so that operations holding the
* lock see consistent data.
*/
WT_READ_BARRIER();

return (0);
}

Expand All @@ -318,6 +324,12 @@ __wt_fair_unlock(WT_SESSION_IMPL *session, WT_FAIR_LOCK *lock)
{
WT_UNUSED(session);

/*
* Ensure that all updates made while the lock was held are visible to
* the next thread to acquire the lock.
*/
WT_WRITE_BARRIER();

/*
* We have exclusive access - the update does not need to be atomic.
*/
Expand Down
37 changes: 26 additions & 11 deletions src/support/mtx_rw.c
Expand Up @@ -183,6 +183,8 @@ __wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
session, WT_VERB_MUTEX, "rwlock: readlock %s", rwlock->name));
WT_STAT_FAST_CONN_INCR(session, rwlock_read);

WT_DIAGNOSTIC_YIELD;

l = &rwlock->rwlock;

/*
Expand Down Expand Up @@ -213,6 +215,12 @@ __wt_readlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
*/
++l->s.readers;

/*
* Applications depend on a barrier here so that operations holding the
* lock see consistent data.
*/
WT_READ_BARRIER();

return (0);
}

Expand Down Expand Up @@ -306,6 +314,12 @@ __wt_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
__wt_sleep(0, 10);
}

/*
* Applications depend on a barrier here so that operations holding the
* lock see consistent data.
*/
WT_READ_BARRIER();

return (0);
}

Expand All @@ -316,31 +330,32 @@ __wt_writelock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
int
__wt_writeunlock(WT_SESSION_IMPL *session, WT_RWLOCK *rwlock)
{
wt_rwlock_t *l, copy;
wt_rwlock_t *l, new;

WT_RET(__wt_verbose(
session, WT_VERB_MUTEX, "rwlock: writeunlock %s", rwlock->name));

/*
* Ensure that all updates made while the lock was held are visible to
* the next thread to acquire the lock.
*/
WT_WRITE_BARRIER();

l = &rwlock->rwlock;

copy = *l;
new = *l;

/*
* We're the only writer of the writers/readers fields, so the update
* does not need to be atomic; we have to update both values at the
* same time though, otherwise we'd potentially race with the thread
* next granted the lock.
*
* Use a memory barrier to ensure the compiler doesn't mess with these
* instructions and rework the code in a way that avoids the update as
* a unit.
*/
WT_BARRIER();

++copy.s.writers;
++copy.s.readers;
++new.s.writers;
++new.s.readers;
l->i.wr = new.i.wr;

l->i.wr = copy.i.wr;
WT_DIAGNOSTIC_YIELD;

return (0);
}
Expand Down

0 comments on commit eaa7b5f

Please sign in to comment.