emitTLSLoad doesn't work on OSX with emulated TLS
- Provide a TLS solution that works on OSX with __emutls_*
Esse commit está contido em:
@@ -17,6 +17,11 @@
|
||||
#define X64_UTIL_H_
|
||||
|
||||
#include "hphp/util/asm-x64.h"
|
||||
#ifndef USE_GCC_FAST_TLS
|
||||
#include <pthread.h>
|
||||
#include "hphp/runtime/vm/jit/abi-x64.h"
|
||||
#include "hphp/runtime/vm/jit/physreg.h"
|
||||
#endif
|
||||
#include "hphp/runtime/vm/jit/translator-inline.h"
|
||||
|
||||
namespace HPHP {
|
||||
@@ -29,6 +34,8 @@ translator_not_reached(X64Assembler &a) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_GCC_FAST_TLS
|
||||
|
||||
/*
|
||||
* TLS access: XXX we currently only support static-style TLS directly
|
||||
* linked off of FS.
|
||||
@@ -46,23 +53,32 @@ translator_not_reached(X64Assembler &a) {
|
||||
*
|
||||
* The virtual addresses of TLS data are not exposed to C/C++. To figure it
|
||||
* out, we take a datum's linear address, and subtract it from the linear
|
||||
* address where TLS starts. If you use the void* variant here, it's up to
|
||||
* the programmer to ensure that it really is a TLS address.
|
||||
* address where TLS starts.
|
||||
*/
|
||||
static inline void
|
||||
emitTLSLoad(X64Assembler& a, const void* datum, RegNumber reg) {
|
||||
uintptr_t virtualAddress = uintptr_t(datum) - tlsBase();
|
||||
a. fs();
|
||||
a. load_disp32_reg64(virtualAddress, reg);
|
||||
}
|
||||
|
||||
//TODO(2525714) Will not work without USE_GCC_FAST_TLS being defined
|
||||
template<typename T>
|
||||
static inline void
|
||||
emitTLSLoad(X64Assembler& a, const ThreadLocalNoCheck<T>& datum,
|
||||
RegNumber reg) {
|
||||
emitTLSLoad(a, &datum.m_node.m_p, reg);
|
||||
uintptr_t virtualAddress = uintptr_t(&datum.m_node.m_p) - tlsBase();
|
||||
a. fs();
|
||||
a. load_disp32_reg64(virtualAddress, reg);
|
||||
}
|
||||
|
||||
#else // USE_GCC_FAST_TLS
|
||||
|
||||
template<typename T>
|
||||
static inline void
|
||||
emitTLSLoad(X64Assembler& a, const ThreadLocalNoCheck<T>& datum,
|
||||
RegNumber reg) {
|
||||
PhysRegSaver(a, kGPCallerSaved); // we don't know for sure what's alive
|
||||
a. emitImmReg(&datum.m_key, argNumToRegName[0]);
|
||||
a. call((TCA)pthread_getspecific);
|
||||
if (reg != reg::rax) {
|
||||
a. mov_reg64_reg64(reg::rax, reg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_GCC_FAST_TLS
|
||||
|
||||
} }
|
||||
#endif
|
||||
|
||||
@@ -31,12 +31,22 @@ namespace HPHP {
|
||||
// Clang seems to have added this feature, or at the very least it is ignoring
|
||||
// __thread keyword and compiling anyway
|
||||
//
|
||||
// On OSX, gcc does emulate TLS but in a manner that invalidates assumptions
|
||||
// we have made about __thread and makes accessing thread-local variables in a
|
||||
// JIT-friendly fashion difficult (as the compiler is doing a lot of magic that
|
||||
// is not contractual or documented that we would need to duplicate in emitted
|
||||
// code) so for now we're not going to use it. One possibility if we really
|
||||
// want to do this is to generate functions that access variables of interest
|
||||
// in ThreadLocal* (all of them are NoCheck right now) and use the bytes of
|
||||
// gcc's compiled functions to find the values we would need to pass to
|
||||
// __emutls_get_address.
|
||||
//
|
||||
// icc 13.0.0 appears to support it as well but we end up with
|
||||
// assembler warnings of unknown importance about incorrect section
|
||||
// types
|
||||
|
||||
#if !defined(NO_TLS) && \
|
||||
((__llvm__ && __clang__) || \
|
||||
#if !defined(NO_TLS) && !defined(__APPLE__) && \
|
||||
((__llvm__ && __clang__) || \
|
||||
__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || \
|
||||
__INTEL_COMPILER)
|
||||
#define USE_GCC_FAST_TLS
|
||||
@@ -65,7 +75,7 @@ inline void ThreadLocalCreateKey(pthread_key_t *key, void (*del)(void*)) {
|
||||
|
||||
/**
|
||||
* A thread-local object is a "global" object within a thread. This is useful
|
||||
* for writing apartment-threaded code, where nothing is actullay shared
|
||||
* for writing apartment-threaded code, where nothing is actually shared
|
||||
* between different threads (hence no locking) but those variables are not
|
||||
* on stack in local scope. To use it, just do something like this,
|
||||
*
|
||||
@@ -426,7 +436,7 @@ public:
|
||||
return *getNoCheck();
|
||||
}
|
||||
|
||||
private:
|
||||
public:
|
||||
pthread_key_t m_key;
|
||||
};
|
||||
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário