Skip to content

Commit 4ae44a5

Browse files
authored
Merge pull request #38714 from DougGregor/actor-scheduling-without-priorities-5.5
Actor scheduling without priorities 5.5
2 parents 18a849e + 9821ff0 commit 4ae44a5

File tree

8 files changed

+34
-33
lines changed

8 files changed

+34
-33
lines changed

stdlib/public/Concurrency/Actor.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,8 +1024,7 @@ static void wakeOverrides(ProcessOverrideJob *nextOverride,
10241024
nextOverride = cur->NextJob.getAsPreprocessedOverride();
10251025

10261026
if (hasAlreadyActivated ||
1027-
!targetPriority ||
1028-
cur->getPriority() != *targetPriority)
1027+
!targetPriority)
10291028
cur->wakeAndAbandon();
10301029
else
10311030
hasAlreadyActivated = cur->wakeAndActivate();
@@ -1187,8 +1186,7 @@ void DefaultActorImpl::giveUpThread(RunningJobInfo runner) {
11871186
}
11881187

11891188
bool hasMoreJobs = (bool) newState.FirstJob;
1190-
bool hasOverrideAtNewPriority =
1191-
(runner.Priority < oldState.Flags.getMaxPriority());
1189+
bool hasOverrideAtNewPriority = false;
11921190
bool hasActiveInlineJob = newState.Flags.hasActiveInlineJob();
11931191
bool needsNewProcessJob = hasMoreJobs && !hasOverrideAtNewPriority;
11941192

@@ -1287,8 +1285,7 @@ Job *DefaultActorImpl::claimNextJobOrGiveUp(bool actorIsOwned,
12871285

12881286
// If the actor is out of work, or its priority doesn't match our
12891287
// priority, don't try to take over the actor.
1290-
if (!oldState.FirstJob ||
1291-
oldState.Flags.getMaxPriority() != runner.Priority) {
1288+
if (!oldState.FirstJob) {
12921289

12931290
// The only change we need here is inline-runner bookkeeping.
12941291
if (!tryUpdateForInlineRunner())
@@ -1370,8 +1367,7 @@ Job *DefaultActorImpl::claimNextJobOrGiveUp(bool actorIsOwned,
13701367
// FIXME: should this be an exact match in priority instead of
13711368
// potentially running jobs with too high a priority?
13721369
Job *jobToRun;
1373-
if (oldState.Flags.getMaxPriority() <= runner.Priority &&
1374-
newFirstJob) {
1370+
if (newFirstJob) {
13751371
jobToRun = newFirstJob;
13761372
newState.FirstJob = getNextJobInQueue(newFirstJob);
13771373
newState.Flags.setStatus(Status::Running);
@@ -1614,7 +1610,7 @@ void DefaultActorImpl::enqueue(Job *job) {
16141610

16151611
// If we need an override job, create it (if necessary) and
16161612
// register it with the queue.
1617-
bool needsOverride = !wasIdle && newPriority != oldPriority;
1613+
bool needsOverride = false;
16181614
if (needsOverride) {
16191615
overrideJob.addToState(this, newState);
16201616
} else {

stdlib/public/Concurrency/Task.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -490,15 +490,18 @@ static AsyncTaskAndContext swift_task_create_commonImpl(
490490

491491
if (currentTask)
492492
jobFlags.setPriority(currentTask->getPriority());
493-
else
494-
// FIXME: Ideally, this should be setting priority based on
495-
// swift_task_getCurrentThreadPriority(). However, that creates
496-
// priority differences which lead to different kinds of hangs
497-
// Temporarily use Unspecified to work around that.
498-
// See also: PR #37939.
499-
jobFlags.setPriority(JobPriority::Unspecified);
493+
else if (taskCreateFlags.inheritContext())
494+
jobFlags.setPriority(swift_task_getCurrentThreadPriority());
500495
}
501496

497+
// Adjust user-interactive priorities down to user-initiated.
498+
if (jobFlags.getPriority() == JobPriority::UserInteractive)
499+
jobFlags.setPriority(JobPriority::UserInitiated);
500+
501+
// If there is still no job priority, use the default priority.
502+
if (jobFlags.getPriority() == JobPriority::Unspecified)
503+
jobFlags.setPriority(JobPriority::Default);
504+
502505
// Figure out the size of the header.
503506
size_t headerSize = sizeof(AsyncTask);
504507
if (parent) {

stdlib/public/Concurrency/Task.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ extension Task where Success == Never, Failure == Never {
284284
}
285285

286286
// Otherwise, query the system.
287-
return TaskPriority(rawValue: UInt8(0))
287+
return TaskPriority(rawValue: UInt8(_getCurrentThreadPriority()))
288288
}
289289
}
290290
}
@@ -659,11 +659,10 @@ extension Task where Success == Never, Failure == Never {
659659
/// As such,
660660
/// this method isn't necessarily a way to avoid resource starvation.
661661
public static func yield() async {
662-
let currentTask = Builtin.getCurrentAsyncTask()
663-
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
664-
665662
return await Builtin.withUnsafeContinuation { (continuation: Builtin.RawUnsafeContinuation) -> Void in
666-
let job = _taskCreateNullaryContinuationJob(priority: Int(priority.rawValue), continuation: continuation)
663+
let job = _taskCreateNullaryContinuationJob(
664+
priority: Int(Task.currentPriority.rawValue),
665+
continuation: continuation)
667666
_enqueueJobGlobal(job)
668667
}
669668
}
@@ -751,7 +750,8 @@ public struct UnsafeCurrentTask {
751750
/// - SeeAlso: `TaskPriority`
752751
/// - SeeAlso: `Task.currentPriority`
753752
public var priority: TaskPriority {
754-
getJobFlags(_task).priority ?? .unspecified
753+
getJobFlags(_task).priority ?? TaskPriority(
754+
rawValue: UInt8(_getCurrentThreadPriority()))
755755
}
756756

757757
/// Cancel the current task.

stdlib/public/Concurrency/TaskPrivate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class alignas(sizeof(void*) * 2) ActiveTaskStatus {
210210
ActiveTaskStatus withEscalatedPriority(JobPriority priority) const {
211211
assert(priority > getStoredPriority());
212212
return ActiveTaskStatus(Record,
213-
(Flags & PriorityMask)
213+
(Flags & ~PriorityMask)
214214
| IsEscalated | uintptr_t(priority));
215215
}
216216
ActiveTaskStatus withoutStoredPriorityEscalation() const {

stdlib/public/Concurrency/TaskSleep.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ extension Task where Success == Never, Failure == Never {
1919
///
2020
/// This function does _not_ block the underlying thread.
2121
public static func sleep(_ duration: UInt64) async {
22-
let currentTask = Builtin.getCurrentAsyncTask()
23-
let priority = getJobFlags(currentTask).priority ?? Task.currentPriority._downgradeUserInteractive
24-
2522
return await Builtin.withUnsafeContinuation { (continuation: Builtin.RawUnsafeContinuation) -> Void in
26-
let job = _taskCreateNullaryContinuationJob(priority: Int(priority.rawValue), continuation: continuation)
23+
let job = _taskCreateNullaryContinuationJob(
24+
priority: Int(Task.currentPriority.rawValue),
25+
continuation: continuation)
2726
_enqueueJobGlobalWithDelay(duration, job)
2827
}
2928
}

test/Concurrency/Runtime/actor_counters.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ actor Counter {
3636
}
3737
}
3838

39+
// Produce a random priority.
40+
nonisolated var randomPriority: TaskPriority? {
41+
let priorities: [TaskPriority?] = [ .background, .low, .medium, .high, nil ]
42+
return priorities.randomElement()!
43+
}
3944

4045
@available(SwiftStdlib 5.5, *)
4146
func worker(identity: Int, counters: [Counter], numIterations: Int) async {
@@ -59,8 +64,8 @@ func runTest(numCounters: Int, numWorkers: Int, numIterations: Int) async {
5964
var workers: [Task.Handle<Void, Error>] = []
6065
for i in 0..<numWorkers {
6166
workers.append(
62-
detach { [counters] in
63-
await Task.sleep(UInt64.random(in: 0..<100) * 1_000_000)
67+
Task.detached(priority: randomPriority) { [counters] in
68+
await try! Task.sleep(nanoseconds: UInt64.random(in: 0..<100) * 1_000_000)
6469
await worker(identity: i, counters: counters, numIterations: numIterations)
6570
}
6671
)

test/Concurrency/Runtime/async.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
// REQUIRES: rdar79670222
21
// RUN: %target-run-simple-swift(-Xfrontend -enable-experimental-concurrency %import-libdispatch)
32

43
// REQUIRES: executable_test
54
// REQUIRES: concurrency
65
// REQUIRES: libdispatch
76

8-
// rdar://76038845
97
// UNSUPPORTED: use_os_stdlib
108

119
import Dispatch

test/Concurrency/Runtime/async_task_priority_current.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Dispatch
1313
@available(SwiftStdlib 5.5, *)
1414
func test_detach() async {
1515
let a1 = Task.currentPriority
16-
print("a1: \(a1)") // CHECK: TaskPriority(rawValue: 0)
16+
print("a1: \(a1)") // CHECK: TaskPriority(rawValue: 21)
1717

1818
// Note: remember to detach using a higher priority, otherwise a lower one
1919
// might be escalated by the get() and we could see `default` in the detached
@@ -24,7 +24,7 @@ func test_detach() async {
2424
}.get()
2525

2626
let a3 = Task.currentPriority
27-
print("a3: \(a3)") // CHECK: a3: TaskPriority(rawValue: 0)
27+
print("a3: \(a3)") // CHECK: a3: TaskPriority(rawValue: 21)
2828
}
2929

3030
@available(SwiftStdlib 5.5, *)

0 commit comments

Comments
 (0)