Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,10 @@ option(SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION
"Enable build of the Swift observation module"
FALSE)

option(SWIFT_ENABLE_SYNCHRONIZATION
"Enable build of the Swift Synchronization module"
FALSE)

option(SWIFT_ENABLE_DISPATCH
"Enable use of libdispatch"
TRUE)
Expand Down Expand Up @@ -1222,6 +1226,7 @@ if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
message(STATUS "Backtracing Support: ${SWIFT_ENABLE_BACKTRACING}")
message(STATUS "Unicode Support: ${SWIFT_STDLIB_ENABLE_UNICODE_DATA}")
message(STATUS "Observation Support: ${SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION}")
message(STATUS "Synchronization Support: ${SWIFT_ENABLE_SYNCHRONIZATION}")
message(STATUS "")
else()
message(STATUS "Not building Swift standard library, SDK overlays, and runtime")
Expand Down
9 changes: 9 additions & 0 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,13 @@ void Serializer::writeBlockInfoBlock() {
BLOCK_RECORD(sil_block, SIL_ONE_OPERAND_EXTRA_ATTR);
BLOCK_RECORD(sil_block, SIL_ONE_TYPE_ONE_OPERAND_EXTRA_ATTR);
BLOCK_RECORD(sil_block, SIL_TWO_OPERANDS_EXTRA_ATTR);
BLOCK_RECORD(sil_block, SIL_INST_DIFFERENTIABLE_FUNCTION);
BLOCK_RECORD(sil_block, SIL_INST_LINEAR_FUNCTION);
BLOCK_RECORD(sil_block, SIL_INST_DIFFERENTIABLE_FUNCTION_EXTRACT);
BLOCK_RECORD(sil_block, SIL_INST_LINEAR_FUNCTION_EXTRACT);
BLOCK_RECORD(sil_block, SIL_INST_INCREMENT_PROFILER_COUNTER);
BLOCK_RECORD(sil_block, SIL_MOVEONLY_DEINIT);
BLOCK_RECORD(sil_block, SIL_INST_HAS_SYMBOL);
BLOCK_RECORD(sil_block, SIL_OPEN_PACK_ELEMENT);
BLOCK_RECORD(sil_block, SIL_PACK_ELEMENT_GET);
BLOCK_RECORD(sil_block, SIL_PACK_ELEMENT_SET);
Expand All @@ -942,6 +949,8 @@ void Serializer::writeBlockInfoBlock() {
BLOCK_RECORD(sil_index_block, SIL_FUNC_OFFSETS);
BLOCK_RECORD(sil_index_block, SIL_VTABLE_NAMES);
BLOCK_RECORD(sil_index_block, SIL_VTABLE_OFFSETS);
BLOCK_RECORD(sil_index_block, SIL_MOVEONLYDEINIT_NAMES);
BLOCK_RECORD(sil_index_block, SIL_MOVEONLYDEINIT_OFFSETS);
BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_NAMES);
BLOCK_RECORD(sil_index_block, SIL_GLOBALVAR_OFFSETS);
BLOCK_RECORD(sil_index_block, SIL_WITNESS_TABLE_NAMES);
Expand Down
4 changes: 4 additions & 0 deletions stdlib/cmake/modules/SwiftSource.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ function(_add_target_variant_swift_compile_flags
list(APPEND result "-D" "SWIFT_ENABLE_EXPERIMENTAL_OBSERVATION")
endif()

if(SWIFT_ENABLE_SYNCHRONIZATION)
list(APPEND result "-D" "SWIFT_ENABLE_SYNCHRONIZATION")
endif()

if(SWIFT_STDLIB_OS_VERSIONING)
list(APPEND result "-D" "SWIFT_RUNTIME_OS_VERSIONING")
endif()
Expand Down
4 changes: 4 additions & 0 deletions stdlib/public/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,10 @@ if(SWIFT_BUILD_STDLIB AND NOT SWIFT_STDLIB_BUILD_ONLY_CORE_MODULES)
if(SWIFT_ENABLE_BACKTRACING)
add_subdirectory(Backtracing)
endif()

if(SWIFT_ENABLE_SYNCHRONIZATION)
add_subdirectory(Synchronization)
endif()
endif()

if(SWIFT_BUILD_REMOTE_MIRROR)
Expand Down
59 changes: 59 additions & 0 deletions stdlib/public/Synchronization/Atomic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Builtin

/// An atomic value.
@available(SwiftStdlib 5.11, *)
@frozen
@_rawLayout(like: Value.AtomicRepresentation)
@_staticExclusiveOnly
public struct Atomic<Value: AtomicRepresentable>: ~Copyable {
@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@_transparent
var address: UnsafeMutablePointer<Value.AtomicRepresentation> {
UnsafeMutablePointer<Value.AtomicRepresentation>(rawAddress)
}

@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@_transparent
var rawAddress: Builtin.RawPointer {
Builtin.unprotectedAddressOfBorrow(self)
}

/// Initializes a value of this atomic with the given initial value.
///
/// - Parameter initialValue: The initial value to set this atomic.
@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@_transparent
public init(_ initialValue: consuming Value) {
address.initialize(to: Value.encodeAtomicRepresentation(initialValue))
}

// Deinit's can't be marked @_transparent. Do these things need all of these
// attributes..?
@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@inlinable
deinit {
let oldValue = Value.decodeAtomicRepresentation(address.pointee)
_ = consume oldValue

address.deinitialize(count: 1)
}
}

@available(SwiftStdlib 5.11, *)
extension Atomic: @unchecked Sendable where Value: Sendable {}
248 changes: 248 additions & 0 deletions stdlib/public/Synchronization/AtomicBool.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

import Builtin

//===----------------------------------------------------------------------===//
// Bool AtomicRepresentable conformance
//===----------------------------------------------------------------------===//

@available(SwiftStdlib 5.11, *)
extension Bool: AtomicRepresentable {
/// The storage representation type that `Self` encodes to and decodes from
/// which is a suitable type when used in atomic operations.
@available(SwiftStdlib 5.11, *)
public typealias AtomicRepresentation = UInt8.AtomicRepresentation

/// Destroys a value of `Self` and prepares an `AtomicRepresentation` storage
/// type to be used for atomic operations.
///
/// - Note: This is not an atomic operation. This simply encodes the logical
/// type `Self` into its storage representation suitable for atomic
/// operations, `AtomicRepresentation`.
///
/// - Parameter value: A valid instance of `Self` that's about to be destroyed
/// to encode an instance of its `AtomicRepresentation`.
/// - Returns: The newly encoded `AtomicRepresentation` storage.
@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@_transparent
public static func encodeAtomicRepresentation(
_ value: borrowing Bool
) -> AtomicRepresentation {
UInt8.encodeAtomicRepresentation(
UInt8(Builtin.zext_Int1_Int8(value._value))
)
}

/// Recovers the logical atomic type `Self` by destroying some
/// `AtomicRepresentation` storage instance returned from an atomic operation.
///
/// - Note: This is not an atomic operation. This simply decodes the storage
/// representation used in atomic operations back into the logical type for
/// normal use, `Self`.
///
/// - Parameter storage: The storage representation for `Self` that's used
/// within atomic operations.
/// - Returns: The newly decoded logical type `Self`.
@available(SwiftStdlib 5.11, *)
@_alwaysEmitIntoClient
@_transparent
public static func decodeAtomicRepresentation(
_ representation: consuming AtomicRepresentation
) -> Bool {
Bool(Builtin.trunc_Int8_Int1(
UInt8.decodeAtomicRepresentation(representation)._value)
)
}
}

//===----------------------------------------------------------------------===//
// Bool atomic operations
//===----------------------------------------------------------------------===//

@available(SwiftStdlib 5.11, *)
extension Atomic where Value == Bool {
/// Perform an atomic logical AND operation and return the old and new value,
/// applying the specified memory ordering.
///
/// - Parameter operand: A boolean value.
/// - Parameter ordering: The memory ordering to apply on this operation.
/// - Returns: A tuple with the old value before the operation a the new value
/// after the operation.
@available(SwiftStdlib 5.11, *)
@discardableResult
@_semantics("atomics.requires_constant_orderings")
@_alwaysEmitIntoClient
@_transparent
public func logicalAnd(
_ operand: Bool,
ordering: AtomicUpdateOrdering
) -> (oldValue: Bool, newValue: Bool) {
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage

let original = switch ordering {
case .relaxed:
Builtin.atomicrmw_and_monotonic_Int8(
rawAddress,
builtinOperand
)

case .acquiring:
Builtin.atomicrmw_and_acquire_Int8(
rawAddress,
builtinOperand
)

case .releasing:
Builtin.atomicrmw_and_release_Int8(
rawAddress,
builtinOperand
)

case .acquiringAndReleasing:
Builtin.atomicrmw_and_acqrel_Int8(
rawAddress,
builtinOperand
)

case .sequentiallyConsistent:
Builtin.atomicrmw_and_seqcst_Int8(
rawAddress,
builtinOperand
)

default:
Builtin.unreachable()
}

let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))

return (oldValue: old, newValue: old && operand)
}

/// Perform an atomic logical OR operation and return the old and new value,
/// applying the specified memory ordering.
///
/// - Parameter operand: A boolean value.
/// - Parameter ordering: The memory ordering to apply on this operation.
/// - Returns: A tuple with the old value before the operation a the new value
/// after the operation.
@available(SwiftStdlib 5.11, *)
@discardableResult
@_semantics("atomics.requires_constant_orderings")
@_alwaysEmitIntoClient
@_transparent
public func logicalOr(
_ operand: Bool,
ordering: AtomicUpdateOrdering
) -> (oldValue: Bool, newValue: Bool) {
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage

let original = switch ordering {
case .relaxed:
Builtin.atomicrmw_or_monotonic_Int8(
rawAddress,
builtinOperand
)

case .acquiring:
Builtin.atomicrmw_or_acquire_Int8(
rawAddress,
builtinOperand
)

case .releasing:
Builtin.atomicrmw_or_release_Int8(
rawAddress,
builtinOperand
)

case .acquiringAndReleasing:
Builtin.atomicrmw_or_acqrel_Int8(
rawAddress,
builtinOperand
)

case .sequentiallyConsistent:
Builtin.atomicrmw_or_seqcst_Int8(
rawAddress,
builtinOperand
)

default:
Builtin.unreachable()
}

let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))

return (oldValue: old, newValue: old || operand)
}

/// Perform an atomic logical XOR operation and return the old and new value,
/// applying the specified memory ordering.
///
/// - Parameter operand: A boolean value.
/// - Parameter ordering: The memory ordering to apply on this operation.
/// - Returns: A tuple with the old value before the operation a the new value
/// after the operation.
@available(SwiftStdlib 5.11, *)
@discardableResult
@_semantics("atomics.requires_constant_orderings")
@_alwaysEmitIntoClient
@_transparent
public func logicalXor(
_ operand: Bool,
ordering: AtomicUpdateOrdering
) -> (oldValue: Bool, newValue: Bool) {
let builtinOperand = Bool.encodeAtomicRepresentation(operand)._storage

let original = switch ordering {
case .relaxed:
Builtin.atomicrmw_xor_monotonic_Int8(
rawAddress,
builtinOperand
)

case .acquiring:
Builtin.atomicrmw_xor_acquire_Int8(
rawAddress,
builtinOperand
)

case .releasing:
Builtin.atomicrmw_xor_release_Int8(
rawAddress,
builtinOperand
)

case .acquiringAndReleasing:
Builtin.atomicrmw_xor_acqrel_Int8(
rawAddress,
builtinOperand
)

case .sequentiallyConsistent:
Builtin.atomicrmw_xor_seqcst_Int8(
rawAddress,
builtinOperand
)

default:
Builtin.unreachable()
}

let old = Bool.decodeAtomicRepresentation(UInt8.AtomicRepresentation(original))

return (oldValue: old, newValue: old != operand)
}
}
Loading