Commit dbf7c3d2 authored by Francis Ma's avatar Francis Ma Committed by facebook-github-bot-0

Make folly::detail::CacheLocality portable on apple

Summary:
This is one of the series steps to port folly::future on ios. Apple doesn't support __thread. Adding a HashingThreadId as a fallback
on apple.

Reviewed By: nbronson

Differential Revision: D2832068

fb-gh-sync-id: c3389245f3c0bbd36de6260680f7ac6110b3206c
parent 94174b55
...@@ -223,7 +223,9 @@ namespace std { typedef ::max_align_t max_align_t; } ...@@ -223,7 +223,9 @@ namespace std { typedef ::max_align_t max_align_t; }
* the semantics are the same * the semantics are the same
* (but remember __thread has different semantics when using emutls (ex. apple)) * (but remember __thread has different semantics when using emutls (ex. apple))
*/ */
#if defined(_MSC_VER) #if defined(__APPLE__)
#undef FOLLY_TLS
#elif defined(_MSC_VER)
# define FOLLY_TLS __declspec(thread) # define FOLLY_TLS __declspec(thread)
#elif defined(__GNUC__) || defined(__clang__) #elif defined(__GNUC__) || defined(__clang__)
# define FOLLY_TLS __thread # define FOLLY_TLS __thread
......
...@@ -232,6 +232,7 @@ Getcpu::Func Getcpu::vdsoFunc() { ...@@ -232,6 +232,7 @@ Getcpu::Func Getcpu::vdsoFunc() {
return func; return func;
} }
#ifdef FOLLY_TLS
/////////////// SequentialThreadId /////////////// SequentialThreadId
template<> template<>
...@@ -239,6 +240,7 @@ std::atomic<size_t> SequentialThreadId<std::atomic>::prevId(0); ...@@ -239,6 +240,7 @@ std::atomic<size_t> SequentialThreadId<std::atomic>::prevId(0);
template<> template<>
FOLLY_TLS size_t SequentialThreadId<std::atomic>::currentId(0); FOLLY_TLS size_t SequentialThreadId<std::atomic>::currentId(0);
#endif
/////////////// AccessSpreader /////////////// AccessSpreader
...@@ -277,7 +279,7 @@ Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc(size_t numStripes) { ...@@ -277,7 +279,7 @@ Getcpu::Func AccessSpreader<std::atomic>::pickGetcpuFunc(size_t numStripes) {
return &degenerateGetcpu; return &degenerateGetcpu;
} else { } else {
auto best = Getcpu::vdsoFunc(); auto best = Getcpu::vdsoFunc();
return best ? best : &SequentialThreadId<std::atomic>::getcpu; return best ? best : &FallbackGetcpuType::getcpu;
} }
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include <folly/Hash.h>
#include <folly/Likely.h> #include <folly/Likely.h>
#include <folly/Portability.h> #include <folly/Portability.h>
...@@ -141,10 +142,7 @@ struct Getcpu { ...@@ -141,10 +142,7 @@ struct Getcpu {
static Func vdsoFunc(); static Func vdsoFunc();
}; };
/// A class that lazily binds a unique (for each implementation of Atom) #ifdef FOLLY_TLS
/// identifier to a thread. This is a fallback mechanism for the access
/// spreader if we are in testing (using DeterministicAtomic) or if
/// __vdso_getcpu can't be dynamically loaded
template <template<typename> class Atom> template <template<typename> class Atom>
struct SequentialThreadId { struct SequentialThreadId {
...@@ -157,11 +155,32 @@ struct SequentialThreadId { ...@@ -157,11 +155,32 @@ struct SequentialThreadId {
return rv; return rv;
} }
private:
static Atom<size_t> prevId;
static FOLLY_TLS size_t currentId;
};
#endif
struct HashingThreadId {
static size_t get() {
pthread_t pid = pthread_self();
uint64_t id = 0;
memcpy(&id, &pid, std::min(sizeof(pid), sizeof(id)));
return hash::twang_32from64(id);
}
};
/// A class that lazily binds a unique (for each implementation of Atom)
/// identifier to a thread. This is a fallback mechanism for the access
/// spreader if __vdso_getcpu can't be loaded
template <typename ThreadId>
struct FallbackGetcpu {
/// Fills the thread id into the cpu and node out params (if they /// Fills the thread id into the cpu and node out params (if they
/// are non-null). This method is intended to act like getcpu when a /// are non-null). This method is intended to act like getcpu when a
/// fast-enough form of getcpu isn't available or isn't desired /// fast-enough form of getcpu isn't available or isn't desired
static int getcpu(unsigned* cpu, unsigned* node, void* unused) { static int getcpu(unsigned* cpu, unsigned* node, void* unused) {
auto id = get(); auto id = ThreadId::get();
if (cpu) { if (cpu) {
*cpu = id; *cpu = id;
} }
...@@ -170,13 +189,14 @@ struct SequentialThreadId { ...@@ -170,13 +189,14 @@ struct SequentialThreadId {
} }
return 0; return 0;
} }
private:
static Atom<size_t> prevId;
static FOLLY_TLS size_t currentId;
}; };
#ifdef FOLLY_TLS
typedef FallbackGetcpu<SequentialThreadId<std::atomic>> FallbackGetcpuType;
#else
typedef FallbackGetcpu<HashingThreadId> FallbackGetcpuType;
#endif
template <template<typename> class Atom, size_t kMaxCpus> template <template<typename> class Atom, size_t kMaxCpus>
struct AccessSpreaderArray; struct AccessSpreaderArray;
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment