Skip to content

Commit e37ecac

Browse files
authored
Merge pull request #68857 from Azoy/atomics
[stdlib] Atomics
2 parents e24c9a8 + 90f5a0a commit e37ecac

File tree

62 files changed

+5926
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+5926
-9
lines changed

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,10 @@ option(SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION
647647
"Enable build of the Swift observation module"
648648
FALSE)
649649

650+
option(SWIFT_ENABLE_SYNCHRONIZATION
651+
"Enable build of the Swift Synchronization module"
652+
FALSE)
653+
650654
option(SWIFT_ENABLE_DISPATCH
651655
"Enable use of libdispatch"
652656
TRUE)
@@ -1224,6 +1228,7 @@ if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
12241228
message(STATUS "Backtracing Support: ${SWIFT_ENABLE_BACKTRACING}")
12251229
message(STATUS "Unicode Support: ${SWIFT_STDLIB_ENABLE_UNICODE_DATA}")
12261230
message(STATUS "Observation Support: ${SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION}")
1231+
message(STATUS "Synchronization Support: ${SWIFT_ENABLE_SYNCHRONIZATION}")
12271232
message(STATUS "")
12281233
else()
12291234
message(STATUS "Not building Swift standard library, SDK overlays, and runtime")

lib/Serialization/Serialization.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,13 @@ void Serializer::writeBlockInfoBlock() {
933933
BLOCK_RECORD(sil_block, SIL_ONE_OPERAND_EXTRA_ATTR);
934934
BLOCK_RECORD(sil_block, SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR);
935935
BLOCK_RECORD(sil_block, SIL_TWO_OPERANDS_EXTRA_ATTR);
936+
BLOCK_RECORD(sil_block, SIL_INST_DIFFERENTIABLE_FUNCTION);
937+
BLOCK_RECORD(sil_block, SIL_INST_LINEAR_FUNCTION);
938+
BLOCK_RECORD(sil_block, SIL_INST_DIFFERENTIABLE_FUNCTION_EXTRACT);
939+
BLOCK_RECORD(sil_block, SIL_INST_LINEAR_FUNCTION_EXTRACT);
940+
BLOCK_RECORD(sil_block, SIL_INST_INCREMENT_PROFILER_COUNTER);
941+
BLOCK_RECORD(sil_block, SIL_MOVEONLY_DEINIT);
942+
BLOCK_RECORD(sil_block, SIL_INST_HAS_SYMBOL);
936943
BLOCK_RECORD(sil_block, SIL_OPEN_PACK_ELEMENT);
937944
BLOCK_RECORD(sil_block, SIL_PACK_ELEMENT_GET);
938945
BLOCK_RECORD(sil_block, SIL_PACK_ELEMENT_SET);
@@ -942,6 +949,8 @@ void Serializer::writeBlockInfoBlock() {
942949
BLOCK_RECORD(sil_index_block, SIL_FUNC_OFFSETS);
943950
BLOCK_RECORD(sil_index_block, SIL_VTABLE_NAMES);
944951
BLOCK_RECORD(sil_index_block, SIL_VTABLE_OFFSETS);
952+
BLOCK_RECORD(sil_index_block, SIL_MOVEONLYDEINIT_NAMES);
953+
BLOCK_RECORD(sil_index_block, SIL_MOVEONLYDEINIT_OFFSETS);
945954
BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_NAMES);
946955
BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_OFFSETS);
947956
BLOCK_RECORD(sil_index_block, SIL_WITNESS_TABLE_NAMES);

stdlib/cmake/modules/SwiftSource.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ function(_add_target_variant_swift_compile_flags
321321
list(APPEND result "-D" "SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION")
322322
endif()
323323

324+
if(SWIFT_ENABLE_SYNCHRONIZATION)
325+
list(APPEND result "-D" "SWIFT_ENABLE_SYNCHRONIZATION")
326+
endif()
327+
324328
if(SWIFT_STDLIB_OS_VERSIONING)
325329
list(APPEND result "-D" "SWIFT_RUNTIME_OS_VERSIONING")
326330
endif()

stdlib/public/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ if(SWIFT_BUILD_STDLIB AND NOT SWIFT_STDLIB_BUILD_ONLY_CORE_MODULES)
252252
if(SWIFT_ENABLE_BACKTRACING)
253253
add_subdirectory(Backtracing)
254254
endif()
255+
256+
if(SWIFT_ENABLE_SYNCHRONIZATION)
257+
add_subdirectory(Synchronization)
258+
endif()
255259
endif()
256260

257261
if(SWIFT_BUILD_REMOTE_MIRROR)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Builtin
14+
15+
/// An atomic value.
16+
@available(SwiftStdlib 5.11, *)
17+
@frozen
18+
@_rawLayout(like: Value.AtomicRepresentation)
19+
@_staticExclusiveOnly
20+
public struct Atomic<Value: AtomicRepresentable>: ~Copyable {
21+
@available(SwiftStdlib 5.11, *)
22+
@_alwaysEmitIntoClient
23+
@_transparent
24+
var address: UnsafeMutablePointer<Value.AtomicRepresentation> {
25+
UnsafeMutablePointer<Value.AtomicRepresentation>(rawAddress)
26+
}
27+
28+
@available(SwiftStdlib 5.11, *)
29+
@_alwaysEmitIntoClient
30+
@_transparent
31+
var rawAddress: Builtin.RawPointer {
32+
Builtin.unprotectedAddressOfBorrow(self)
33+
}
34+
35+
/// Initializes a value of this atomic with the given initial value.
36+
///
37+
/// - Parameter initialValue: The initial value to set this atomic.
38+
@available(SwiftStdlib 5.11, *)
39+
@_alwaysEmitIntoClient
40+
@_transparent
41+
public init(_ initialValue: consuming Value) {
42+
address.initialize(to: Value.encodeAtomicRepresentation(initialValue))
43+
}
44+
45+
// Deinit's can't be marked @_transparent. Do these things need all of these
46+
// attributes..?
47+
@available(SwiftStdlib 5.11, *)
48+
@_alwaysEmitIntoClient
49+
@inlinable
50+
deinit {
51+
let oldValue = Value.decodeAtomicRepresentation(address.pointee)
52+
_ = consume oldValue
53+
54+
address.deinitialize(count: 1)
55+
}
56+
}
57+
58+
@available(SwiftStdlib 5.11, *)
59+
extension Atomic: @unchecked Sendable where Value: Sendable {}
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import Builtin
14+
15+
//===----------------------------------------------------------------------===//
16+
// Bool AtomicRepresentable conformance
17+
//===----------------------------------------------------------------------===//
18+
19+
@available(SwiftStdlib 5.11, *)
20+
extension Bool: AtomicRepresentable {
21+
/// The storage representation type that `Self` encodes to and decodes from
22+
/// which is a suitable type when used in atomic operations.
23+
@available(SwiftStdlib 5.11, *)
24+
public typealias AtomicRepresentation = UInt8.AtomicRepresentation
25+
26+
/// Destroys a value of `Self` and prepares an `AtomicRepresentation` storage
27+
/// type to be used for atomic operations.
28+
///
29+
/// - Note: This is not an atomic operation. This simply encodes the logical
30+
/// type `Self` into its storage representation suitable for atomic
31+
/// operations, `AtomicRepresentation`.
32+
///
33+
/// - Parameter value: A valid instance of `Self` that's about to be destroyed
34+
/// to encode an instance of its `AtomicRepresentation`.
35+
/// - Returns: The newly encoded `AtomicRepresentation` storage.
36+
@available(SwiftStdlib 5.11, *)
37+
@_alwaysEmitIntoClient
38+
@_transparent
39+
public static func encodeAtomicRepresentation(
40+
_ value: borrowing Bool
41+
) -> AtomicRepresentation {
42+
UInt8.encodeAtomicRepresentation(
43+
UInt8(Builtin.zext_Int1_Int8(value._value))
44+
)
45+
}
46+
47+
/// Recovers the logical atomic type `Self` by destroying some
48+
/// `AtomicRepresentation` storage instance returned from an atomic operation.
49+
///
50+
/// - Note: This is not an atomic operation. This simply decodes the storage
51+
/// representation used in atomic operations back into the logical type for
52+
/// normal use, `Self`.
53+
///
54+
/// - Parameter storage: The storage representation for `Self` that's used
55+
/// within atomic operations.
56+
/// - Returns: The newly decoded logical type `Self`.
57+
@available(SwiftStdlib 5.11, *)
58+
@_alwaysEmitIntoClient
59+
@_transparent
60+
public static func decodeAtomicRepresentation(
61+
_ representation: consuming AtomicRepresentation
62+
) -> Bool {
63+
Bool(Builtin.trunc_Int8_Int1(
64+
UInt8.decodeAtomicRepresentation(representation)._value)
65+
)
66+
}
67+
}
68+
69+
//===----------------------------------------------------------------------===//
70+
// Bool atomic operations
71+
//===----------------------------------------------------------------------===//
72+
73+
@available(SwiftStdlib 5.11, *)
74+
extension Atomic where Value == Bool {
75+
/// Perform an atomic logical AND operation and return the old and new value,
76+
/// applying the specified memory ordering.
77+
///
78+
/// - Parameter operand: A boolean value.
79+
/// - Parameter ordering: The memory ordering to apply on this operation.
80+
/// - Returns: A tuple with the old value before the operation a the new value
81+
/// after the operation.
82+
@available(SwiftStdlib 5.11, *)
83+
@discardableResult
84+
@_semantics("atomics.requires_constant_orderings")
85+
@_alwaysEmitIntoClient
86+
@_transparent
87+
public func logicalAnd(
88+
_ operand: Bool,
89+
ordering: AtomicUpdateOrdering
90+
) -> (oldValue: Bool, newValue: Bool) {
91+
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage
92+
93+
let original = switch ordering {
94+
case .relaxed:
95+
Builtin.atomicrmw_and_monotonic_Int8(
96+
rawAddress,
97+
builtinOperand
98+
)
99+
100+
case .acquiring:
101+
Builtin.atomicrmw_and_acquire_Int8(
102+
rawAddress,
103+
builtinOperand
104+
)
105+
106+
case .releasing:
107+
Builtin.atomicrmw_and_release_Int8(
108+
rawAddress,
109+
builtinOperand
110+
)
111+
112+
case .acquiringAndReleasing:
113+
Builtin.atomicrmw_and_acqrel_Int8(
114+
rawAddress,
115+
builtinOperand
116+
)
117+
118+
case .sequentiallyConsistent:
119+
Builtin.atomicrmw_and_seqcst_Int8(
120+
rawAddress,
121+
builtinOperand
122+
)
123+
124+
default:
125+
Builtin.unreachable()
126+
}
127+
128+
let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))
129+
130+
return (oldValue: old, newValue: old && operand)
131+
}
132+
133+
/// Perform an atomic logical OR operation and return the old and new value,
134+
/// applying the specified memory ordering.
135+
///
136+
/// - Parameter operand: A boolean value.
137+
/// - Parameter ordering: The memory ordering to apply on this operation.
138+
/// - Returns: A tuple with the old value before the operation a the new value
139+
/// after the operation.
140+
@available(SwiftStdlib 5.11, *)
141+
@discardableResult
142+
@_semantics("atomics.requires_constant_orderings")
143+
@_alwaysEmitIntoClient
144+
@_transparent
145+
public func logicalOr(
146+
_ operand: Bool,
147+
ordering: AtomicUpdateOrdering
148+
) -> (oldValue: Bool, newValue: Bool) {
149+
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage
150+
151+
let original = switch ordering {
152+
case .relaxed:
153+
Builtin.atomicrmw_or_monotonic_Int8(
154+
rawAddress,
155+
builtinOperand
156+
)
157+
158+
case .acquiring:
159+
Builtin.atomicrmw_or_acquire_Int8(
160+
rawAddress,
161+
builtinOperand
162+
)
163+
164+
case .releasing:
165+
Builtin.atomicrmw_or_release_Int8(
166+
rawAddress,
167+
builtinOperand
168+
)
169+
170+
case .acquiringAndReleasing:
171+
Builtin.atomicrmw_or_acqrel_Int8(
172+
rawAddress,
173+
builtinOperand
174+
)
175+
176+
case .sequentiallyConsistent:
177+
Builtin.atomicrmw_or_seqcst_Int8(
178+
rawAddress,
179+
builtinOperand
180+
)
181+
182+
default:
183+
Builtin.unreachable()
184+
}
185+
186+
let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))
187+
188+
return (oldValue: old, newValue: old || operand)
189+
}
190+
191+
/// Perform an atomic logical XOR operation and return the old and new value,
192+
/// applying the specified memory ordering.
193+
///
194+
/// - Parameter operand: A boolean value.
195+
/// - Parameter ordering: The memory ordering to apply on this operation.
196+
/// - Returns: A tuple with the old value before the operation a the new value
197+
/// after the operation.
198+
@available(SwiftStdlib 5.11, *)
199+
@discardableResult
200+
@_semantics("atomics.requires_constant_orderings")
201+
@_alwaysEmitIntoClient
202+
@_transparent
203+
public func logicalXor(
204+
_ operand: Bool,
205+
ordering: AtomicUpdateOrdering
206+
) -> (oldValue: Bool, newValue: Bool) {
207+
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage
208+
209+
let original = switch ordering {
210+
case .relaxed:
211+
Builtin.atomicrmw_xor_monotonic_Int8(
212+
rawAddress,
213+
builtinOperand
214+
)
215+
216+
case .acquiring:
217+
Builtin.atomicrmw_xor_acquire_Int8(
218+
rawAddress,
219+
builtinOperand
220+
)
221+
222+
case .releasing:
223+
Builtin.atomicrmw_xor_release_Int8(
224+
rawAddress,
225+
builtinOperand
226+
)
227+
228+
case .acquiringAndReleasing:
229+
Builtin.atomicrmw_xor_acqrel_Int8(
230+
rawAddress,
231+
builtinOperand
232+
)
233+
234+
case .sequentiallyConsistent:
235+
Builtin.atomicrmw_xor_seqcst_Int8(
236+
rawAddress,
237+
builtinOperand
238+
)
239+
240+
default:
241+
Builtin.unreachable()
242+
}
243+
244+
let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))
245+
246+
return (oldValue: old, newValue: old != operand)
247+
}
248+
}

0 commit comments

Comments
 (0)