diff options
-rw-r--r-- | Makefile.ckati | 2 | ||||
-rw-r--r-- | stats.cc | 13 | ||||
-rw-r--r-- | thread_local.h | 91 |
3 files changed, 99 insertions, 7 deletions
diff --git a/Makefile.ckati b/Makefile.ckati index cd8a0f8..f35824b 100644 --- a/Makefile.ckati +++ b/Makefile.ckati @@ -71,7 +71,7 @@ KATI_CXXFLAGS += -O -DNOLOG #KATI_CXXFLAGS += -pg ifeq ($(shell uname),Linux) -KATI_LIBS := -lrt +KATI_LIBS := -lrt -lpthread endif # Rule to build ckati into KATI_BIN_PATH @@ -22,12 +22,13 @@ #include "flags.h" #include "log.h" #include "stringprintf.h" +#include "thread_local.h" #include "timeutil.h" namespace { vector<Stats*>* g_stats; -thread_local double g_start_time = 0.0; +DEFINE_THREAD_LOCAL(double, g_start_time); } // namespace @@ -44,16 +45,16 @@ string Stats::String() const { } void Stats::Start() { - CHECK(!g_start_time); - g_start_time = GetTime(); + CHECK(!g_start_time.Ref()); + g_start_time.Ref() = GetTime(); unique_lock<mutex> lock(mu_); cnt_++; } double Stats::End() { - CHECK(g_start_time); - double e = GetTime() - g_start_time; - g_start_time = 0; + CHECK(g_start_time.Ref()); + double e = GetTime() - g_start_time.Ref(); + g_start_time.Ref() = 0; unique_lock<mutex> lock(mu_); elapsed_ += e; return e; diff --git a/thread_local.h b/thread_local.h new file mode 100644 index 0000000..3bbf663 --- /dev/null +++ b/thread_local.h @@ -0,0 +1,91 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// A simple cross platform thread local storage implementation. +// +// This is a drop-in replacement of __thread keyword. If your compiler +// toolchain supports __thread keyword, the user of this code should +// be as fast as the code which uses __thread. Chrome's +// base::ThreadLocalPointer and base::ThreadLocalStorage cannot be as +// fast as __thread. +// TODO(crbug.com/249345): If pthread_getspecific is slow for our use, +// expose bionic's internal TLS and stop using pthread_getspecific +// based implementation. +// +// Usage: +// +// Before (linux): +// +// __thread Foo* foo; +// foo = new Foo(); +// foo->func(); +// +// +// After: +// +// DEFINE_THREAD_LOCAL(Foo*, foo); +// foo.Ref() = new Foo(); +// foo.Ref()->func(); +// +// Thread local PODs are zero-initialized. +// Thread local non-PODs are initialized with the default constructor. + +#ifndef THREAD_LOCAL_H_ +#define THREAD_LOCAL_H_ + +#include <errno.h> +#include <pthread.h> + +#include "log.h" + +// Thread local storage implementation which uses pthread. +// Note that DEFINE_THREAD_LOCAL creates a global variable just like +// thread local storage based on __thread keyword. So we should not use +// constructor in ThreadLocal class to avoid static initializator. +template <typename Type> +void ThreadLocalDestructor(void* ptr) { + delete reinterpret_cast<Type>(ptr); +} + +template<typename Type, pthread_key_t* key> +void ThreadLocalInit() { + if (pthread_key_create(key, ThreadLocalDestructor<Type>)) + ERROR("Failed to create a pthread key for TLS errno=%d", errno); +} + +template<typename Type, pthread_key_t* key, pthread_once_t* once> +class ThreadLocal { + public: + Type& Ref() { + return *GetPointer(); + } + Type Get() { + return Ref(); + } + void Set(const Type& value) { + Ref() = value; + } + Type* GetPointer() { + pthread_once(once, ThreadLocalInit<Type*, key>); + Type* value = reinterpret_cast<Type*>(pthread_getspecific(*key)); + if (value) return value; + // new Type() for PODs means zero initialization. + value = new Type(); + int error = pthread_setspecific(*key, value); + if (error != 0) + ERROR("Failed to set a TLS: error=%d", error); + return value; + } +}; + +// We need a namespace for name##_key and name##_once since template parameters +// do not accept unnamed values such as static global variables. +#define DEFINE_THREAD_LOCAL(Type, name) \ + namespace { \ + pthread_once_t name##_once = PTHREAD_ONCE_INIT; \ + pthread_key_t name##_key; \ + } \ + ThreadLocal<Type, &name##_key, &name##_once> name; + +#endif // THREAD_LOCAL_H_ |