mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Properly save and restore the current task in the runtime so that tasks
can be reentrantly executed. I don't think doing this is *actually a good idea*, but corrupting the runtime is an even worse idea, and the overhead here is very low.
This commit is contained in:
@@ -115,6 +115,15 @@ public:
|
|||||||
T get() { return value; }
|
T get() { return value; }
|
||||||
|
|
||||||
void set(T newValue) { value = newValue; }
|
void set(T newValue) { value = newValue; }
|
||||||
|
|
||||||
|
T swap(T newValue) {
|
||||||
|
// There's an implicit optimization here because we implicitly
|
||||||
|
// materialize the address of the thread-local once instead of
|
||||||
|
// separately for two calls to get and set.
|
||||||
|
auto curValue = get();
|
||||||
|
set(newValue);
|
||||||
|
return curValue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
// A wrapper around a TLS key that is lazily initialized using swift::once.
|
// A wrapper around a TLS key that is lazily initialized using swift::once.
|
||||||
@@ -168,6 +177,12 @@ public:
|
|||||||
memcpy(&storedValue, &newValue, sizeof(T));
|
memcpy(&storedValue, &newValue, sizeof(T));
|
||||||
tls_set(key.getKey(), storedValue);
|
tls_set(key.getKey(), storedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T swap(T newValue) {
|
||||||
|
auto curValue = get();
|
||||||
|
set(newValue);
|
||||||
|
return curValue;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -196,6 +196,9 @@ class ActiveTask {
|
|||||||
public:
|
public:
|
||||||
static void set(AsyncTask *task) { Value.set(task); }
|
static void set(AsyncTask *task) { Value.set(task); }
|
||||||
static AsyncTask *get() { return Value.get(); }
|
static AsyncTask *get() { return Value.get(); }
|
||||||
|
static AsyncTask *swap(AsyncTask *newTask) {
|
||||||
|
return Value.swap(newTask);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Define the thread-locals.
|
/// Define the thread-locals.
|
||||||
@@ -217,7 +220,7 @@ void swift::runJobInEstablishedExecutorContext(Job *job) {
|
|||||||
|
|
||||||
if (auto task = dyn_cast<AsyncTask>(job)) {
|
if (auto task = dyn_cast<AsyncTask>(job)) {
|
||||||
// Update the active task in the current thread.
|
// Update the active task in the current thread.
|
||||||
ActiveTask::set(task);
|
auto oldTask = ActiveTask::swap(task);
|
||||||
|
|
||||||
// Update the task status to say that it's running on the
|
// Update the task status to say that it's running on the
|
||||||
// current thread. If the task suspends somewhere, it should
|
// current thread. If the task suspends somewhere, it should
|
||||||
@@ -231,6 +234,7 @@ void swift::runJobInEstablishedExecutorContext(Job *job) {
|
|||||||
|
|
||||||
assert(ActiveTask::get() == nullptr &&
|
assert(ActiveTask::get() == nullptr &&
|
||||||
"active task wasn't cleared before suspending?");
|
"active task wasn't cleared before suspending?");
|
||||||
|
if (oldTask) ActiveTask::set(oldTask);
|
||||||
} else {
|
} else {
|
||||||
// There's no extra bookkeeping to do for simple jobs besides swapping in
|
// There's no extra bookkeeping to do for simple jobs besides swapping in
|
||||||
// the voucher.
|
// the voucher.
|
||||||
@@ -259,15 +263,11 @@ AsyncTask *swift::swift_task_getCurrent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AsyncTask *swift::_swift_task_clearCurrent() {
|
AsyncTask *swift::_swift_task_clearCurrent() {
|
||||||
auto task = ActiveTask::get();
|
return ActiveTask::swap(nullptr);
|
||||||
ActiveTask::set(nullptr);
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncTask *swift::_swift_task_setCurrent(AsyncTask *new_task) {
|
AsyncTask *swift::_swift_task_setCurrent(AsyncTask *new_task) {
|
||||||
auto task = ActiveTask::get();
|
return ActiveTask::swap(new_task);
|
||||||
ActiveTask::set(new_task);
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SWIFT_CC(swift)
|
SWIFT_CC(swift)
|
||||||
|
|||||||
Reference in New Issue
Block a user