Skip to content

Commit 92e6a98

Browse files
committed
Cache TID in TLS on Linux
1 parent 5b7e3d8 commit 92e6a98

File tree

5 files changed

+33
-17
lines changed

5 files changed

+33
-17
lines changed

stdlib/public/SwiftShims/swift/shims/SynchronizationShims.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#define SWIFT_FUTEX_WAITERS FUTEX_WAITERS
2525

2626
static inline __swift_uint32_t _swift_stdlib_gettid() {
27-
return syscall(SYS_gettid);
27+
static __thread tid = syscall(SYS_gettid);
28+
return tid;
2829
}
2930

3031
static inline __swift_bool _swift_stdlib_wait(__swift_uint32_t *lock) {

stdlib/public/Synchronization/Cell.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,11 @@ internal struct _Cell<Value: ~Copyable>: ~Copyable {
3030
init(_ initialValue: consuming Value) {
3131
Builtin.initialize(initialValue, rawAddress)
3232
}
33+
34+
@available(SwiftStdlib 6.0, *)
35+
@_alwaysEmitIntoClient
36+
@inlinable
37+
deinit {
38+
Builtin.destroy(Value.self, rawAddress)
39+
}
3340
}

stdlib/public/Synchronization/Mutex/LinuxImpl.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ internal struct _MutexHandle: ~Copyable {
4444
@available(SwiftStdlib 6.0, *)
4545
@usableFromInline
4646
borrowing func lock() {
47-
// TODO: Is it worth caching this value in TLS?
47+
// Note: This is being TLS cached.
4848
let selfId = _swift_stdlib_gettid()
4949

5050
// Note: We could probably merge this cas into a do/while style loop, but we
@@ -101,6 +101,8 @@ internal struct _MutexHandle: ~Copyable {
101101
borrowing func tryLock() -> Bool {
102102
storage.compareExchange(
103103
expected: 0,
104+
105+
// Note: This is being TLS cached.
104106
desired: _swift_stdlib_gettid(),
105107
successOrdering: .acquiring,
106108
failureOrdering: .relaxed
@@ -110,7 +112,7 @@ internal struct _MutexHandle: ~Copyable {
110112
@available(SwiftStdlib 6.0, *)
111113
@usableFromInline
112114
borrowing func unlock() {
113-
// TODO: Is it worth caching this value in TLS?
115+
// Note: This is being TLS cached.
114116
let selfId = _swift_stdlib_gettid()
115117

116118
// Attempt to release the lock. We can only atomically release the lock in

stdlib/public/Synchronization/Mutex/Mutex.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
import Builtin
14-
1513
/// A synchronization primitive that protects shared mutable state via
1614
/// mutual exclusion.
1715
///

stdlib/public/Synchronization/Mutex/WasmImpl.swift

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
// Note: All atomic accesses on WASM are sequentially consistent regardless of
14+
// what ordering we tell LLVM to use.
15+
1316
@_extern(c, "llvm.wasm32.memory.atomic.wait32")
1417
func _swift_stdlib_wait(
1518
on: UnsafePointer<UInt32>,
@@ -37,6 +40,18 @@ extension Atomic where Value == UInt32 {
3740
}
3841
}
3942

43+
@available(SwiftStdlib 6.0, *)
44+
extension _MutexHandle {
45+
@available(SwiftStdlib 6.0, *)
46+
@frozen
47+
@usableFromInline
48+
internal enum State: UInt32, AtomicRepresentable {
49+
case unlocked
50+
case locked
51+
case contended
52+
}
53+
}
54+
4055
@available(SwiftStdlib 6.0, *)
4156
@frozen
4257
@usableFromInline
@@ -75,7 +90,11 @@ internal struct _MutexHandle: ~Copyable {
7590
// If we're not already contended, go ahead and transition the mutex state
7691
// into being contended. If when we do this that the value stored there
7792
// was unlocked, then we know we unintentionally acquired the lock. A
78-
// weird quirk is that
93+
// weird quirk that occurs if this happens is that we go directly from
94+
// .unlocked -> .contended when in fact the lock may not be contended.
95+
// We may be able to do another atomic access and change it to .locked if
96+
// acquired it, but it may cause more problems than just potentially
97+
// calling wake with no waiters.
7998
if state != .contended, storage.exchange(
8099
.contended,
81100
ordering: .acquiring
@@ -130,14 +149,3 @@ internal struct _MutexHandle: ~Copyable {
130149
// Unlocked!
131150
}
132151
}
133-
134-
extension _MutexHandle {
135-
@available(SwiftStdlib 6.0, *)
136-
@frozen
137-
@usableFromInline
138-
internal enum State: UInt32, AtomicRepresentable {
139-
case unlocked
140-
case locked
141-
case contended
142-
}
143-
}

0 commit comments

Comments
 (0)