Skip to content

Commit 8f2ac18

Browse files
committed
Make sure that currentPriority actually reads the max QoS in the active
task status instead of the Job priority which is not necessarily in sync Radar-Id: rdar://problem/86100376
1 parent 42dca84 commit 8f2ac18

File tree

3 files changed

+26
-10
lines changed

3 files changed

+26
-10
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,13 @@ size_t swift_task_getJobFlags(AsyncTask* task);
481481
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
482482
bool swift_task_isCancelled(AsyncTask* task);
483483

484+
/// Returns the current priority of the task which is >= base priority of the
485+
/// task. This function does not exist in the base ABI of this library and must
486+
/// be deployment limited
487+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
488+
JobPriority
489+
swift_task_currentPriority(AsyncTask *task);
490+
484491
/// Create and add an cancellation record to the task.
485492
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
486493
CancellationNotificationStatusRecord*

stdlib/public/Concurrency/Task.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ static void completeTaskWithClosure(SWIFT_ASYNC_CONTEXT AsyncContext *context,
413413
reinterpret_cast<char *>(context) - sizeof(AsyncContextPrefix));
414414

415415
swift_release((HeapObject *)asyncContextPrefix->closureContext);
416-
416+
417417
// Clean up the rest of the task.
418418
return completeTaskAndRelease(context, error);
419419
}
@@ -470,6 +470,13 @@ const void *AsyncTask::getResumeFunctionForLogging() {
470470
return reinterpret_cast<const void *>(ResumeTask);
471471
}
472472

473+
JobPriority swift::swift_task_currentPriority(AsyncTask *task)
474+
{
475+
// This is racey but this is to be used in an API is inherently racey anyways.
476+
auto oldStatus = task->_private().Status.load(std::memory_order_relaxed);
477+
return oldStatus.getStoredPriority();
478+
}
479+
473480
/// Implementation of task creation.
474481
SWIFT_CC(swift)
475482
static AsyncTaskAndContext swift_task_create_commonImpl(
@@ -520,7 +527,7 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
520527
// of in a FutureFragment.
521528
hasAsyncLetResultBuffer = true;
522529
assert(asyncLet && "Missing async let storage");
523-
530+
524531
jobFlags.task_setIsAsyncLetTask(true);
525532
jobFlags.task_setIsChildTask(true);
526533
break;
@@ -591,14 +598,14 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
591598
void *allocation = nullptr;
592599
if (asyncLet) {
593600
assert(parent);
594-
601+
595602
// If there isn't enough room in the fixed async let allocation to
596603
// set up the initial context, then we'll have to allocate more space
597604
// from the parent.
598605
if (asyncLet->getSizeOfPreallocatedSpace() < amountToAllocate) {
599606
hasAsyncLetResultBuffer = false;
600607
}
601-
608+
602609
// DEPRECATED. This is separated from the above condition because we
603610
// also have to handle an older async let ABI that did not provide
604611
// space for the initial slab in the compiler-generated preallocation.
@@ -678,7 +685,7 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
678685
auto groupChildFragment = task->groupChildFragment();
679686
new (groupChildFragment) AsyncTask::GroupChildFragment(group);
680687
}
681-
688+
682689
// Initialize the future fragment if applicable.
683690
if (futureResultType) {
684691
assert(task->isFuture());
@@ -940,7 +947,7 @@ static AsyncTask *swift_continuation_initImpl(ContinuationAsyncContext *context,
940947
// must happen-after this call.
941948
context->AwaitSynchronization.store(flags.isPreawaited()
942949
? ContinuationStatus::Awaited
943-
: ContinuationStatus::Pending,
950+
: ContinuationStatus::Pending,
944951
std::memory_order_relaxed);
945952

946953
AsyncTask *task;

stdlib/public/Concurrency/Task.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,8 @@ extension Task where Success == Never, Failure == Never {
289289
public static var currentPriority: TaskPriority {
290290
withUnsafeCurrentTask { task in
291291
// If we are running on behalf of a task, use that task's priority.
292-
if let task = task {
293-
return task.priority
292+
if let unsafeTask = task {
293+
return TaskPriority(rawValue: _taskCurrentPriority(unsafeTask._task))
294294
}
295295

296296
// Otherwise, query the system.
@@ -752,8 +752,7 @@ public struct UnsafeCurrentTask {
752752
/// - SeeAlso: `TaskPriority`
753753
/// - SeeAlso: `Task.currentPriority`
754754
public var priority: TaskPriority {
755-
getJobFlags(_task).priority ?? TaskPriority(
756-
rawValue: UInt8(_getCurrentThreadPriority()))
755+
TaskPriority(rawValue: _taskCurrentPriority(_task))
757756
}
758757

759758
/// Cancel the current task.
@@ -850,6 +849,9 @@ func _taskCancel(_ task: Builtin.NativeObject)
850849
@usableFromInline
851850
func _taskIsCancelled(_ task: Builtin.NativeObject) -> Bool
852851

852+
@_silgen_name("swift_task_currentPriority")
853+
internal func _taskCurrentPriority(_ task: Builtin.NativeObject) -> UInt8
854+
853855
@available(SwiftStdlib 5.1, *)
854856
@_silgen_name("swift_task_createNullaryContinuationJob")
855857
func _taskCreateNullaryContinuationJob(priority: Int, continuation: Builtin.RawUnsafeContinuation) -> Builtin.Job

0 commit comments

Comments
 (0)