1// Copyright (c) 2005, 2006, Google Inc. 2// Copyright (c) 2010, Patrick Gansterer <paroga@paroga.com> 3// All rights reserved. 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31// --- 32// Author: Sanjay Ghemawat <opensource@google.com> 33 34#ifndef TCMALLOC_INTERNAL_SPINLOCK_H__ 35#define TCMALLOC_INTERNAL_SPINLOCK_H__ 36 37#include <wtf/Atomics.h> 38#if OS(UNIX) 39#include <sched.h> 40#endif 41 42#if ENABLE(COMPARE_AND_SWAP) 43 44static void TCMalloc_SlowLock(unsigned* lockword); 45 46// The following is a struct so that it can be initialized at compile time 47struct TCMalloc_SpinLock { 48 void Lock() { 49 if (!WTF::weakCompareAndSwap(&lockword_, 0, 1)) 50 TCMalloc_SlowLock(&lockword_); 51 WTF::memoryBarrierAfterLock(); 52 } 53 54 void Unlock() { 55 WTF::memoryBarrierBeforeUnlock(); 56 lockword_ = 0; 57 } 58 59 // Report if we think the lock can be held by this thread. 60 // When the lock is truly held by the invoking thread 61 // we will always return true. 62 // Indended to be used as CHECK(lock.IsHeld()); 63 bool IsHeld() const { 64 return lockword_ != 0; 65 } 66 67 void Init() { lockword_ = 0; } 68 void Finalize() { } 69 70 unsigned lockword_; 71}; 72 73#define SPINLOCK_INITIALIZER { 0 } 74 75static void TCMalloc_SlowLock(unsigned* lockword) { 76 do { 77#if OS(WINDOWS) 78 Sleep(0); 79#else 80 sched_yield(); 81#endif 82 } while (!WTF::weakCompareAndSwap(lockword, 0, 1)); 83} 84 85#else 86 87#include <pthread.h> 88 89// Portable version 90struct TCMalloc_SpinLock { 91 pthread_mutex_t private_lock_; 92 93 inline void Init() { 94 if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH(); 95 } 96 inline void Finalize() { 97 if (pthread_mutex_destroy(&private_lock_) != 0) CRASH(); 98 } 99 inline void Lock() { 100 if (pthread_mutex_lock(&private_lock_) != 0) CRASH(); 101 } 102 inline void Unlock() { 103 if (pthread_mutex_unlock(&private_lock_) != 0) CRASH(); 104 } 105 bool IsHeld() { 106 if (pthread_mutex_trylock(&private_lock_)) 107 return true; 108 109 Unlock(); 110 return false; 111 } 112}; 113 114#define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } 115 116#endif 117 118// Corresponding locker object that arranges to acquire a spinlock for 119// the duration of a C++ scope. 120class TCMalloc_SpinLockHolder { 121 private: 122 TCMalloc_SpinLock* lock_; 123 public: 124 inline explicit TCMalloc_SpinLockHolder(TCMalloc_SpinLock* l) 125 : lock_(l) { l->Lock(); } 126 inline ~TCMalloc_SpinLockHolder() { lock_->Unlock(); } 127}; 128 129// Short-hands for convenient use by tcmalloc.cc 130typedef TCMalloc_SpinLock SpinLock; 131typedef TCMalloc_SpinLockHolder SpinLockHolder; 132 133#endif // TCMALLOC_INTERNAL_SPINLOCK_H__ 134