Skip to content

Commit bbb018b

Browse files
authored
Merge pull request #38163 from mikeash/concurrency-constant-pthread-keys-5.5
[5.5][Concurrency] Use pthread_specific for thread-local storage on Darwin.
2 parents c2567ca + cd050f0 commit bbb018b

File tree

7 files changed

+100
-46
lines changed

7 files changed

+100
-46
lines changed

include/swift/Runtime/ThreadLocal.h

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@
1818
#ifndef SWIFT_RUNTIME_THREADLOCAL_H
1919
#define SWIFT_RUNTIME_THREADLOCAL_H
2020

21+
#include <type_traits>
22+
#include "ThreadLocalStorage.h"
23+
2124
/// SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL - Does the current configuration
2225
/// allow the use of SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL?
23-
#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
26+
#if defined(__APPLE__)
27+
// The pthread TLS APIs work better than C++ TLS on Apple platforms.
28+
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
29+
#elif defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
2430
// We define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL to nothing in this
2531
// configuration and just use a global variable, so this is okay.
2632
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
@@ -57,6 +63,17 @@
5763
#endif
5864

5965
namespace swift {
66+
// Validate a type stored in thread-local storage, using static asserts. Such
67+
// types must fit in a pointer and be trivially copyable/destructible.
68+
#define VALIDATE_THREAD_LOCAL_TYPE(T) \
69+
static_assert(sizeof(T) <= sizeof(void *), \
70+
"cannot store more than a pointer"); \
71+
static_assert(std::is_trivially_copyable<T>::value, \
72+
"ThreadLocal values must be trivially copyable"); \
73+
static_assert(std::is_trivially_destructible<T>::value, \
74+
"ThreadLocal cleanup is not supported, stored types must be " \
75+
"trivially destructible");
76+
6077
// A wrapper class for thread-local storage.
6178
//
6279
// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
@@ -72,50 +89,70 @@ namespace swift {
7289
// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL,
7390
// we have to simulate thread-local storage. Fortunately, all of
7491
// these platforms (at least for now) support pthread_getspecific.
92+
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
7593
template <class T>
7694
class ThreadLocal {
77-
static_assert(sizeof(T) <= sizeof(void*), "cannot store more than a pointer");
95+
VALIDATE_THREAD_LOCAL_TYPE(T)
7896

79-
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
8097
T value;
98+
99+
public:
100+
constexpr ThreadLocal() {}
101+
102+
T get() { return value; }
103+
104+
void set(T newValue) { value = newValue; }
105+
};
81106
#else
107+
// A wrapper around a pthread_key_t that is lazily initialized using
108+
// dispatch_once.
109+
class ThreadLocalKey {
82110
// We rely on the zero-initialization of objects with static storage
83111
// duration.
84112
dispatch_once_t once;
85113
pthread_key_t key;
86114

115+
public:
87116
pthread_key_t getKey() {
88-
dispatch_once_f(&once, this, [](void *ctx) {
89-
pthread_key_create(&reinterpret_cast<ThreadLocal*>(ctx)->key, nullptr);
117+
dispatch_once_f(&once, &key, [](void *ctx) {
118+
pthread_key_create(reinterpret_cast<pthread_key_t *>(ctx), nullptr);
90119
});
91120
return key;
92121
}
93-
#endif
122+
};
123+
124+
// A type representing a constant pthread_key_t, for use on platforms that
125+
// provide reserved keys.
126+
template <pthread_key_t constantKey>
127+
class ConstantThreadLocalKey {
128+
public:
129+
pthread_key_t getKey() { return constantKey; }
130+
};
131+
132+
template <class T, class Key>
133+
class ThreadLocal {
134+
VALIDATE_THREAD_LOCAL_TYPE(T)
135+
136+
Key key;
94137

95138
public:
96139
constexpr ThreadLocal() {}
97140

98141
T get() {
99-
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
100-
return value;
101-
#else
102-
void *storedValue = pthread_getspecific(getKey());
142+
void *storedValue = SWIFT_THREAD_GETSPECIFIC(key.getKey());
103143
T value;
104144
memcpy(&value, &storedValue, sizeof(T));
105145
return value;
106-
#endif
107146
}
108147

109148
void set(T newValue) {
110-
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
111-
value = newValue;
112-
#else
113149
void *storedValue;
114150
memcpy(&storedValue, &newValue, sizeof(T));
115-
pthread_setspecific(getKey(), storedValue);
116-
#endif
151+
SWIFT_THREAD_SETSPECIFIC(key.getKey(), storedValue);
117152
}
118153
};
154+
#endif
155+
119156
} // end namespace swift
120157

121158
/// SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) - Declare a variable
@@ -124,13 +161,16 @@ class ThreadLocal {
124161
///
125162
/// Because of the fallback path, the default-initialization of the
126163
/// type must be equivalent to a bitwise zero-initialization, and the
127-
/// type must be small and trivially copyable.
164+
/// type must be small and trivially copyable and destructible.
128165
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
129-
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) \
166+
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
130167
SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL swift::ThreadLocal<TYPE> NAME
168+
#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
169+
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
170+
swift::ThreadLocal<TYPE, ConstantThreadLocalKey<KEY>> NAME
131171
#else
132-
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) \
133-
swift::ThreadLocal<TYPE> NAME
172+
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
173+
swift::ThreadLocal<TYPE, ThreadLocalKey> NAME
134174
#endif
135175

136176
#endif

stdlib/public/runtime/ThreadLocalStorage.h renamed to include/swift/Runtime/ThreadLocalStorage.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,33 @@ extern "C" int pthread_key_init_np(int key, void (*destructor)(void *));
4848
# ifndef __PTK_FRAMEWORK_SWIFT_KEY3
4949
# define __PTK_FRAMEWORK_SWIFT_KEY3 103
5050
# endif
51+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY4
52+
# define __PTK_FRAMEWORK_SWIFT_KEY4 104
53+
# endif
54+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY5
55+
# define __PTK_FRAMEWORK_SWIFT_KEY5 105
56+
# endif
57+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY6
58+
# define __PTK_FRAMEWORK_SWIFT_KEY6 106
59+
# endif
60+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY7
61+
# define __PTK_FRAMEWORK_SWIFT_KEY7 107
62+
# endif
63+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY8
64+
# define __PTK_FRAMEWORK_SWIFT_KEY8 108
65+
# endif
66+
# ifndef __PTK_FRAMEWORK_SWIFT_KEY9
67+
# define __PTK_FRAMEWORK_SWIFT_KEY9 109
68+
# endif
5169

5270

5371
# define SWIFT_RUNTIME_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY0
5472
# define SWIFT_STDLIB_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY1
5573
# define SWIFT_COMPATIBILITY_50_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY2
5674
# define SWIFT_CONCURRENCY_TASK_KEY __PTK_FRAMEWORK_SWIFT_KEY3
75+
# define SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY __PTK_FRAMEWORK_SWIFT_KEY4
76+
# define SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY \
77+
__PTK_FRAMEWORK_SWIFT_KEY5
5778

5879
#endif
5980

stdlib/public/Concurrency/Actor.cpp

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@
2626
#endif
2727

2828
#include "../CompatibilityOverride/CompatibilityOverride.h"
29-
#include "../runtime/ThreadLocalStorage.h"
3029
#include "swift/Runtime/Atomic.h"
3130
#include "swift/Runtime/Casting.h"
3231
#include "swift/Runtime/Once.h"
3332
#include "swift/Runtime/Mutex.h"
3433
#include "swift/Runtime/ThreadLocal.h"
34+
#include "swift/Runtime/ThreadLocalStorage.h"
3535
#include "swift/ABI/Task.h"
3636
#include "swift/ABI/Actor.h"
3737
#include "llvm/ADT/PointerIntPair.h"
@@ -111,8 +111,9 @@ class ExecutorTrackingInfo {
111111
/// the right executor. It would make sense for that to be a
112112
/// separate thread-local variable (or whatever is most efficient
113113
/// on the target platform).
114-
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer<ExecutorTrackingInfo>,
115-
ActiveInfoInThread);
114+
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
115+
Pointer<ExecutorTrackingInfo>, ActiveInfoInThread,
116+
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY);
116117

117118
/// The active executor.
118119
ExecutorRef ActiveExecutor = ExecutorRef::generic();
@@ -186,21 +187,11 @@ class ExecutorTrackingInfo {
186187
}
187188
};
188189

189-
#ifdef SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
190-
class ActiveTask {
191-
public:
192-
static void set(AsyncTask *task) {
193-
SWIFT_THREAD_SETSPECIFIC(SWIFT_CONCURRENCY_TASK_KEY, task);
194-
}
195-
static AsyncTask *get() {
196-
return (AsyncTask *)SWIFT_THREAD_GETSPECIFIC(SWIFT_CONCURRENCY_TASK_KEY);
197-
}
198-
};
199-
#else
200190
class ActiveTask {
201191
/// A thread-local variable pointing to the active tracking
202192
/// information about the current thread, if any.
203-
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer<AsyncTask>, Value);
193+
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer<AsyncTask>, Value,
194+
SWIFT_CONCURRENCY_TASK_KEY);
204195

205196
public:
206197
static void set(AsyncTask *task) { Value.set(task); }
@@ -210,11 +201,13 @@ class ActiveTask {
210201
/// Define the thread-locals.
211202
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
212203
Pointer<AsyncTask>,
213-
ActiveTask::Value);
214-
#endif
204+
ActiveTask::Value,
205+
SWIFT_CONCURRENCY_TASK_KEY);
206+
215207
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
216208
Pointer<ExecutorTrackingInfo>,
217-
ExecutorTrackingInfo::ActiveInfoInThread);
209+
ExecutorTrackingInfo::ActiveInfoInThread,
210+
SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY);
218211

219212
} // end anonymous namespace
220213

stdlib/public/Concurrency/TaskLocal.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "../CompatibilityOverride/CompatibilityOverride.h"
14-
#include "../runtime/ThreadLocalStorage.h"
1514
#include "swift/Runtime/Atomic.h"
1615
#include "swift/Runtime/Casting.h"
1716
#include "swift/Runtime/Once.h"
1817
#include "swift/Runtime/Mutex.h"
1918
#include "swift/Runtime/Concurrency.h"
2019
#include "swift/Runtime/ThreadLocal.h"
20+
#include "swift/Runtime/ThreadLocalStorage.h"
2121
#include "swift/ABI/TaskLocal.h"
2222
#include "swift/ABI/Task.h"
2323
#include "swift/ABI/Actor.h"
@@ -59,8 +59,8 @@ template <class T> struct Pointer {
5959
/// THIS IS RUNTIME INTERNAL AND NOT ABI.
6060
class FallbackTaskLocalStorage {
6161
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
62-
Pointer<TaskLocal::Storage>,
63-
Value);
62+
Pointer<TaskLocal::Storage>, Value,
63+
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY);
6464

6565
public:
6666
static void set(TaskLocal::Storage *task) { Value.set(task); }
@@ -69,8 +69,8 @@ class FallbackTaskLocalStorage {
6969

7070
/// Define the thread-locals.
7171
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
72-
Pointer<TaskLocal::Storage>,
73-
FallbackTaskLocalStorage::Value);
72+
Pointer<TaskLocal::Storage>, FallbackTaskLocalStorage::Value,
73+
SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY);
7474

7575
// ==== ABI --------------------------------------------------------------------
7676

stdlib/public/runtime/Exclusivity.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424

2525
#include "swift/Runtime/Exclusivity.h"
2626
#include "../SwiftShims/Visibility.h"
27-
#include "ThreadLocalStorage.h"
2827
#include "swift/Basic/Lazy.h"
2928
#include "swift/Runtime/Config.h"
3029
#include "swift/Runtime/Debug.h"
3130
#include "swift/Runtime/Metadata.h"
31+
#include "swift/Runtime/ThreadLocalStorage.h"
3232
#include <memory>
3333
#include <inttypes.h>
3434
#include <stdio.h>

stdlib/public/stubs/ThreadLocalStorage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
#include <cstring>
1414

1515
#include "../SwiftShims/ThreadLocalStorage.h"
16-
#include "../runtime/ThreadLocalStorage.h"
1716
#include "swift/Basic/Lazy.h"
1817
#include "swift/Runtime/Debug.h"
18+
#include "swift/Runtime/ThreadLocalStorage.h"
1919

2020
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
2121
void _stdlib_destroyTLS(void *);

stdlib/toolchain/CompatibilityDynamicReplacements/DynamicReplaceable.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
#include "swift/Runtime/Once.h"
2121
#include "swift/Runtime/Exclusivity.h"
22-
#include "../../public/runtime/ThreadLocalStorage.h"
22+
#include "swift/Runtime/ThreadLocalStorage.h"
2323

2424
using namespace swift;
2525

0 commit comments

Comments
 (0)