Skip to content

Commit 60fb31c

Browse files
committed
[Concurrency][32-bit] Store timestamp out-of-line on 32-bit.
CooperativeExecutor needs to store its timestamp out-of-line for 32-bit architectures (like WASI). rdar://141348916
1 parent 4576d53 commit 60fb31c

File tree

1 file changed

+61
-5
lines changed

1 file changed

+61
-5
lines changed

stdlib/public/Concurrency/CooperativeExecutor.swift

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,77 @@
1212

1313
import Swift
1414

15+
// Store the Timestamp in the executor private data, if it will fit; otherwise,
16+
// use the allocator to allocate space for it and stash a pointer in the private
17+
// data area.
1518
@available(SwiftStdlib 6.2, *)
1619
extension ExecutorJob {
17-
fileprivate var cooperativeExecutorTimestamp: CooperativeExecutor.Timestamp {
20+
fileprivate var cooperativeExecutorTimestampIsIndirect: Bool {
21+
return MemoryLayout<(Int, Int)>.size
22+
< MemoryLayout<CooperativeExecutor.Timestamp>.size
23+
}
24+
25+
fileprivate var cooperativeExecutorTimestampPointer: UnsafeMutablePointer<CooperativeExecutor.Timestamp> {
1826
get {
27+
assert(cooperativeExecutorTimestampIsIndirect)
1928
return unsafe withUnsafeExecutorPrivateData {
20-
return unsafe $0.assumingMemoryBound(
21-
to: CooperativeExecutor.Timestamp.self
22-
)[0]
29+
unsafe $0.withMemoryRebound(to: UnsafeMutablePointer<CooperativeExecutor.Timestamp>.self) {
30+
return unsafe $0[0]
31+
}
2332
}
2433
}
2534
set {
35+
assert(cooperativeExecutorTimestampIsIndirect)
2636
unsafe withUnsafeExecutorPrivateData {
27-
unsafe $0.withMemoryRebound(to: CooperativeExecutor.Timestamp.self) {
37+
unsafe $0.withMemoryRebound(to: UnsafeMutablePointer<CooperativeExecutor.Timestamp>.self) {
2838
unsafe $0[0] = newValue
2939
}
3040
}
3141
}
3242
}
43+
44+
fileprivate var cooperativeExecutorTimestamp: CooperativeExecutor.Timestamp {
45+
get {
46+
if cooperativeExecutorTimestampIsIndirect {
47+
let ptr = unsafe cooperativeExecutorTimestampPointer
48+
return unsafe ptr.pointee
49+
} else {
50+
return unsafe withUnsafeExecutorPrivateData {
51+
return unsafe $0.assumingMemoryBound(
52+
to: CooperativeExecutor.Timestamp.self
53+
)[0]
54+
}
55+
}
56+
}
57+
set {
58+
if cooperativeExecutorTimestampIsIndirect {
59+
let ptr = unsafe cooperativeExecutorTimestampPointer
60+
unsafe ptr.pointee = newValue
61+
} else {
62+
unsafe withUnsafeExecutorPrivateData {
63+
unsafe $0.withMemoryRebound(to: CooperativeExecutor.Timestamp.self) {
64+
unsafe $0[0] = newValue
65+
}
66+
}
67+
}
68+
}
69+
}
70+
71+
fileprivate mutating func setupCooperativeExecutorTimestamp() {
72+
// If a Timestamp won't fit, allocate
73+
if cooperativeExecutorTimestampIsIndirect {
74+
let ptr = unsafe allocator!.allocate(as: CooperativeExecutor.Timestamp.self)
75+
unsafe self.cooperativeExecutorTimestampPointer = ptr
76+
}
77+
}
78+
79+
fileprivate mutating func clearCooperativeExecutorTimestamp() {
80+
// If a Timestamp won't fit, deallocate
81+
if cooperativeExecutorTimestampIsIndirect {
82+
let ptr = unsafe self.cooperativeExecutorTimestampPointer
83+
unsafe allocator!.deallocate(ptr)
84+
}
85+
}
3386
}
3487

3588
/// A co-operative executor that can be used as the main executor or as a
@@ -131,6 +184,7 @@ extension CooperativeExecutor: SchedulableExecutor {
131184
let duration = Duration(from: clock.convert(from: delay)!)
132185
let deadline = self.currentTime + duration
133186

187+
job.setupCooperativeExecutorTimestamp()
134188
job.cooperativeExecutorTimestamp = deadline
135189
waitQueue.push(UnownedJob(job))
136190
}
@@ -150,6 +204,8 @@ extension CooperativeExecutor: RunLoopExecutor {
150204
while let job = waitQueue.pop(when: {
151205
ExecutorJob($0).cooperativeExecutorTimestamp <= now
152206
}) {
207+
var theJob = ExecutorJob(job)
208+
theJob.clearCooperativeExecutorTimestamp()
153209
runQueue.push(job)
154210
}
155211

0 commit comments

Comments
 (0)