Use the google spinlock code instead of the built-in windows code.

The main benefit for perftools is that google spinlocks allow for
link-time (static) initialization, which we had to simulate before,
yielding bugs and worse performance.


git-svn-id: http://gperftools.googlecode.com/svn/trunk@73 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
This commit is contained in:
csilvers 2009-05-18 22:50:20 +00:00
parent ad03b009ef
commit 104bf697fb
12 changed files with 295 additions and 26 deletions

View File

@ -37,6 +37,9 @@
#ifndef BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
#define BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
#include <stdio.h>
#include <stdlib.h>
#include "base/basictypes.h" // For COMPILE_ASSERT
typedef int32 Atomic32;
@ -257,9 +260,6 @@ inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
// TBD(vchen): The GNU assembly below must be converted to MSVC inline
// assembly.
#include <stdio.h>
#include <stdlib.h>
inline void NotImplementedFatalError(const char *function_name) {
fprintf(stderr, "64-bit %s() not implemented on this platform\n",
function_name);

View File

@ -33,7 +33,9 @@
#include <config.h>
#include <time.h> /* For nanosleep() */
#ifdef HAVE_SCHED_H
#include <sched.h> /* For sched_yield() */
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* For nanosleep() on Windows, read() */
#endif
@ -78,9 +80,13 @@ void SpinLock::SlowLock() {
c--;
}
#ifdef HAVE_SCHED_H
if (lockword_ == 1) {
sched_yield(); // Spinning failed. Let's try to be gentle.
}
#else
sleep(0); // best we can do? Useful on windows at least.
#endif
while (Acquire_CompareAndSwap(&lockword_, 0, 1) != 0) {
// This code was adapted from the ptmalloc2 implementation of

View File

@ -67,7 +67,9 @@ class LOCKABLE SpinLock {
}
// Acquire this SpinLock.
inline void Lock() EXCLUSIVE_LOCK_FUNCTION() {
// TODO(csilvers): uncomment the annotation when we figure out how to
// support this macro with 0 args (see thread_annotations.h)
inline void Lock() /*EXCLUSIVE_LOCK_FUNCTION()*/ {
if (Acquire_CompareAndSwap(&lockword_, 0, 1) != 0) {
SlowLock();
}
@ -87,7 +89,9 @@ class LOCKABLE SpinLock {
}
// Release this SpinLock, which must be held by the calling thread.
inline void Unlock() UNLOCK_FUNCTION() {
// TODO(csilvers): uncomment the annotation when we figure out how to
// support this macro with 0 args (see thread_annotations.h)
inline void Unlock() /*UNLOCK_FUNCTION()*/ {
// This is defined in mutex.cc.
extern void SubmitSpinLockProfileData(const void *, int64);
@ -144,7 +148,9 @@ class SCOPED_LOCKABLE SpinLockHolder {
: lock_(l) {
l->Lock();
}
inline ~SpinLockHolder() UNLOCK_FUNCTION() { lock_->Unlock(); }
// TODO(csilvers): uncomment the annotation when we figure out how to
// support this macro with 0 args (see thread_annotations.h)
inline ~SpinLockHolder() /*UNLOCK_FUNCTION()*/ { lock_->Unlock(); }
};
// Catch bug where variable name is omitted, e.g. SpinLockHolder (&lock);
#define SpinLockHolder(x) COMPILE_ASSERT(0, spin_lock_decl_missing_var_name)

View File

@ -19,15 +19,6 @@
*/
#undef WIN32_OVERRIDE_ALLOCATORS
/* the location of <hash_map> */
#define HASH_MAP_H <hash_map>
/* the namespace of hash_map/hash_set */
#define HASH_NAMESPACE stdext
/* the location of <hash_set> */
#define HASH_SET_H <hash_set>
/* Define to 1 if your libc has a snprintf implementation */
#undef HAVE_SNPRINTF
@ -85,12 +76,6 @@
/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H
/* define if the compiler has hash_map */
#define HAVE_HASH_MAP 1
/* define if the compiler has hash_set */
#define HAVE_HASH_SET 1
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H

View File

@ -76,6 +76,7 @@
#include <malloc.h> // for _msize and _expand
#include <tlhelp32.h> // for CreateToolhelp32Snapshot()
#include <base/logging.h>
#include "base/spinlock.h"
#include "google/malloc_hook.h"
#include "malloc_hook-inl.h"
#include "preamble_patcher.h"

View File

@ -42,6 +42,7 @@
#include <windows.h>
#include "port.h"
#include "base/logging.h"
#include "base/spinlock.h"
#include "system-alloc.h"
// -----------------------------------------------------------------------

View File

@ -111,7 +111,7 @@ inline void* perftools_pthread_getspecific(DWORD key) {
}
#define perftools_pthread_setspecific(key, val) \
TlsSetValue((key), (val))
// NOTE: this is Win98 and later. For Win95 we could use a CRITICAL_SECTION...
// NOTE: this is Win2K and later. For Win98 we could use a CRITICAL_SECTION...
#define perftools_pthread_once(once, init) do { \
if (InterlockedCompareExchange(once, 1, 0) == 0) (init)(); \
} while (0)
@ -122,11 +122,16 @@ inline void* perftools_pthread_getspecific(DWORD key) {
// things we need to do before main()! So this kind of TLS is safe for us.
#define __thread __declspec(thread)
// This code is obsolete, but I keep it around in case we are ever in
// an environment where we can't or don't want to use google spinlocks
// (from base/spinlock.{h,cc}). In that case, uncommenting this out,
// and removing spinlock.cc from the build, should be enough to revert
// back to using native spinlocks.
#if 0
// Windows uses a spinlock internally for its mutexes, making our life easy!
// However, the Windows spinlock must always be initialized, making life hard,
// since we want LINKER_INITIALIZED. We work around this by having the
// linker initialize a bool to 0, and check that before accessing the mutex.
// TODO(csilvers): figure out a faster way.
// This replaces spinlock.{h,cc}, and all the stuff it depends on (atomicops)
#ifdef __cplusplus
class SpinLock {
@ -134,7 +139,10 @@ class SpinLock {
SpinLock() : initialize_token_(PTHREAD_ONCE_INIT) {}
// Used for global SpinLock vars (see base/spinlock.h for more details).
enum StaticInitializer { LINKER_INITIALIZED };
explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {}
explicit SpinLock(StaticInitializer) : initialize_token_(PTHREAD_ONCE_INIT) {
perftools_pthread_once(&initialize_token_, InitializeMutex);
}
// It's important SpinLock not have a destructor: otherwise we run
// into problems when the main thread has exited, but other threads
// are still running and try to access a main-thread spinlock. This
@ -144,6 +152,15 @@ class SpinLock {
// perfectly fine. But be aware of this for the future!
void Lock() {
// You'd thionk this would be unnecessary, since we call
// InitializeMutex() in our constructor. But sometimes Lock() can
// be called before our constructor is! This can only happen in
// global constructors, when this is a global. If we live in
// bar.cc, and some global constructor in foo.cc calls a routine
// in bar.cc that calls this->Lock(), then Lock() may well run
// before our global constructor does. To protect against that,
// we do this check. For SpinLock objects created after main()
// has started, this pthread_once call will always be a noop.
perftools_pthread_once(&initialize_token_, InitializeMutex);
EnterCriticalSection(&mutex_);
}
@ -172,7 +189,12 @@ class SpinLockHolder { // Acquires a spinlock for as long as the scope lasts
inline explicit SpinLockHolder(SpinLock* l) : lock_(l) { l->Lock(); }
inline ~SpinLockHolder() { lock_->Unlock(); }
};
#endif
#endif // #ifdef __cplusplus
// This keeps us from using base/spinlock.h's implementation of SpinLock.
#define BASE_SPINLOCK_H_ 1
#endif // #if 0
// This replaces testutil.{h,cc}
extern PERFTOOLS_DLL_DECL void RunInThread(void (*fn)());
@ -264,6 +286,14 @@ extern PERFTOOLS_DLL_DECL int getpagesize(); // in port.cc
#define random rand
#define sleep(t) Sleep(t * 1000)
struct timespec {
int tv_sec;
int tv_nsec;
};
#define nanosleep(tm_ptr, ignored) \
Sleep((tm_ptr)->tv_sec * 1000 + (tm_ptr)->tv_nsec / 1000000)
#ifndef __MINGW32__
#define strtoq _strtoi64
#define strtouq _strtoui64
@ -284,7 +314,6 @@ extern PERFTOOLS_DLL_DECL void PatchWindowsFunctions();
// windows/port.h defines compatibility APIs for several .h files, which
// we therefore shouldn't be #including directly. This hack keeps us from
// doing so. TODO(csilvers): do something more principled.
#define BASE_SPINLOCK_H_ 1
#define GOOGLE_MAYBE_THREADS_H_ 1

View File

@ -129,6 +129,40 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\dynamic_annotations.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\logging.cc">
<FileConfiguration
@ -146,6 +180,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\windows\port.cc">
<FileConfiguration
@ -186,6 +237,21 @@
<File
RelativePath="..\..\src\base\logging.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\cycleclock.h">
</File>
<File
RelativePath="..\..\src\base\dynamic_annotations.h">
</File>
<File
RelativePath="..\..\src\windows\port.h">
</File>

View File

@ -539,6 +539,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
@ -620,6 +637,15 @@
<File
RelativePath="..\..\src\base\low_level_alloc.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\google\malloc_extension.h">
</File>

View File

@ -129,6 +129,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\logging.cc">
<FileConfiguration
@ -163,6 +180,23 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\tests\low_level_alloc_unittest.cc">
<FileConfiguration
@ -259,12 +293,27 @@
<File
RelativePath="..\..\src\base\commandlineflags.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\windows\config.h">
</File>
<File
RelativePath="..\..\src\config_for_unittests.h">
</File>
<File
RelativePath="..\..\src\base\cycleclock.h">
</File>
<File
RelativePath="..\..\src\base\dynamic_annotations.h">
</File>
<File
RelativePath="..\..\src\base\logging.h">
</File>

View File

@ -129,6 +129,57 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\dynamic_annotations.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\tests\packed-cache_test.cc">
<FileConfiguration
@ -177,6 +228,27 @@
<File
RelativePath="..\..\src\base\logging.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\base\cycleclock.h">
</File>
<File
RelativePath="..\..\src\base\basictypes.h">
</File>
<File
RelativePath="..\..\src\base\commandlineflags.h">
</File>
<File
RelativePath="..\..\src\base\dynamic_annotations.h">
</File>
<File
RelativePath="..\..\src\packed-cache-inl.h">
</File>

View File

@ -583,6 +583,25 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\spinlock.cc">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D PERFTOOLS_DLL_DECL="
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D PERFTOOLS_DLL_DECL="
AdditionalIncludeDirectories="..\..\src\windows;..\..\src"
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\base\sysinfo.cc">
<FileConfiguration
@ -709,6 +728,15 @@
<File
RelativePath="..\..\src\base\low_level_alloc.h">
</File>
<File
RelativePath="..\..\src\base\spinlock.h">
</File>
<File
RelativePath="..\..\src\base\atomicops.h">
</File>
<File
RelativePath="..\..\src\base\atomicops-internals-x86-msvc.h">
</File>
<File
RelativePath="..\..\src\google\malloc_extension.h">
</File>