summaryrefslogtreecommitdiff
path: root/util/concurrency/spin_lock.cpp
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-12-15 10:02:19 +0100
committerAntonin Kral <a.kral@bobek.cz>2011-12-15 10:02:46 +0100
commit0b48f8ada2acb0de830b23f8cefc8e3fea28d915 (patch)
treef7c2811269b6b53199412be2dd5ec02eea15d55d /util/concurrency/spin_lock.cpp
parent85f1cd56145b90a32b7ccdc750000deeed54fe22 (diff)
parentf0d9a01bccdaeb466c12c92057914bbfef59526c (diff)
downloadmongodb-0b48f8ada2acb0de830b23f8cefc8e3fea28d915.tar.gz
Merge branch 'upstream/2.0.2'
Diffstat (limited to 'util/concurrency/spin_lock.cpp')
-rw-r--r--util/concurrency/spin_lock.cpp31
1 files changed, 30 insertions, 1 deletions
diff --git a/util/concurrency/spin_lock.cpp b/util/concurrency/spin_lock.cpp
index 1811f15..52bd218 100644
--- a/util/concurrency/spin_lock.cpp
+++ b/util/concurrency/spin_lock.cpp
@@ -45,7 +45,36 @@ namespace mongo {
#if defined(_WIN32)
EnterCriticalSection(&_cs);
#elif defined(__USE_XOPEN2K)
- pthread_spin_lock( &_lock );
+
+ /**
+ * this is designed to perform close to the default spin lock
+ * the reason for the mild insanity is to prevent horrible performance
+ * when contention spikes
+ * it allows spinlocks to be used in many more places
+ * which is good because even with this change they are about 8x faster on linux
+ */
+
+ if ( pthread_spin_trylock( &_lock ) == 0 )
+ return;
+
+ for ( int i=0; i<1000; i++ )
+ if ( pthread_spin_trylock( &_lock ) == 0 )
+ return;
+
+ for ( int i=0; i<1000; i++ ) {
+ if ( pthread_spin_trylock( &_lock ) == 0 )
+ return;
+ pthread_yield();
+ }
+
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = 5000000;
+
+ while ( pthread_spin_trylock( &_lock ) != 0 ) {
+ nanosleep(&t, NULL);
+ }
+
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
// fast path
if (!_locked && !__sync_lock_test_and_set(&_locked, true)) {