summaryrefslogtreecommitdiff
path: root/util/concurrency/spin_lock.cpp
diff options
context:
space:
mode:
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)) {