| Index: src/IceTLS.h
|
| diff --git a/src/IceTLS.h b/src/IceTLS.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3fba80307e0a2414572e666e23d94a3796352519
|
| --- /dev/null
|
| +++ b/src/IceTLS.h
|
| @@ -0,0 +1,100 @@
|
| +//===- subzero/src/IceTLS.h - thread_local workaround -----------*- C++ -*-===//
|
| +//
|
| +// The Subzero Code Generator
|
| +//
|
| +// This file is distributed under the University of Illinois Open Source
|
| +// License. See LICENSE.TXT for details.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +//
|
| +// This file defines macros for working around the lack of support for
|
| +// thread_local in MacOS 10.6. It assumes std::thread is written in
|
| +// terms of pthread. Define ICE_THREAD_LOCAL_HACK to enable the
|
| +// pthread workarounds.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#ifndef SUBZERO_SRC_ICETLS_H
|
| +#define SUBZERO_SRC_ICETLS_H
|
| +
|
| +#if defined(_MSC_VER)
|
| +#define ICE_ATTRIBUTE_TLS __declspec(thread)
|
| +#else // !_MSC_VER
|
| +#define ICE_ATTRIBUTE_TLS thread_local
|
| +#endif // !_MSC_VER
|
| +
|
| +// Defines 4 macros for unifying thread_local and pthread:
|
| +//
|
| +// ICE_TLS_DECLARE_FIELD(Type, FieldName): Declare a static
|
| +// thread_local field inside the current class definition. "Type"
|
| +// needs to be a pointer type, such as int* or class Foo*.
|
| +//
|
| +// ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName): Define a static
|
| +// thread_local field outside of its class definition. The field will
|
| +// ultimately be initialized to nullptr.
|
| +//
|
| +// ICE_TLS_INIT_FIELD(FieldName): Ensure the thread_local field is
|
| +// properly initialized. This is intended to be called from within a
|
| +// static method of the field's class after main() starts (to ensure
|
| +// that the pthread library is fully initialized) but before any uses
|
| +// of ICE_TLS_GET_FIELD or ICE_TLS_SET_FIELD.
|
| +//
|
| +// ICE_TLS_GET_FIELD(Type, FieldName): Read the value of the static
|
| +// thread_local field. Must be done within the context of its class.
|
| +//
|
| +// ICE_TLS_SET_FIELD(FieldName, Value): Write a value into the static
|
| +// thread_local field. Must be done within the context of its class.
|
| +
|
| +// TODO(stichnot): Limit this define to only the platforms that
|
| +// absolutely require it. And ideally, eventually remove this hack
|
| +// altogether.
|
| +#define ICE_THREAD_LOCAL_HACK
|
| +#ifdef ICE_THREAD_LOCAL_HACK
|
| +
|
| +// For a static thread_local field F of a class C, instead of
|
| +// declaring and defining C::F, we create two static fields:
|
| +// static pthread_key_t F__key;
|
| +// static int F__initStatus;
|
| +//
|
| +// The F__initStatus field is used to hold the result of the
|
| +// pthread_key_create() call, where a zero value indicates success,
|
| +// and a nonzero value indicates failure or that ICE_TLS_INIT_FIELD()
|
| +// was never called.
|
| +// The F__key field is used as the argument to
|
| +// pthread_getspecific() and pthread_setspecific().
|
| +
|
| +#include <pthread.h>
|
| +
|
| +#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
|
| + typedef Type FieldName##__type; \
|
| + static pthread_key_t FieldName##__key; \
|
| + static int FieldName##__initStatus
|
| +#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
|
| + pthread_key_t ClassName::FieldName##__key; \
|
| + int ClassName::FieldName##__initStatus = 1;
|
| +#define ICE_TLS_INIT_FIELD(FieldName) \
|
| + if (FieldName##__initStatus) { \
|
| + FieldName##__initStatus = pthread_key_create(&FieldName##__key, nullptr); \
|
| + if (FieldName##__initStatus) \
|
| + llvm::report_fatal_error("Failed to create pthread key"); \
|
| + }
|
| +#define ICE_TLS_GET_FIELD(FieldName) \
|
| + (assert(FieldName##__initStatus == 0), \
|
| + static_cast<FieldName##__type>(pthread_getspecific(FieldName##__key)))
|
| +#define ICE_TLS_SET_FIELD(FieldName, Value) \
|
| + (assert(FieldName##__initStatus == 0), \
|
| + pthread_setspecific(FieldName##__key, (Value)))
|
| +
|
| +#else // !ICE_THREAD_LOCAL_HACK
|
| +
|
| +#define ICE_TLS_DECLARE_FIELD(Type, FieldName) \
|
| + static ICE_ATTRIBUTE_TLS Type FieldName
|
| +#define ICE_TLS_DEFINE_FIELD(Type, ClassName, FieldName) \
|
| + ICE_ATTRIBUTE_TLS Type ClassName::FieldName = nullptr
|
| +#define ICE_TLS_INIT_FIELD(FieldName)
|
| +#define ICE_TLS_GET_FIELD(FieldName) (FieldName)
|
| +#define ICE_TLS_SET_FIELD(FieldName, Value) (FieldName = (Value))
|
| +
|
| +#endif // !ICE_THREAD_LOCAL_HACK
|
| +
|
| +#endif // SUBZERO_SRC_ICETLS_H
|
|
|