mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/main' into rebranch
This commit is contained in:
@@ -295,8 +295,6 @@ else()
|
||||
set(compatibility_libs
|
||||
"swiftCompatibility50-${platform}"
|
||||
"swiftCompatibility51-${platform}"
|
||||
"swiftCompatibility56-${platform}"
|
||||
"swiftCompatibilityConcurrency-${platform}"
|
||||
"swiftCompatibilityDynamicReplacements-${platform}")
|
||||
|
||||
list(APPEND b0_deps ${compatibility_libs})
|
||||
|
||||
@@ -28,6 +28,5 @@ BACK_DEPLOYMENT_LIB((5, 0), all, "swiftCompatibility50")
|
||||
BACK_DEPLOYMENT_LIB((5, 1), all, "swiftCompatibility51")
|
||||
BACK_DEPLOYMENT_LIB((5, 0), executable, "swiftCompatibilityDynamicReplacements")
|
||||
BACK_DEPLOYMENT_LIB((5, 4), all, "swiftCompatibilityConcurrency")
|
||||
BACK_DEPLOYMENT_LIB((5, 6), all, "swiftCompatibility56")
|
||||
|
||||
#undef BACK_DEPLOYMENT_LIB
|
||||
|
||||
@@ -412,8 +412,6 @@ toolchains::Darwin::addArgsToLinkStdlib(ArgStringList &Arguments,
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 1);
|
||||
} else if (value.equals("5.5")) {
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 5);
|
||||
} else if (value.equals("5.6")) {
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
|
||||
} else if (value.equals("none")) {
|
||||
runtimeCompatibilityVersion = None;
|
||||
} else {
|
||||
|
||||
@@ -2292,8 +2292,6 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 1);
|
||||
} else if (version.equals("5.5")) {
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 5);
|
||||
} else if (version.equals("5.6")) {
|
||||
runtimeCompatibilityVersion = llvm::VersionTuple(5, 6);
|
||||
} else {
|
||||
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
|
||||
versionArg->getAsString(Args), version);
|
||||
|
||||
@@ -39,8 +39,6 @@ include(StdlibOptions)
|
||||
# End of user-configurable options.
|
||||
#
|
||||
|
||||
set(SWIFT_STDLIB_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
# Remove llvm-project/llvm/include directory from -I search part when building
|
||||
# the stdlib. We have our own fork of LLVM includes (Support, ADT) in
|
||||
# stdlib/include/llvm and we don't want to silently use headers from LLVM.
|
||||
|
||||
@@ -50,7 +50,6 @@ if(SWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT)
|
||||
add_subdirectory(legacy_layouts)
|
||||
add_subdirectory(Compatibility50)
|
||||
add_subdirectory(Compatibility51)
|
||||
add_subdirectory(Compatibility56)
|
||||
add_subdirectory(CompatibilityDynamicReplacements)
|
||||
add_subdirectory(CompatibilityConcurrency)
|
||||
endif()
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
set(library_name "swiftCompatibility56")
|
||||
|
||||
include_directories("include/" "${SWIFT_STDLIB_SOURCE_DIR}")
|
||||
|
||||
add_swift_target_library("${library_name}" STATIC
|
||||
Overrides.cpp
|
||||
Concurrency/Task.cpp
|
||||
Concurrency/Error.cpp
|
||||
Concurrency/Actor.cpp
|
||||
Concurrency/AsyncLet.cpp
|
||||
|
||||
TARGET_SDKS ${SWIFT_DARWIN_PLATFORMS}
|
||||
|
||||
C_COMPILE_FLAGS ${CXX_COMPILE_FLAGS}
|
||||
LINK_FLAGS ${CXX_LINK_FLAGS}
|
||||
INCORPORATE_OBJECT_LIBRARIES swiftThreading
|
||||
SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
|
||||
DEPLOYMENT_VERSION_OSX ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_OSX}
|
||||
DEPLOYMENT_VERSION_IOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_IOS}
|
||||
DEPLOYMENT_VERSION_TVOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_TVOS}
|
||||
DEPLOYMENT_VERSION_WATCHOS ${COMPATIBILITY_MINIMUM_DEPLOYMENT_VERSION_WATCHOS}
|
||||
|
||||
INSTALL_IN_COMPONENT compiler
|
||||
INSTALL_WITH_SHARED)
|
||||
|
||||
|
||||
# FIXME: We need a more flexible mechanism to add lipo targets generated by
|
||||
# add_swift_target_library to the ALL target. Until then this hack is necessary
|
||||
# to ensure these libraries build.
|
||||
foreach(sdk ${SWIFT_SDKS})
|
||||
set(target_name "${library_name}-${SWIFT_SDK_${sdk}_LIB_SUBDIR}")
|
||||
if(NOT TARGET "${target_name}")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
set_target_properties("${target_name}"
|
||||
PROPERTIES
|
||||
EXCLUDE_FROM_ALL FALSE)
|
||||
endforeach()
|
||||
@@ -1,137 +0,0 @@
|
||||
//===--- CompatibiltyOverride.h - Back-deploying compatibility fixes --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Support back-deploying compatibility fixes for newer apps running on older runtimes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef COMPATIBILITY_OVERRIDE_H
|
||||
#define COMPATIBILITY_OVERRIDE_H
|
||||
|
||||
#include "public/runtime/Private.h"
|
||||
|
||||
#include "Runtime/Concurrency.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "swift/Runtime/Once.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace swift {
|
||||
|
||||
// Macro utilities.
|
||||
#define COMPATIBILITY_UNPAREN(...) __VA_ARGS__
|
||||
#define COMPATIBILITY_CONCAT2(x, y) x##y
|
||||
#define COMPATIBILITY_CONCAT(x, y) COMPATIBILITY_CONCAT2(x, y)
|
||||
|
||||
// This ridiculous construct will remove the parentheses from the argument and
|
||||
// add a trailing comma, or will produce nothing when passed no argument. For
|
||||
// example:
|
||||
// COMPATIBILITY_UNPAREN_WITH_COMMA((1, 2, 3)) -> 1, 2, 3,
|
||||
// COMPATIBILITY_UNPAREN_WITH_COMMA((4)) -> 4,
|
||||
// COMPATIBILITY_UNPAREN_WITH_COMMA() ->
|
||||
#define COMPATIBILITY_UNPAREN_WITH_COMMA(x) \
|
||||
COMPATIBILITY_CONCAT(COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_, \
|
||||
COMPATIBILITY_UNPAREN_WITH_COMMA2 x)
|
||||
#define COMPATIBILITY_UNPAREN_WITH_COMMA2(...) PARAMS(__VA_ARGS__)
|
||||
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_PARAMS(...) __VA_ARGS__,
|
||||
#define COMPATIBILITY_UNPAREN_ADD_TRAILING_COMMA_COMPATIBILITY_UNPAREN_WITH_COMMA2
|
||||
|
||||
// This ridiculous construct will preserve the parentheses around the argument,
|
||||
// or will produce an empty pair of parentheses when passed no argument. For
|
||||
// example:
|
||||
// COMPATIBILITY_PAREN((1, 2, 3)) -> (1, 2, 3)
|
||||
// COMPATIBILITY_PAREN((4)) -> (4)
|
||||
// COMPATIBILITY_PAREN() -> ()
|
||||
#define COMPATIBILITY_PAREN(x) \
|
||||
COMPATIBILITY_CONCAT(COMPATIBILITY_PAREN_, COMPATIBILITY_PAREN2 x)
|
||||
#define COMPATIBILITY_PAREN2(...) PARAMS(__VA_ARGS__)
|
||||
#define COMPATIBILITY_PAREN_PARAMS(...) (__VA_ARGS__)
|
||||
#define COMPATIBILITY_PAREN_COMPATIBILITY_PAREN2 ()
|
||||
|
||||
// Include path computation. Code that includes this file can write
|
||||
// `#include COMPATIBILITY_OVERRIDE_INCLUDE_PATH` to include the appropriate
|
||||
// .def file for the current library.
|
||||
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swiftRuntime \
|
||||
"CompatibilityOverrideRuntime.def"
|
||||
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH_swift_Concurrency \
|
||||
"CompatibilityOverrideConcurrency.def"
|
||||
|
||||
#define COMPATIBILITY_OVERRIDE_INCLUDE_PATH \
|
||||
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_INCLUDE_PATH_, \
|
||||
SWIFT_TARGET_LIBRARY_NAME)
|
||||
|
||||
// Compatibility overrides are only supported on Darwin.
|
||||
#ifndef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
|
||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
||||
#define SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
|
||||
|
||||
# error Back-deployment library must always be built with compatibilty overrides
|
||||
|
||||
#else // #ifdef SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
|
||||
|
||||
// Override section name computation. `COMPATIBILITY_OVERRIDE_SECTION_NAME` will
|
||||
// resolve to string literal containing the appropriate section name for the
|
||||
// current library.
|
||||
#define COMPATIBILITY_OVERRIDE_SECTION_NAME_swift_Concurrency "__s_async_hook"
|
||||
|
||||
#define COMPATIBILITY_OVERRIDE_SECTION_NAME \
|
||||
COMPATIBILITY_CONCAT(COMPATIBILITY_OVERRIDE_SECTION_NAME_, \
|
||||
SWIFT_TARGET_LIBRARY_NAME)
|
||||
|
||||
// Create typedefs for function pointers to call the original implementation.
|
||||
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
|
||||
ccAttrs typedef ret(*Original_##name) COMPATIBILITY_PAREN(typedArgs);
|
||||
#include "CompatibilityOverrideRuntime.def"
|
||||
#include "CompatibilityOverrideConcurrency.def"
|
||||
#undef OVERRIDE
|
||||
|
||||
|
||||
// Create typedefs for override function pointers.
|
||||
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
|
||||
ccAttrs typedef ret (*Override_##name)(COMPATIBILITY_UNPAREN_WITH_COMMA( \
|
||||
typedArgs) Original_##name originalImpl);
|
||||
#include "CompatibilityOverrideRuntime.def"
|
||||
#include "CompatibilityOverrideConcurrency.def"
|
||||
#undef OVERRIDE
|
||||
|
||||
// Create declarations for getOverride functions.
|
||||
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
|
||||
Override_ ## name getOverride_ ## name();
|
||||
#include "CompatibilityOverrideRuntime.def"
|
||||
#include "CompatibilityOverrideConcurrency.def"
|
||||
#undef OVERRIDE
|
||||
|
||||
/// Used to define an override point. The override point #defines the appropriate
|
||||
/// OVERRIDE macro from CompatibilityOverride.def to this macro, then includes
|
||||
/// the file to generate the override points. The original implementation of the
|
||||
/// functionality must be available as swift_funcNameHereImpl.
|
||||
#define COMPATIBILITY_OVERRIDE(name, ret, attrs, ccAttrs, namespace, \
|
||||
typedArgs, namedArgs) \
|
||||
attrs ccAttrs ret namespace swift_##name COMPATIBILITY_PAREN(typedArgs) { \
|
||||
static Override_##name Override; \
|
||||
static swift_once_t Predicate; \
|
||||
swift_once( \
|
||||
&Predicate, [](void *) { Override = getOverride_##name(); }, nullptr); \
|
||||
if (Override != nullptr) \
|
||||
return Override(COMPATIBILITY_UNPAREN_WITH_COMMA(namedArgs) \
|
||||
swift_##name##Impl); \
|
||||
return swift_##name##Impl COMPATIBILITY_PAREN(namedArgs); \
|
||||
}
|
||||
|
||||
#endif // #else SWIFT_RUNTIME_NO_COMPATIBILITY_OVERRIDES
|
||||
|
||||
} /* end namespace swift */
|
||||
|
||||
#endif /* COMPATIBILITY_OVERRIDE_H */
|
||||
@@ -1,356 +0,0 @@
|
||||
//===--- CompatibilityOverridesConcurrency.def - Overrides Info -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines x-macros used for metaprogramming with the set of
|
||||
// compatibility override functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs)
|
||||
/// Provides information about an overridable function.
|
||||
/// - name is the name of the function, without any leading swift_ or
|
||||
/// namespace.
|
||||
/// - ret is the return type of the function.
|
||||
/// - attrs is the attributes, if any, applied to the function definition.
|
||||
/// - ccAttrs is the calling convention attributes, if any, applied to the
|
||||
/// function definition and corresponding typedefs
|
||||
/// - namespace is the namespace, if any, the function is in, including a
|
||||
/// trailing ::
|
||||
/// - typedArgs is the argument list, including types, surrounded by
|
||||
/// parentheses
|
||||
/// - namedArgs is the list of argument names, with no types, surrounded by
|
||||
/// parentheses
|
||||
///
|
||||
/// The entries are organized by group. A user may define OVERRIDE to get all
|
||||
/// entries, or define one or more of the more specific OVERRIDE_* variants to
|
||||
/// get only those entries.
|
||||
|
||||
// NOTE: this file is used to build the definition of OverrideSection in
|
||||
// CompatibilityOverride.cpp, which is part of the ABI. Moving or removing
|
||||
// entries in this file will break the ABI. Additional entries can be added to
|
||||
// the end. ABI breaks or version-specific changes can be accommodated by
|
||||
// changing the name of the override section in that file.
|
||||
|
||||
#ifdef OVERRIDE
|
||||
# define OVERRIDE_ACTOR OVERRIDE
|
||||
# define OVERRIDE_TASK OVERRIDE
|
||||
# define OVERRIDE_ASYNC_LET OVERRIDE
|
||||
# define OVERRIDE_TASK_GROUP OVERRIDE
|
||||
# define OVERRIDE_TASK_LOCAL OVERRIDE
|
||||
# define OVERRIDE_TASK_STATUS OVERRIDE
|
||||
#else
|
||||
# ifndef OVERRIDE_ACTOR
|
||||
# define OVERRIDE_ACTOR(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_TASK
|
||||
# define OVERRIDE_TASK(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_ASYNC_LET
|
||||
# define OVERRIDE_ASYNC_LET(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_TASK_GROUP
|
||||
# define OVERRIDE_TASK_GROUP(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_TASK_LOCAL
|
||||
# define OVERRIDE_TASK_LOCAL(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_TASK_STATUS
|
||||
# define OVERRIDE_TASK_STATUS(...)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
OVERRIDE_ACTOR(task_enqueue, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (class Job *job, ExecutorRef executor),
|
||||
(job, executor))
|
||||
|
||||
OVERRIDE_ACTOR(job_run, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (class Job *job, ExecutorRef executor),
|
||||
(job, executor))
|
||||
|
||||
OVERRIDE_ACTOR(task_getCurrentExecutor, ExecutorRef,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, ,)
|
||||
|
||||
OVERRIDE_ACTOR(task_isCurrentExecutor, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (ExecutorRef executor), (executor))
|
||||
|
||||
OVERRIDE_ACTOR(task_switch, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::, (SWIFT_ASYNC_CONTEXT AsyncContext *resumeToContext,
|
||||
TaskContinuationFunction *resumeFunction, ExecutorRef newExecutor),
|
||||
(resumeToContext, resumeFunction, newExecutor))
|
||||
|
||||
OVERRIDE_TASK(task_create_common, AsyncTaskAndContext,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(size_t taskCreateFlags,
|
||||
TaskOptionRecord *options,
|
||||
const Metadata *futureResultType,
|
||||
FutureAsyncSignature::FunctionType *function,
|
||||
void *closureContext,
|
||||
size_t initialContextSize),
|
||||
(taskCreateFlags, options, futureResultType, function,
|
||||
closureContext, initialContextSize))
|
||||
|
||||
OVERRIDE_TASK(task_future_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency),
|
||||
SWIFT_CC(swiftasync), swift::,
|
||||
(OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, AsyncTask *task,
|
||||
TaskContinuationFunction *resumeFunction,
|
||||
AsyncContext *callContext),
|
||||
(result, callerContext, task, resumeFunction, callContext))
|
||||
|
||||
OVERRIDE_TASK(task_future_wait_throwing, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext, AsyncTask *task,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFunction,
|
||||
AsyncContext *callContext),
|
||||
(result, callerContext, task, resumeFunction, callContext))
|
||||
|
||||
OVERRIDE_TASK(continuation_resume, void, SWIFT_EXPORT_FROM(swift_Concurrency),
|
||||
SWIFT_CC(swift), swift::,
|
||||
(AsyncTask *continuation),
|
||||
(continuation))
|
||||
|
||||
OVERRIDE_TASK(continuation_throwingResume, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(AsyncTask *continuation),
|
||||
(continuation))
|
||||
|
||||
OVERRIDE_TASK(continuation_throwingResumeWithError, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(AsyncTask *continuation, SwiftError *error),
|
||||
(continuation, error))
|
||||
|
||||
OVERRIDE_TASK(task_addCancellationHandler,
|
||||
CancellationNotificationStatusRecord *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(CancellationNotificationStatusRecord::FunctionType handler,
|
||||
void *context),
|
||||
(handler, context))
|
||||
|
||||
OVERRIDE_TASK(task_removeCancellationHandler, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(CancellationNotificationStatusRecord *record), (record))
|
||||
|
||||
OVERRIDE_TASK(task_createNullaryContinuationJob, NullaryContinuationJob *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(size_t priority,
|
||||
AsyncTask *continuation), (priority, continuation))
|
||||
|
||||
OVERRIDE_TASK(task_asyncMainDrainQueue, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
, )
|
||||
|
||||
OVERRIDE_TASK(task_suspend, AsyncTask *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, ,)
|
||||
|
||||
OVERRIDE_TASK(continuation_init, AsyncTask *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (ContinuationAsyncContext *context,
|
||||
AsyncContinuationFlags flags),
|
||||
(context, flags))
|
||||
|
||||
OVERRIDE_TASK(continuation_await, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::, (ContinuationAsyncContext *context),
|
||||
(context))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_wait, void, SWIFT_EXPORT_FROM(swift_Concurrency),
|
||||
SWIFT_CC(swiftasync), swift::,
|
||||
(OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(result, callerContext, alet, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_wait_throwing, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resume,
|
||||
AsyncContext *callContext),
|
||||
(result, callerContext, alet, resume, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_end, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (AsyncLet *alet), (alet))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_get, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, void *resultBuffer,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(callerContext, alet, resultBuffer, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_get_throwing, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, void *resultBuffer,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(callerContext, alet, resultBuffer, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_consume, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, void *resultBuffer,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(callerContext, alet, resultBuffer, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_consume_throwing, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, void *resultBuffer,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(callerContext, alet, resultBuffer, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_ASYNC_LET(asyncLet_finish, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncLet *alet, void *resultBuffer,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(callerContext, alet, resultBuffer, resumeFn, callContext))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_initialize, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group, const Metadata *T), (group, T))
|
||||
|
||||
OVERRIDE_TASK_STATUS(taskGroup_attachChild, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group, AsyncTask *child),
|
||||
(group, child))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_destroy, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group), (group))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_wait_next_throwing, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swiftasync),
|
||||
swift::,
|
||||
(OpaqueValue *resultPointer,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
TaskGroup *_group,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext),
|
||||
(resultPointer, callerContext, _group, resumeFn,
|
||||
callContext))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_isEmpty, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group), (group))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_isCancelled, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group), (group))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_cancelAll, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group), (group))
|
||||
|
||||
OVERRIDE_TASK_GROUP(taskGroup_addPending, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group, bool unconditionally),
|
||||
(group, unconditionally))
|
||||
|
||||
|
||||
OVERRIDE_TASK_LOCAL(task_reportIllegalTaskLocalBindingWithinWithTaskGroup, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift), swift::,
|
||||
(const unsigned char *file, uintptr_t fileLength,
|
||||
bool fileIsASCII, uintptr_t line),
|
||||
(file, fileLength, fileIsASCII, line))
|
||||
|
||||
OVERRIDE_TASK_LOCAL(task_localValuePush, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::,
|
||||
(const HeapObject *key, OpaqueValue *value,
|
||||
const Metadata *valueType),
|
||||
(key, value, valueType))
|
||||
|
||||
OVERRIDE_TASK_LOCAL(task_localValueGet, OpaqueValue *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::,
|
||||
(const HeapObject *key),
|
||||
(key))
|
||||
|
||||
OVERRIDE_TASK_LOCAL(task_localValuePop, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, ,)
|
||||
|
||||
OVERRIDE_TASK_LOCAL(task_localsCopyTo, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::,
|
||||
(AsyncTask *target),
|
||||
(target))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_addStatusRecord, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskStatusRecord *newRecord), (newRecord))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_tryAddStatusRecord, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskStatusRecord *newRecord), (newRecord))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_removeStatusRecord, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskStatusRecord *record), (record))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_hasTaskGroupStatusRecord, bool,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, , )
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_attachChild, ChildTaskStatusRecord *,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (AsyncTask *child), (child))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_detachChild, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (ChildTaskStatusRecord *record), (record))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_cancel, void, SWIFT_EXPORT_FROM(swift_Concurrency),
|
||||
SWIFT_CC(swift), swift::, (AsyncTask *task), (task))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_cancel_group_child_tasks, void,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (TaskGroup *group), (group))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_escalate, JobPriority,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (AsyncTask *task, JobPriority newPriority),
|
||||
(task, newPriority))
|
||||
|
||||
OVERRIDE_TASK_STATUS(task_getNearestDeadline, NearestTaskDeadline,
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency), SWIFT_CC(swift),
|
||||
swift::, (AsyncTask *task), (task))
|
||||
|
||||
#undef OVERRIDE_ACTOR
|
||||
#undef OVERRIDE_TASK
|
||||
#undef OVERRIDE_ASYNC_LET
|
||||
#undef OVERRIDE_TASK_GROUP
|
||||
#undef OVERRIDE_TASK_LOCAL
|
||||
#undef OVERRIDE_TASK_STATUS
|
||||
@@ -1,227 +0,0 @@
|
||||
//===--- CompatibilityOverridesRuntime.def - Overrides Database -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines x-macros used for metaprogramming with the set of
|
||||
// compatibility override functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs)
|
||||
/// Provides information about an overridable function.
|
||||
/// - name is the name of the function, without any leading swift_ or
|
||||
/// namespace.
|
||||
/// - ret is the return type of the function.
|
||||
/// - attrs is the attributes, if any, applied to the function definition.
|
||||
/// - ccAttrs is the calling convention attributes, if any, applied to the
|
||||
/// function definition and corresponding typedefs
|
||||
/// - namespace is the namespace, if any, the function is in, including a
|
||||
/// trailing ::
|
||||
/// - typedArgs is the argument list, including types, surrounded by
|
||||
/// parentheses
|
||||
/// - namedArgs is the list of argument names, with no types, surrounded by
|
||||
/// parentheses
|
||||
///
|
||||
/// The entries are organized by group. A user may define OVERRIDE to get all
|
||||
/// entries, or define one or more of OVERRIDE_METADATALOOKUP, OVERRIDE_CASTING,
|
||||
/// OVERRIDE_OBJC, OVERRIDE_FOREIGN, OVERRIDE_PROTOCOLCONFORMANCE,
|
||||
/// and OVERRIDE_KEYPATH to get only those entries.
|
||||
|
||||
// NOTE: this file is used to build the definition of OverrideSection in
|
||||
// CompatibilityOverride.cpp, which is part of the ABI. Moving or removing
|
||||
// entries in this file will break the ABI. Additional entries can be added to
|
||||
// the end. ABI breaks or version-specific changes can be accommodated by
|
||||
// changing the name of the override section in that file.
|
||||
|
||||
#ifdef OVERRIDE
|
||||
# define OVERRIDE_METADATALOOKUP OVERRIDE
|
||||
# define OVERRIDE_CASTING OVERRIDE
|
||||
# define OVERRIDE_DYNAMICCASTING OVERRIDE
|
||||
# define OVERRIDE_OBJC OVERRIDE
|
||||
# define OVERRIDE_FOREIGN OVERRIDE
|
||||
# define OVERRIDE_PROTOCOLCONFORMANCE OVERRIDE
|
||||
# define OVERRIDE_KEYPATH OVERRIDE
|
||||
# define OVERRIDE_WITNESSTABLE OVERRIDE
|
||||
#else
|
||||
# ifndef OVERRIDE_METADATALOOKUP
|
||||
# define OVERRIDE_METADATALOOKUP(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_CASTING
|
||||
# define OVERRIDE_CASTING(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_DYNAMICCASTING
|
||||
# define OVERRIDE_DYNAMICCASTING(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_OBJC
|
||||
# define OVERRIDE_OBJC(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_FOREIGN
|
||||
# define OVERRIDE_FOREIGN(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_PROTOCOLCONFORMANCE
|
||||
# define OVERRIDE_PROTOCOLCONFORMANCE(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_KEYPATH
|
||||
# define OVERRIDE_KEYPATH(...)
|
||||
# endif
|
||||
# ifndef OVERRIDE_WITNESSTABLE
|
||||
# define OVERRIDE_WITNESSTABLE(...)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
OVERRIDE_DYNAMICCASTING(dynamicCast, bool, , , swift::,
|
||||
(OpaqueValue *dest, OpaqueValue *src,
|
||||
const Metadata *srcType,
|
||||
const Metadata *targetType,
|
||||
DynamicCastFlags flags),
|
||||
(dest, src, srcType, targetType, flags))
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastClass, const void *, , , swift::,
|
||||
(const void *object,
|
||||
const ClassMetadata *targetType),
|
||||
(object, targetType))
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastClassUnconditional, const void *, , , swift::,
|
||||
(const void *object,
|
||||
const ClassMetadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(object, targetType, file, line, column))
|
||||
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastUnknownClass, const void *, , , swift::,
|
||||
(const void *object, const Metadata *targetType),
|
||||
(object, targetType))
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastUnknownClassUnconditional, const void *, , , swift::,
|
||||
(const void *object, const Metadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(object, targetType, file, line, column))
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastMetatype, const Metadata *, , , swift::,
|
||||
(const Metadata *sourceType,
|
||||
const Metadata *targetType),
|
||||
(sourceType, targetType))
|
||||
|
||||
|
||||
OVERRIDE_CASTING(dynamicCastMetatypeUnconditional, const Metadata *, , , swift::,
|
||||
(const Metadata *sourceType,
|
||||
const Metadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(sourceType, targetType, file, line, column))
|
||||
|
||||
|
||||
OVERRIDE_FOREIGN(dynamicCastForeignClassMetatype, const ClassMetadata *, , , swift::,
|
||||
(const ClassMetadata *sourceType,
|
||||
const ClassMetadata *targetType),
|
||||
(sourceType, targetType))
|
||||
|
||||
|
||||
OVERRIDE_FOREIGN(dynamicCastForeignClassMetatypeUnconditional,
|
||||
const ClassMetadata *, , , swift::,
|
||||
(const ClassMetadata *sourceType,
|
||||
const ClassMetadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(sourceType, targetType, file, line, column))
|
||||
|
||||
|
||||
OVERRIDE_PROTOCOLCONFORMANCE(conformsToProtocol, const WitnessTable *, , , swift::,
|
||||
(const Metadata * const type,
|
||||
const ProtocolDescriptor *protocol),
|
||||
(type, protocol))
|
||||
|
||||
OVERRIDE_KEYPATH(getKeyPath, const HeapObject *, , , swift::,
|
||||
(const void *pattern, const void *arguments),
|
||||
(pattern, arguments))
|
||||
|
||||
OVERRIDE_METADATALOOKUP(getTypeByMangledNode, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::,
|
||||
(MetadataRequest request,
|
||||
Demangler &demangler,
|
||||
Demangle::NodePointer node,
|
||||
const void * const *arguments,
|
||||
SubstGenericParameterFn substGenericParam,
|
||||
SubstDependentWitnessTableFn substWitnessTable),
|
||||
(request, demangler, node, arguments, substGenericParam, substWitnessTable))
|
||||
OVERRIDE_METADATALOOKUP(getTypeByMangledName, TypeLookupErrorOr<TypeInfo>, , SWIFT_CC(swift), swift::,
|
||||
(MetadataRequest request,
|
||||
StringRef typeName,
|
||||
const void * const *arguments,
|
||||
SubstGenericParameterFn substGenericParam,
|
||||
SubstDependentWitnessTableFn substWitnessTable),
|
||||
(request, typeName, arguments, substGenericParam, substWitnessTable))
|
||||
|
||||
OVERRIDE_WITNESSTABLE(getAssociatedTypeWitnessSlow, MetadataResponse,
|
||||
SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::,
|
||||
(MetadataRequest request, WitnessTable *wtable,
|
||||
const Metadata *conformingType,
|
||||
const ProtocolRequirement *reqBase,
|
||||
const ProtocolRequirement *assocType),
|
||||
(request, wtable, conformingType, reqBase, assocType))
|
||||
|
||||
OVERRIDE_WITNESSTABLE(getAssociatedConformanceWitnessSlow, const WitnessTable *,
|
||||
SWIFT_RUNTIME_STDLIB_INTERNAL, SWIFT_CC(swift), swift::,
|
||||
(WitnessTable *wtable, const Metadata *conformingType,
|
||||
const Metadata *assocType,
|
||||
const ProtocolRequirement *reqBase,
|
||||
const ProtocolRequirement *assocConformance),
|
||||
(wtable, conformingType, assocType, reqBase,
|
||||
assocConformance))
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
|
||||
OVERRIDE_OBJC(dynamicCastObjCClass, const void *, , , swift::,
|
||||
(const void *object,
|
||||
const ClassMetadata *targetType),
|
||||
(object, targetType))
|
||||
|
||||
|
||||
OVERRIDE_OBJC(dynamicCastObjCClassUnconditional, const void *, , , swift::,
|
||||
(const void *object,
|
||||
const ClassMetadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(object, targetType, file, line, column))
|
||||
|
||||
OVERRIDE_OBJC(dynamicCastObjCClassMetatype, const ClassMetadata *, , , swift::,
|
||||
(const ClassMetadata *sourceType,
|
||||
const ClassMetadata *targetType),
|
||||
(sourceType, targetType))
|
||||
|
||||
|
||||
OVERRIDE_OBJC(dynamicCastObjCClassMetatypeUnconditional, const ClassMetadata *, , , swift::,
|
||||
(const ClassMetadata *sourceType, const ClassMetadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(sourceType, targetType, file, line, column))
|
||||
|
||||
|
||||
OVERRIDE_FOREIGN(dynamicCastForeignClass, const void *, , , swift::,
|
||||
(const void *object,
|
||||
const ForeignClassMetadata *targetType),
|
||||
(object, targetType))
|
||||
|
||||
|
||||
OVERRIDE_FOREIGN(dynamicCastForeignClassUnconditional, const void *, , , swift::,
|
||||
(const void *object, const ForeignClassMetadata *targetType,
|
||||
const char *file, unsigned line, unsigned column),
|
||||
(object, targetType, file, line, column))
|
||||
|
||||
#endif
|
||||
|
||||
#undef OVERRIDE_METADATALOOKUP
|
||||
#undef OVERRIDE_CASTING
|
||||
#undef OVERRIDE_DYNAMICCASTING
|
||||
#undef OVERRIDE_OBJC
|
||||
#undef OVERRIDE_FOREIGN
|
||||
#undef OVERRIDE_PROTOCOLCONFORMANCE
|
||||
#undef OVERRIDE_KEYPATH
|
||||
#undef OVERRIDE_WITNESSTABLE
|
||||
@@ -1,48 +0,0 @@
|
||||
#include "Runtime/Concurrency.h"
|
||||
#include "Concurrency/Actor.h"
|
||||
#include "Concurrency/Task.h"
|
||||
|
||||
#include "swift/Runtime/Atomic.h"
|
||||
#include "swift/Runtime/Casting.h"
|
||||
#include "Runtime/Threading/Mutex.h"
|
||||
#include "Runtime/Threading/Once.h"
|
||||
#include "Runtime/Threading/ThreadLocal.h"
|
||||
#include "Runtime/Threading/ThreadLocalStorage.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <new>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
namespace {
|
||||
|
||||
/// An extremely silly class which exists to make pointer
|
||||
/// default-initialization constexpr.
|
||||
template <class T> struct Pointer {
|
||||
T *Value;
|
||||
constexpr Pointer() : Value(nullptr) {}
|
||||
constexpr Pointer(T *value) : Value(value) {}
|
||||
operator T *() const { return Value; }
|
||||
T *operator->() const { return Value; }
|
||||
};
|
||||
|
||||
|
||||
class ActiveTask {
|
||||
/// A thread-local variable pointing to the active tracking
|
||||
/// information about the current thread, if any.
|
||||
static SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(Pointer<AsyncTask>, Value,
|
||||
SWIFT_CONCURRENCY_TASK_KEY);
|
||||
|
||||
public:
|
||||
static void set(AsyncTask *task) { Value.set(task); }
|
||||
static AsyncTask *get() { return Value.get(); }
|
||||
};
|
||||
|
||||
/// Define the thread-locals.
|
||||
SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(
|
||||
Pointer<AsyncTask>,
|
||||
ActiveTask::Value,
|
||||
SWIFT_CONCURRENCY_TASK_KEY);
|
||||
|
||||
|
||||
} // namespace
|
||||
@@ -1,19 +0,0 @@
|
||||
//===--- Error.cpp - Error handling support code --------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Concurrency/Error.h"
|
||||
|
||||
// swift::fatalError is not exported from libswiftCore and not shared, so define another
|
||||
// internal function instead.
|
||||
SWIFT_NORETURN void swift::swift_Concurrency_fatalError(uint32_t flags, const char *format, ...) {
|
||||
abort();
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "Concurrency/Task.h"
|
||||
|
||||
#include "Concurrency/TaskPrivate.h"
|
||||
#include "Concurrency/Error.h"
|
||||
#include "Overrides.h"
|
||||
|
||||
using namespace swift;
|
||||
using FutureFragment = AsyncTask::FutureFragment;
|
||||
using TaskGroup = swift::TaskGroup;
|
||||
|
||||
//===--- swift_task_future_wait -------------------------------------------===//
|
||||
|
||||
void SWIFT_CC(swiftasync) swift::swift56override_swift_task_future_wait(
|
||||
OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncTask *task,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext,
|
||||
TaskFutureWait_t *original) {
|
||||
original(result, callerContext, task, resumeFn, callContext);
|
||||
}
|
||||
|
||||
//===--- swift_task_future_wait_throwing ----------------------------------===//
|
||||
|
||||
void SWIFT_CC(swiftasync) swift::swift56override_swift_task_future_wait_throwing(
|
||||
OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncTask *task,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFunction,
|
||||
AsyncContext *callContext,
|
||||
TaskFutureWaitThrowing_t *original) {
|
||||
original(result, callerContext, task, resumeFunction, callContext);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
//===--- Overrides.cpp - Compat override table for Swift 5.6 runtime ------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides compatibility override hooks for Swift 5.6 runtimes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Overrides.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <mach-o/getsect.h>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
#define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
|
||||
Override_ ## name name;
|
||||
|
||||
struct RuntimeOverrideSection {
|
||||
uintptr_t version;
|
||||
#include "CompatibilityOverrideRuntime.def"
|
||||
};
|
||||
|
||||
struct ConcurrencyOverrideSection {
|
||||
uintptr_t version;
|
||||
#include "CompatibilityOverrideConcurrency.def"
|
||||
};
|
||||
|
||||
#undef OVERRIDE
|
||||
|
||||
ConcurrencyOverrideSection Swift56ConcurrencyOverrides
|
||||
__attribute__((used, section("__DATA,__s_async_hook"))) = {
|
||||
.version = 0,
|
||||
.task_future_wait = swift56override_swift_task_future_wait,
|
||||
.task_future_wait_throwing = swift56override_swift_task_future_wait_throwing,
|
||||
};
|
||||
|
||||
RuntimeOverrideSection Swift56RuntimeOverrides
|
||||
__attribute__((used, section("__DATA,__swift56_hooks"))) = {
|
||||
.version = 0,
|
||||
};
|
||||
|
||||
// Allow this library to get force-loaded by autolinking
|
||||
__attribute__((weak, visibility("hidden")))
|
||||
extern "C"
|
||||
char _swift_FORCE_LOAD_$_swiftCompatibility56 = 0;
|
||||
@@ -1,61 +0,0 @@
|
||||
//===--- Overrides.h - Compat overrides for Swift 5.6 runtime ------s------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides compatibility override hooks for Swift 5.6 runtimes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "CompatibilityOverride.h"
|
||||
|
||||
namespace swift {
|
||||
struct OpaqueValue;
|
||||
class AsyncContext;
|
||||
class AsyncTask;
|
||||
|
||||
using TaskFutureWait_t = SWIFT_CC(swiftasync) void(
|
||||
OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncTask *task,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext);
|
||||
|
||||
using TaskFutureWaitThrowing_t = SWIFT_CC(swiftasync) void(
|
||||
OpaqueValue *result,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *callerContext,
|
||||
AsyncTask *task,
|
||||
ThrowingTaskFutureWaitContinuationFunction *resumeFn,
|
||||
AsyncContext *callContext);
|
||||
|
||||
void SWIFT_CC(swiftasync) swift56override_swift_task_future_wait(
|
||||
OpaqueValue *,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *,
|
||||
AsyncTask *,
|
||||
TaskContinuationFunction *,
|
||||
AsyncContext *,
|
||||
TaskFutureWait_t *original);
|
||||
|
||||
void SWIFT_CC(swiftasync) swift56override_swift_task_future_wait_throwing(
|
||||
OpaqueValue *,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *,
|
||||
AsyncTask *,
|
||||
ThrowingTaskFutureWaitContinuationFunction *,
|
||||
AsyncContext *,
|
||||
TaskFutureWaitThrowing_t *original);
|
||||
|
||||
|
||||
using AsyncMainDrainQueue_t = SWIFT_CC(swift) void();
|
||||
|
||||
void SWIFT_CC(swift) swift56override_swift_asyncMainDrainQueue(AsyncMainDrainQueue_t *);
|
||||
|
||||
} // namespace swift
|
||||
@@ -1,45 +0,0 @@
|
||||
//===--- Actor.h - ABI structures for actors --------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift ABI describing actors.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_ACTOR_BACKDEPLOY56_H
|
||||
#define SWIFT_ABI_ACTOR_BACKDEPLOY56_H
|
||||
|
||||
#include "swift/ABI/HeapObject.h"
|
||||
#include "swift/ABI/MetadataValues.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// The default actor implementation. This is the layout of both
|
||||
/// the DefaultActor and NSDefaultActor classes.
|
||||
class alignas(Alignment_DefaultActor) DefaultActor : public HeapObject {
|
||||
public:
|
||||
// These constructors do not initialize the actor instance, and the
|
||||
// destructor does not destroy the actor instance; you must call
|
||||
// swift_defaultActor_{initialize,destroy} yourself.
|
||||
constexpr DefaultActor(const HeapMetadata *metadata)
|
||||
: HeapObject(metadata), PrivateData{} {}
|
||||
|
||||
constexpr DefaultActor(const HeapMetadata *metadata,
|
||||
InlineRefCounts::Immortal_t immortal)
|
||||
: HeapObject(metadata, immortal), PrivateData{} {}
|
||||
|
||||
void *PrivateData[NumWords_DefaultActor];
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_ABI_ACTOR_BACKDEPLOY56_H
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
//===--- AsyncLet.h - ABI structures for async let -00-----------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift ABI describing task groups.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H
|
||||
#define SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H
|
||||
|
||||
#include "Task.h"
|
||||
#include "swift/ABI/HeapObject.h"
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "swift/Basic/RelativePointer.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// Represents an in-flight `async let`, i.e. the Task that is computing the
|
||||
/// result of the async let, along with the awaited status and other metadata.
|
||||
class alignas(Alignment_AsyncLet) AsyncLet {
|
||||
public:
|
||||
// These constructors do not initialize the AsyncLet instance, and the
|
||||
// destructor does not destroy the AsyncLet instance; you must call
|
||||
// swift_asyncLet_{start,end} yourself.
|
||||
constexpr AsyncLet()
|
||||
: PrivateData{} {}
|
||||
|
||||
void *PrivateData[NumWords_AsyncLet];
|
||||
|
||||
// TODO: we could offer a "was awaited on" check here
|
||||
|
||||
/// Returns the child task that is associated with this async let.
|
||||
/// The tasks completion is used to fulfil the value represented by this async let.
|
||||
AsyncTask *getTask() const;
|
||||
|
||||
// The compiler preallocates a large fixed space for the `async let`, with the
|
||||
// intent that most of it be used for the child task context. The next two
|
||||
// methods return the address and size of that space.
|
||||
|
||||
/// Return a pointer to the unused space within the async let block.
|
||||
void *getPreallocatedSpace();
|
||||
|
||||
/// Return the size of the unused space within the async let block.
|
||||
static size_t getSizeOfPreallocatedSpace();
|
||||
|
||||
/// Was the task allocated out of the parent's allocator?
|
||||
bool didAllocateFromParentTask();
|
||||
|
||||
/// Flag that the task was allocated from the parent's allocator.
|
||||
void setDidAllocateFromParentTask(bool value = true);
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_ABI_TASK_ASYNC_LET_BACKDEPLOY56_H
|
||||
@@ -1,30 +0,0 @@
|
||||
//===--- Error.h - Swift Concurrency error helpers --------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Error handling support.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H
|
||||
#define SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H
|
||||
|
||||
#include "public/SwiftShims/Visibility.h"
|
||||
#include <cstdint>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace swift {
|
||||
|
||||
SWIFT_NORETURN void swift_Concurrency_fatalError(uint32_t flags, const char *format, ...);
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_CONCURRENCY_ERROR_BACKDEPLOY56_H
|
||||
@@ -1,221 +0,0 @@
|
||||
//===--- Executor.h - ABI structures for executors --------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift ABI describing executors.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H
|
||||
#define SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "Actor.h"
|
||||
#include "swift/ABI/HeapObject.h"
|
||||
#include "swift/Runtime/Casting.h"
|
||||
|
||||
namespace swift {
|
||||
class AsyncContext;
|
||||
class AsyncTask;
|
||||
class DefaultActor;
|
||||
class Job;
|
||||
class SerialExecutorWitnessTable;
|
||||
|
||||
/// An unmanaged reference to an executor.
|
||||
///
|
||||
/// This type corresponds to the type Optional<Builtin.Executor> in
|
||||
/// Swift. The representation of nil in Optional<Builtin.Executor>
|
||||
/// aligns with what this type calls the generic executor, so the
|
||||
/// notional subtype of this type which is never generic corresponds
|
||||
/// to the type Builtin.Executor.
|
||||
///
|
||||
/// An executor reference is divided into two pieces:
|
||||
///
|
||||
/// - The identity, which is just a (potentially ObjC) object
|
||||
/// reference; when this is null, the reference is generic.
|
||||
/// Equality of executor references is based solely on equality
|
||||
/// of identity.
|
||||
///
|
||||
/// - The implementation, which is an optional reference to a
|
||||
/// witness table for the SerialExecutor protocol. When this
|
||||
/// is null, but the identity is non-null, the reference is to
|
||||
/// a default actor. The low bits of the implementation pointer
|
||||
/// are reserved for the use of marking interesting properties
|
||||
/// about the executor's implementation. The runtime masks these
|
||||
/// bits off before accessing the witness table, so setting them
|
||||
/// in the future should back-deploy as long as the witness table
|
||||
/// reference is still present.
|
||||
class ExecutorRef {
|
||||
HeapObject *Identity; // Not necessarily Swift reference-countable
|
||||
uintptr_t Implementation;
|
||||
|
||||
// We future-proof the ABI here by masking the low bits off the
|
||||
// implementation pointer before using it as a witness table.
|
||||
enum: uintptr_t {
|
||||
WitnessTableMask = ~uintptr_t(alignof(void*) - 1)
|
||||
};
|
||||
|
||||
constexpr ExecutorRef(HeapObject *identity, uintptr_t implementation)
|
||||
: Identity(identity), Implementation(implementation) {}
|
||||
|
||||
public:
|
||||
/// A generic execution environment. When running in a generic
|
||||
/// environment, it's presumed to be okay to switch synchronously
|
||||
/// to an actor. As an executor request, this represents a request
|
||||
/// to drop whatever the current actor is.
|
||||
constexpr static ExecutorRef generic() {
|
||||
return ExecutorRef(nullptr, 0);
|
||||
}
|
||||
|
||||
/// Given a pointer to a default actor, return an executor reference
|
||||
/// for it.
|
||||
static ExecutorRef forDefaultActor(DefaultActor *actor) {
|
||||
assert(actor);
|
||||
return ExecutorRef(actor, 0);
|
||||
}
|
||||
|
||||
/// Given a pointer to a serial executor and its SerialExecutor
|
||||
/// conformance, return an executor reference for it.
|
||||
static ExecutorRef forOrdinary(HeapObject *identity,
|
||||
const SerialExecutorWitnessTable *witnessTable) {
|
||||
assert(identity);
|
||||
assert(witnessTable);
|
||||
return ExecutorRef(identity, reinterpret_cast<uintptr_t>(witnessTable));
|
||||
}
|
||||
|
||||
HeapObject *getIdentity() const {
|
||||
return Identity;
|
||||
}
|
||||
|
||||
/// Is this the generic executor reference?
|
||||
bool isGeneric() const {
|
||||
return Identity == 0;
|
||||
}
|
||||
|
||||
/// Is this a default-actor executor reference?
|
||||
bool isDefaultActor() const {
|
||||
return !isGeneric() && Implementation == 0;
|
||||
}
|
||||
DefaultActor *getDefaultActor() const {
|
||||
assert(isDefaultActor());
|
||||
return reinterpret_cast<DefaultActor*>(Identity);
|
||||
}
|
||||
|
||||
const SerialExecutorWitnessTable *getSerialExecutorWitnessTable() const {
|
||||
assert(!isGeneric() && !isDefaultActor());
|
||||
auto table = Implementation & WitnessTableMask;
|
||||
return reinterpret_cast<const SerialExecutorWitnessTable*>(table);
|
||||
}
|
||||
|
||||
/// Do we have to do any work to start running as the requested
|
||||
/// executor?
|
||||
bool mustSwitchToRun(ExecutorRef newExecutor) const {
|
||||
return Identity != newExecutor.Identity;
|
||||
}
|
||||
|
||||
/// Is this executor the main executor?
|
||||
bool isMainExecutor() const;
|
||||
|
||||
bool operator==(ExecutorRef other) const {
|
||||
return Identity == other.Identity;
|
||||
}
|
||||
bool operator!=(ExecutorRef other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
using JobInvokeFunction =
|
||||
SWIFT_CC(swiftasync)
|
||||
void (Job *);
|
||||
|
||||
using TaskContinuationFunction =
|
||||
SWIFT_CC(swiftasync)
|
||||
void (SWIFT_ASYNC_CONTEXT AsyncContext *);
|
||||
|
||||
using ThrowingTaskFutureWaitContinuationFunction =
|
||||
SWIFT_CC(swiftasync)
|
||||
void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *);
|
||||
|
||||
|
||||
template <class AsyncSignature>
|
||||
class AsyncFunctionPointer;
|
||||
template <class AsyncSignature>
|
||||
struct AsyncFunctionTypeImpl;
|
||||
|
||||
/// The abstract signature for an asynchronous function.
|
||||
template <class Sig, bool HasErrorResult>
|
||||
struct AsyncSignature;
|
||||
|
||||
template <class DirectResultTy, class... ArgTys, bool HasErrorResult>
|
||||
struct AsyncSignature<DirectResultTy(ArgTys...), HasErrorResult> {
|
||||
bool hasDirectResult = !std::is_same<DirectResultTy, void>::value;
|
||||
using DirectResultType = DirectResultTy;
|
||||
|
||||
bool hasErrorResult = HasErrorResult;
|
||||
|
||||
using FunctionPointer = AsyncFunctionPointer<AsyncSignature>;
|
||||
using FunctionType = typename AsyncFunctionTypeImpl<AsyncSignature>::type;
|
||||
};
|
||||
|
||||
/// A signature for a thin async function that takes no arguments
|
||||
/// and returns no results.
|
||||
using ThinNullaryAsyncSignature =
|
||||
AsyncSignature<void(), false>;
|
||||
|
||||
/// A signature for a thick async function that takes no formal
|
||||
/// arguments and returns no results.
|
||||
using ThickNullaryAsyncSignature =
|
||||
AsyncSignature<void(HeapObject*), false>;
|
||||
|
||||
/// A class which can be used to statically query whether a type
|
||||
/// is a specialization of AsyncSignature.
|
||||
template <class T>
|
||||
struct IsAsyncSignature {
|
||||
static const bool value = false;
|
||||
};
|
||||
template <class DirectResultTy, class... ArgTys, bool HasErrorResult>
|
||||
struct IsAsyncSignature<AsyncSignature<DirectResultTy(ArgTys...),
|
||||
HasErrorResult>> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class Signature>
|
||||
struct AsyncFunctionTypeImpl {
|
||||
static_assert(IsAsyncSignature<Signature>::value,
|
||||
"template argument is not an AsyncSignature");
|
||||
|
||||
// TODO: expand and include the arguments in the parameters.
|
||||
using type = TaskContinuationFunction;
|
||||
};
|
||||
|
||||
template <class Fn>
|
||||
using AsyncFunctionType = typename AsyncFunctionTypeImpl<Fn>::type;
|
||||
|
||||
/// A "function pointer" for an async function.
|
||||
///
|
||||
/// Eventually, this will always be signed with the data key
|
||||
/// using a type-specific discriminator.
|
||||
template <class AsyncSignature>
|
||||
class AsyncFunctionPointer {
|
||||
public:
|
||||
/// The function to run.
|
||||
RelativeDirectPointer<AsyncFunctionType<AsyncSignature>,
|
||||
/*nullable*/ false,
|
||||
int32_t> Function;
|
||||
|
||||
/// The expected size of the context.
|
||||
uint32_t ExpectedContextSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SWIFT_ABI_EXECUTOR_BACKDEPLOY56_H
|
||||
@@ -1,776 +0,0 @@
|
||||
//===--- Task.h - ABI structures for asynchronous tasks ---------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift ABI describing tasks.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_TASK_BACKDEPLOY56_H
|
||||
#define SWIFT_ABI_TASK_BACKDEPLOY56_H
|
||||
|
||||
#include "Executor.h"
|
||||
#include "swift/ABI/HeapObject.h"
|
||||
#include "swift/ABI/Metadata.h"
|
||||
#include "swift/ABI/MetadataValues.h" // Maybe replace?
|
||||
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "VoucherShims.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include <bitset>
|
||||
#include <queue>
|
||||
|
||||
namespace swift {
|
||||
class AsyncTask;
|
||||
class AsyncContext;
|
||||
class Job;
|
||||
struct OpaqueValue;
|
||||
struct SwiftError;
|
||||
class TaskStatusRecord;
|
||||
class TaskOptionRecord;
|
||||
class TaskGroup;
|
||||
|
||||
extern FullMetadata<DispatchClassMetadata> jobHeapMetadata;
|
||||
|
||||
/// A schedulable job.
|
||||
class alignas(2 * alignof(void*)) Job :
|
||||
// For async-let tasks, the refcount bits are initialized as "immortal"
|
||||
// because such a task is allocated with the parent's stack allocator.
|
||||
public HeapObject {
|
||||
public:
|
||||
// Indices into SchedulerPrivate, for use by the runtime.
|
||||
enum {
|
||||
/// The next waiting task link, an AsyncTask that is waiting on a future.
|
||||
NextWaitingTaskIndex = 0,
|
||||
|
||||
// The Dispatch object header is one pointer and two ints, which is
|
||||
// equivalent to three pointers on 32-bit and two pointers 64-bit. Set the
|
||||
// indexes accordingly so that DispatchLinkageIndex points to where Dispatch
|
||||
// expects.
|
||||
DispatchHasLongObjectHeader = sizeof(void *) == sizeof(int),
|
||||
|
||||
/// An opaque field used by Dispatch when enqueueing Jobs directly.
|
||||
DispatchLinkageIndex = DispatchHasLongObjectHeader ? 1 : 0,
|
||||
|
||||
/// The dispatch queue being used when enqueueing a Job directly with
|
||||
/// Dispatch.
|
||||
DispatchQueueIndex = DispatchHasLongObjectHeader ? 0 : 1,
|
||||
};
|
||||
|
||||
// Reserved for the use of the scheduler.
|
||||
void *SchedulerPrivate[2];
|
||||
|
||||
JobFlags Flags;
|
||||
|
||||
// Derived classes can use this to store a Job Id.
|
||||
uint32_t Id = 0;
|
||||
|
||||
/// The voucher associated with the job. Note: this is currently unused on
|
||||
/// non-Darwin platforms, with stub implementations of the functions for
|
||||
/// consistency.
|
||||
voucher_t Voucher = nullptr;
|
||||
|
||||
/// Reserved for future use.
|
||||
void *Reserved = nullptr;
|
||||
|
||||
// We use this union to avoid having to do a second indirect branch
|
||||
// when resuming an asynchronous task, which we expect will be the
|
||||
// common case.
|
||||
union {
|
||||
// A function to run a job that isn't an AsyncTask.
|
||||
JobInvokeFunction * __ptrauth_swift_job_invoke_function RunJob;
|
||||
|
||||
// A function to resume an AsyncTask.
|
||||
TaskContinuationFunction * __ptrauth_swift_task_resume_function ResumeTask;
|
||||
};
|
||||
|
||||
Job(JobFlags flags, JobInvokeFunction *invoke,
|
||||
const HeapMetadata *metadata = &jobHeapMetadata)
|
||||
: HeapObject(metadata), Flags(flags), RunJob(invoke) {
|
||||
Voucher = voucher_copy();
|
||||
assert(!isAsyncTask() && "wrong constructor for a task");
|
||||
}
|
||||
|
||||
Job(JobFlags flags, TaskContinuationFunction *invoke,
|
||||
const HeapMetadata *metadata = &jobHeapMetadata,
|
||||
bool captureCurrentVoucher = true)
|
||||
: HeapObject(metadata), Flags(flags), ResumeTask(invoke) {
|
||||
if (captureCurrentVoucher)
|
||||
Voucher = voucher_copy();
|
||||
assert(isAsyncTask() && "wrong constructor for a non-task job");
|
||||
}
|
||||
|
||||
/// Create a job with "immortal" reference counts.
|
||||
/// Used for async let tasks.
|
||||
Job(JobFlags flags, TaskContinuationFunction *invoke,
|
||||
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
|
||||
bool captureCurrentVoucher = true)
|
||||
: HeapObject(metadata, immortal), Flags(flags), ResumeTask(invoke) {
|
||||
if (captureCurrentVoucher)
|
||||
Voucher = voucher_copy();
|
||||
assert(isAsyncTask() && "wrong constructor for a non-task job");
|
||||
}
|
||||
|
||||
~Job() { swift_voucher_release(Voucher); }
|
||||
|
||||
bool isAsyncTask() const {
|
||||
return Flags.isAsyncTask();
|
||||
}
|
||||
|
||||
JobPriority getPriority() const {
|
||||
return Flags.getPriority();
|
||||
}
|
||||
|
||||
/// Given that we've fully established the job context in the current
|
||||
/// thread, actually start running this job. To establish the context
|
||||
/// correctly, call swift_job_run or runJobInExecutorContext.
|
||||
SWIFT_CC(swiftasync)
|
||||
void runInFullyEstablishedContext();
|
||||
|
||||
/// Given that we've fully established the job context in the
|
||||
/// current thread, and that the job is a simple (non-task) job,
|
||||
/// actually start running this job.
|
||||
SWIFT_CC(swiftasync)
|
||||
void runSimpleInFullyEstablishedContext() {
|
||||
return RunJob(this); // 'return' forces tail call
|
||||
}
|
||||
};
|
||||
|
||||
// The compiler will eventually assume these.
|
||||
#if SWIFT_POINTER_IS_8_BYTES
|
||||
static_assert(sizeof(Job) == 8 * sizeof(void*),
|
||||
"Job size is wrong");
|
||||
#else
|
||||
static_assert(sizeof(Job) == 10 * sizeof(void*),
|
||||
"Job size is wrong");
|
||||
#endif
|
||||
static_assert(alignof(Job) == 2 * alignof(void*),
|
||||
"Job alignment is wrong");
|
||||
|
||||
class NullaryContinuationJob : public Job {
|
||||
|
||||
private:
|
||||
AsyncTask* Task;
|
||||
AsyncTask* Continuation;
|
||||
|
||||
public:
|
||||
NullaryContinuationJob(AsyncTask *task, JobPriority priority, AsyncTask *continuation)
|
||||
: Job({JobKind::NullaryContinuation, priority}, &process),
|
||||
Task(task), Continuation(continuation) {}
|
||||
|
||||
SWIFT_CC(swiftasync)
|
||||
static void process(Job *job);
|
||||
|
||||
static bool classof(const Job *job) {
|
||||
return job->Flags.getKind() == JobKind::NullaryContinuation;
|
||||
}
|
||||
};
|
||||
|
||||
/// An asynchronous task. Tasks are the analogue of threads for
|
||||
/// asynchronous functions: that is, they are a persistent identity
|
||||
/// for the overall async computation.
|
||||
///
|
||||
/// ### Fragments
|
||||
/// An AsyncTask may have the following fragments:
|
||||
///
|
||||
/// +--------------------------+
|
||||
/// | childFragment? |
|
||||
/// | groupChildFragment? |
|
||||
/// | futureFragment? |*
|
||||
/// +--------------------------+
|
||||
///
|
||||
/// * The future fragment is dynamic in size, based on the future result type
|
||||
/// it can hold, and thus must be the *last* fragment.
|
||||
class AsyncTask : public Job {
|
||||
public:
|
||||
// On 32-bit targets, there is a word of tail padding remaining
|
||||
// in Job, and ResumeContext will fit into that, at offset 28.
|
||||
// Private then has offset 32.
|
||||
// On 64-bit targets, there is no tail padding in Job, and so
|
||||
// ResumeContext has offset 48. There is therefore another word
|
||||
// of reserved storage prior to Private (which needs to have
|
||||
// double-word alignment), which has offset 64.
|
||||
// We therefore converge and end up with 16 words of storage on
|
||||
// all platforms.
|
||||
|
||||
/// The context for resuming the job. When a task is scheduled
|
||||
/// as a job, the next continuation should be installed as the
|
||||
/// ResumeTask pointer in the job header, with this serving as
|
||||
/// the context pointer.
|
||||
///
|
||||
/// We can't protect the data in the context from being overwritten
|
||||
/// by attackers, but we can at least sign the context pointer to
|
||||
/// prevent it from being corrupted in flight.
|
||||
AsyncContext * __ptrauth_swift_task_resume_context ResumeContext;
|
||||
|
||||
#if SWIFT_POINTER_IS_8_BYTES
|
||||
void *Reserved64;
|
||||
#endif
|
||||
|
||||
struct PrivateStorage;
|
||||
|
||||
/// Private storage for the use of the runtime.
|
||||
struct alignas(2 * alignof(void*)) OpaquePrivateStorage {
|
||||
void *Storage[14];
|
||||
|
||||
/// Initialize this storage during the creation of a task.
|
||||
void initialize(JobPriority basePri);
|
||||
void initializeWithSlab(JobPriority basePri, void *slab,
|
||||
size_t slabCapacity);
|
||||
|
||||
/// React to the completion of the enclosing task's execution.
|
||||
void complete(AsyncTask *task);
|
||||
|
||||
/// React to the final destruction of the enclosing task.
|
||||
void destroy();
|
||||
|
||||
PrivateStorage &get();
|
||||
const PrivateStorage &get() const;
|
||||
};
|
||||
PrivateStorage &_private();
|
||||
const PrivateStorage &_private() const;
|
||||
|
||||
OpaquePrivateStorage Private;
|
||||
|
||||
/// Create a task.
|
||||
/// This does not initialize Private; callers must call
|
||||
/// Private.initialize separately.
|
||||
AsyncTask(const HeapMetadata *metadata, JobFlags flags,
|
||||
TaskContinuationFunction *run,
|
||||
AsyncContext *initialContext,
|
||||
bool captureCurrentVoucher)
|
||||
: Job(flags, run, metadata, captureCurrentVoucher),
|
||||
ResumeContext(initialContext) {
|
||||
assert(flags.isAsyncTask());
|
||||
setTaskId();
|
||||
}
|
||||
|
||||
/// Create a task with "immortal" reference counts.
|
||||
/// Used for async let tasks.
|
||||
/// This does not initialize Private; callers must call
|
||||
/// Private.initialize separately.
|
||||
AsyncTask(const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
|
||||
JobFlags flags,
|
||||
TaskContinuationFunction *run,
|
||||
AsyncContext *initialContext,
|
||||
bool captureCurrentVoucher)
|
||||
: Job(flags, run, metadata, immortal, captureCurrentVoucher),
|
||||
ResumeContext(initialContext) {
|
||||
assert(flags.isAsyncTask());
|
||||
setTaskId();
|
||||
}
|
||||
|
||||
~AsyncTask();
|
||||
|
||||
/// Set the task's ID field to the next task ID.
|
||||
void setTaskId();
|
||||
uint64_t getTaskId();
|
||||
|
||||
/// Get the task's resume function, for logging purposes only. This will
|
||||
/// attempt to see through the various adapters that are sometimes used, and
|
||||
/// failing that will return ResumeTask. The returned function pointer may
|
||||
/// have a different signature than ResumeTask, and it's only for identifying
|
||||
/// code associated with the task.
|
||||
const void *getResumeFunctionForLogging();
|
||||
|
||||
/// Given that we've already fully established the job context
|
||||
/// in the current thread, start running this task. To establish
|
||||
/// the job context correctly, call swift_job_run or
|
||||
/// runInExecutorContext.
|
||||
SWIFT_CC(swiftasync)
|
||||
void runInFullyEstablishedContext() {
|
||||
return ResumeTask(ResumeContext); // 'return' forces tail call
|
||||
}
|
||||
|
||||
/// A task can have the following states:
|
||||
/// * suspended: In this state, a task is considered not runnable
|
||||
/// * enqueued: In this state, a task is considered runnable
|
||||
/// * running on a thread
|
||||
/// * completed
|
||||
///
|
||||
/// The following state transitions are possible:
|
||||
/// suspended -> enqueued
|
||||
/// suspended -> running
|
||||
/// enqueued -> running
|
||||
/// running -> suspended
|
||||
/// running -> completed
|
||||
/// running -> enqueued
|
||||
///
|
||||
/// The 4 methods below are how a task switches from one state to another.
|
||||
|
||||
/// Flag that this task is now running. This can update
|
||||
/// the priority stored in the job flags if the priority has been
|
||||
/// escalated.
|
||||
///
|
||||
/// Generally this should be done immediately after updating
|
||||
/// ActiveTask.
|
||||
void flagAsRunning();
|
||||
|
||||
/// Flag that this task is now suspended.
|
||||
void flagAsSuspended();
|
||||
|
||||
/// Flag that the task is to be enqueued on the provided executor and actually
|
||||
/// enqueue it
|
||||
void flagAsAndEnqueueOnExecutor(ExecutorRef newExecutor);
|
||||
|
||||
/// Flag that this task is now completed. This normally does not do anything
|
||||
/// but can be used to locally insert logging.
|
||||
void flagAsCompleted();
|
||||
|
||||
/// Check whether this task has been cancelled.
|
||||
/// Checking this is, of course, inherently race-prone on its own.
|
||||
bool isCancelled() const;
|
||||
|
||||
// ==== Task Local Values ----------------------------------------------------
|
||||
|
||||
void localValuePush(const HeapObject *key,
|
||||
/* +1 */ OpaqueValue *value,
|
||||
const Metadata *valueType);
|
||||
|
||||
OpaqueValue *localValueGet(const HeapObject *key);
|
||||
|
||||
/// Returns true if storage has still more bindings.
|
||||
bool localValuePop();
|
||||
|
||||
// ==== Child Fragment -------------------------------------------------------
|
||||
|
||||
/// A fragment of an async task structure that happens to be a child task.
|
||||
class ChildFragment {
|
||||
/// The parent task of this task.
|
||||
AsyncTask *Parent;
|
||||
|
||||
// TODO: Document more how this is used from the `TaskGroupTaskStatusRecord`
|
||||
|
||||
/// The next task in the singly-linked list of child tasks.
|
||||
/// The list must start in a `ChildTaskStatusRecord` registered
|
||||
/// with the parent task.
|
||||
///
|
||||
/// Note that the parent task may have multiple such records.
|
||||
///
|
||||
/// WARNING: Access can only be performed by the `Parent` of this task.
|
||||
AsyncTask *NextChild = nullptr;
|
||||
|
||||
public:
|
||||
ChildFragment(AsyncTask *parent) : Parent(parent) {}
|
||||
|
||||
AsyncTask *getParent() const {
|
||||
return Parent;
|
||||
}
|
||||
|
||||
AsyncTask *getNextChild() const {
|
||||
return NextChild;
|
||||
}
|
||||
|
||||
/// Set the `NextChild` to to the passed task.
|
||||
///
|
||||
/// WARNING: This must ONLY be invoked from the parent of both
|
||||
/// (this and the passed-in) tasks for thread-safety reasons.
|
||||
void setNextChild(AsyncTask *task) {
|
||||
NextChild = task;
|
||||
}
|
||||
};
|
||||
|
||||
bool hasChildFragment() const {
|
||||
return Flags.task_isChildTask();
|
||||
}
|
||||
|
||||
ChildFragment *childFragment() {
|
||||
assert(hasChildFragment());
|
||||
|
||||
auto offset = reinterpret_cast<char*>(this);
|
||||
offset += sizeof(AsyncTask);
|
||||
|
||||
return reinterpret_cast<ChildFragment*>(offset);
|
||||
}
|
||||
|
||||
// ==== TaskGroup Child ------------------------------------------------------
|
||||
|
||||
/// A child task created by `group.add` is called a "task group child."
|
||||
/// Upon completion, in addition to the usual future notifying all its waiters,
|
||||
/// it must also `group->offer` itself to the group.
|
||||
///
|
||||
/// This signalling is necessary to correctly implement the group's `next()`.
|
||||
class GroupChildFragment {
|
||||
private:
|
||||
TaskGroup* Group;
|
||||
|
||||
friend class AsyncTask;
|
||||
friend class TaskGroup;
|
||||
|
||||
public:
|
||||
explicit GroupChildFragment(TaskGroup *group)
|
||||
: Group(group) {}
|
||||
|
||||
/// Return the group this task should offer into when it completes.
|
||||
TaskGroup* getGroup() {
|
||||
return Group;
|
||||
}
|
||||
};
|
||||
|
||||
// Checks if task is a child of a TaskGroup task.
|
||||
//
|
||||
// A child task that is a group child knows that it's parent is a group
|
||||
// and therefore may `groupOffer` to it upon completion.
|
||||
bool hasGroupChildFragment() const { return Flags.task_isGroupChildTask(); }
|
||||
|
||||
GroupChildFragment *groupChildFragment() {
|
||||
assert(hasGroupChildFragment());
|
||||
|
||||
auto offset = reinterpret_cast<char*>(this);
|
||||
offset += sizeof(AsyncTask);
|
||||
if (hasChildFragment())
|
||||
offset += sizeof(ChildFragment);
|
||||
|
||||
return reinterpret_cast<GroupChildFragment *>(offset);
|
||||
}
|
||||
|
||||
// ==== Future ---------------------------------------------------------------
|
||||
|
||||
class FutureFragment {
|
||||
public:
|
||||
/// Describes the status of the future.
|
||||
///
|
||||
/// Futures always begin in the "Executing" state, and will always
|
||||
/// make a single state change to either Success or Error.
|
||||
enum class Status : uintptr_t {
|
||||
/// The future is executing or ready to execute. The storage
|
||||
/// is not accessible.
|
||||
Executing = 0,
|
||||
|
||||
/// The future has completed with result (of type \c resultType).
|
||||
Success,
|
||||
|
||||
/// The future has completed by throwing an error (an \c Error
|
||||
/// existential).
|
||||
Error,
|
||||
};
|
||||
|
||||
/// An item within the wait queue, which includes the status and the
|
||||
/// head of the list of tasks.
|
||||
struct WaitQueueItem {
|
||||
/// Mask used for the low status bits in a wait queue item.
|
||||
static const uintptr_t statusMask = 0x03;
|
||||
|
||||
uintptr_t storage;
|
||||
|
||||
Status getStatus() const {
|
||||
return static_cast<Status>(storage & statusMask);
|
||||
}
|
||||
|
||||
AsyncTask *getTask() const {
|
||||
return reinterpret_cast<AsyncTask *>(storage & ~statusMask);
|
||||
}
|
||||
|
||||
static WaitQueueItem get(Status status, AsyncTask *task) {
|
||||
return WaitQueueItem{
|
||||
reinterpret_cast<uintptr_t>(task) | static_cast<uintptr_t>(status)};
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// Queue containing all of the tasks that are waiting in `get()`.
|
||||
///
|
||||
/// The low bits contain the status, the rest of the pointer is the
|
||||
/// AsyncTask.
|
||||
std::atomic<WaitQueueItem> waitQueue;
|
||||
|
||||
/// The type of the result that will be produced by the future.
|
||||
const Metadata *resultType;
|
||||
|
||||
SwiftError *error = nullptr;
|
||||
|
||||
// Trailing storage for the result itself. The storage will be
|
||||
// uninitialized, contain an instance of \c resultType.
|
||||
|
||||
friend class AsyncTask;
|
||||
|
||||
public:
|
||||
explicit FutureFragment(const Metadata *resultType)
|
||||
: waitQueue(WaitQueueItem::get(Status::Executing, nullptr)),
|
||||
resultType(resultType) { }
|
||||
|
||||
/// Destroy the storage associated with the future.
|
||||
void destroy();
|
||||
|
||||
const Metadata *getResultType() const {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
/// Retrieve a pointer to the storage of the result.
|
||||
OpaqueValue *getStoragePtr() {
|
||||
// The result storage starts at the first aligned offset following
|
||||
// the fragment header. This offset will agree with the abstract
|
||||
// calculation for `resultOffset` in the fragmentSize function below
|
||||
// because the entire task is aligned to at least the target
|
||||
// alignment (because it's aligned to MaxAlignment), which means
|
||||
// `this` must have the same value modulo that alignment as
|
||||
// `fragmentOffset` has in that function.
|
||||
char *fragmentAddr = reinterpret_cast<char *>(this);
|
||||
uintptr_t alignment = resultType->vw_alignment();
|
||||
char *resultAddr = fragmentAddr + sizeof(FutureFragment);
|
||||
uintptr_t unalignedResultAddrInt =
|
||||
reinterpret_cast<uintptr_t>(resultAddr);
|
||||
uintptr_t alignedResultAddrInt =
|
||||
(unalignedResultAddrInt + alignment - 1) & ~(alignment - 1);
|
||||
// We could just cast alignedResultAddrInt back to a pointer, but
|
||||
// doing pointer arithmetic is more strictly conformant and less
|
||||
// likely to annoy the optimizer.
|
||||
resultAddr += (alignedResultAddrInt - unalignedResultAddrInt);
|
||||
return reinterpret_cast<OpaqueValue *>(resultAddr);
|
||||
}
|
||||
|
||||
/// Retrieve the error.
|
||||
SwiftError *&getError() { return error; }
|
||||
|
||||
/// Determine the size of the future fragment given the result type
|
||||
/// of the future.
|
||||
static size_t fragmentSize(size_t fragmentOffset,
|
||||
const Metadata *resultType) {
|
||||
assert((fragmentOffset & (alignof(FutureFragment) - 1)) == 0);
|
||||
size_t alignment = resultType->vw_alignment();
|
||||
size_t resultOffset = fragmentOffset + sizeof(FutureFragment);
|
||||
resultOffset = (resultOffset + alignment - 1) & ~(alignment - 1);
|
||||
size_t endOffset = resultOffset + resultType->vw_size();
|
||||
return (endOffset - fragmentOffset);
|
||||
}
|
||||
};
|
||||
|
||||
bool isFuture() const { return Flags.task_isFuture(); }
|
||||
|
||||
FutureFragment *futureFragment() {
|
||||
assert(isFuture());
|
||||
auto offset = reinterpret_cast<char*>(this);
|
||||
offset += sizeof(AsyncTask);
|
||||
if (hasChildFragment())
|
||||
offset += sizeof(ChildFragment);
|
||||
if (hasGroupChildFragment())
|
||||
offset += sizeof(GroupChildFragment);
|
||||
|
||||
return reinterpret_cast<FutureFragment *>(offset);
|
||||
}
|
||||
|
||||
/// Wait for this future to complete.
|
||||
///
|
||||
/// \returns the status of the future. If this result is
|
||||
/// \c Executing, then \c waitingTask has been added to the
|
||||
/// wait queue and will be scheduled when the future completes. Otherwise,
|
||||
/// the future has completed and can be queried.
|
||||
/// The waiting task's async context will be initialized with the parameters if
|
||||
/// the current's task state is executing.
|
||||
FutureFragment::Status waitFuture(AsyncTask *waitingTask,
|
||||
AsyncContext *waitingTaskContext,
|
||||
TaskContinuationFunction *resumeFn,
|
||||
AsyncContext *callerContext,
|
||||
OpaqueValue *result);
|
||||
|
||||
/// Complete this future.
|
||||
///
|
||||
/// Upon completion, any waiting tasks will be scheduled on the given
|
||||
/// executor.
|
||||
void completeFuture(AsyncContext *context);
|
||||
|
||||
// ==== ----------------------------------------------------------------------
|
||||
|
||||
static bool classof(const Job *job) {
|
||||
return job->isAsyncTask();
|
||||
}
|
||||
|
||||
private:
|
||||
/// Access the next waiting task, which establishes a singly linked list of
|
||||
/// tasks that are waiting on a future.
|
||||
AsyncTask *&getNextWaitingTask() {
|
||||
return reinterpret_cast<AsyncTask *&>(
|
||||
SchedulerPrivate[NextWaitingTaskIndex]);
|
||||
}
|
||||
};
|
||||
|
||||
// The compiler will eventually assume these.
|
||||
static_assert(sizeof(AsyncTask) == NumWords_AsyncTask * sizeof(void*),
|
||||
"AsyncTask size is wrong");
|
||||
static_assert(alignof(AsyncTask) == 2 * alignof(void*),
|
||||
"AsyncTask alignment is wrong");
|
||||
// Libc hardcodes this offset to extract the TaskID
|
||||
static_assert(offsetof(AsyncTask, Id) == 4 * sizeof(void *) + 4,
|
||||
"AsyncTask::Id offset is wrong");
|
||||
|
||||
SWIFT_CC(swiftasync)
|
||||
inline void Job::runInFullyEstablishedContext() {
|
||||
if (auto task = dyn_cast<AsyncTask>(this))
|
||||
return task->runInFullyEstablishedContext(); // 'return' forces tail call
|
||||
else
|
||||
return runSimpleInFullyEstablishedContext(); // 'return' forces tail call
|
||||
}
|
||||
|
||||
// ==== ------------------------------------------------------------------------
|
||||
|
||||
/// An asynchronous context within a task. Generally contexts are
|
||||
/// allocated using the task-local stack alloc/dealloc operations, but
|
||||
/// there's no guarantee of that, and the ABI is designed to permit
|
||||
/// contexts to be allocated within their caller's frame.
|
||||
class alignas(MaximumAlignment) AsyncContext {
|
||||
public:
|
||||
/// The parent context.
|
||||
AsyncContext * __ptrauth_swift_async_context_parent Parent;
|
||||
|
||||
/// The function to call to resume running in the parent context.
|
||||
/// Generally this means a semantic return, but for some temporary
|
||||
/// translation contexts it might mean initiating a call.
|
||||
///
|
||||
/// Eventually, the actual type here will depend on the types
|
||||
/// which need to be passed to the parent. For now, arguments
|
||||
/// are always written into the context, and so the type is
|
||||
/// always the same.
|
||||
TaskContinuationFunction * __ptrauth_swift_async_context_resume
|
||||
ResumeParent;
|
||||
|
||||
AsyncContext(TaskContinuationFunction *resumeParent,
|
||||
AsyncContext *parent)
|
||||
: Parent(parent), ResumeParent(resumeParent) {}
|
||||
|
||||
AsyncContext(const AsyncContext &) = delete;
|
||||
AsyncContext &operator=(const AsyncContext &) = delete;
|
||||
|
||||
/// Perform a return from this context.
|
||||
///
|
||||
/// Generally this should be tail-called.
|
||||
SWIFT_CC(swiftasync)
|
||||
void resumeParent() {
|
||||
// TODO: destroy context before returning?
|
||||
// FIXME: force tail call
|
||||
return ResumeParent(Parent);
|
||||
}
|
||||
};
|
||||
|
||||
/// An async context that supports yielding.
|
||||
class YieldingAsyncContext : public AsyncContext {
|
||||
public:
|
||||
/// The function to call to temporarily resume running in the
|
||||
/// parent context. Generally this means a semantic yield.
|
||||
TaskContinuationFunction * __ptrauth_swift_async_context_yield
|
||||
YieldToParent;
|
||||
|
||||
YieldingAsyncContext(TaskContinuationFunction *resumeParent,
|
||||
TaskContinuationFunction *yieldToParent,
|
||||
AsyncContext *parent)
|
||||
: AsyncContext(resumeParent, parent),
|
||||
YieldToParent(yieldToParent) {}
|
||||
};
|
||||
|
||||
/// An async context that can be resumed as a continuation.
|
||||
class ContinuationAsyncContext : public AsyncContext {
|
||||
public:
|
||||
class FlagsType : public FlagSet<size_t> {
|
||||
public:
|
||||
enum {
|
||||
CanThrow = 0,
|
||||
IsExecutorSwitchForced = 1,
|
||||
};
|
||||
|
||||
explicit FlagsType(size_t bits) : FlagSet(bits) {}
|
||||
constexpr FlagsType() {}
|
||||
|
||||
/// Whether this is a throwing continuation.
|
||||
FLAGSET_DEFINE_FLAG_ACCESSORS(CanThrow,
|
||||
canThrow,
|
||||
setCanThrow)
|
||||
|
||||
/// See AsyncContinuationFlags::isExecutorSwitchForced().
|
||||
FLAGSET_DEFINE_FLAG_ACCESSORS(IsExecutorSwitchForced,
|
||||
isExecutorSwitchForced,
|
||||
setIsExecutorSwitchForced)
|
||||
};
|
||||
|
||||
/// Flags for the continuation. Not public ABI.
|
||||
FlagsType Flags;
|
||||
|
||||
/// An atomic object used to ensure that a continuation is not
|
||||
/// scheduled immediately during a resume if it hasn't yet been
|
||||
/// awaited by the function which set it up. Not public ABI.
|
||||
std::atomic<ContinuationStatus> AwaitSynchronization;
|
||||
|
||||
/// The error result value of the continuation.
|
||||
/// This should be null-initialized when setting up the continuation.
|
||||
/// Throwing resumers must overwrite this with a non-null value.
|
||||
/// Public ABI.
|
||||
SwiftError *ErrorResult;
|
||||
|
||||
/// A pointer to the normal result value of the continuation.
|
||||
/// Normal resumers must initialize this before resuming.
|
||||
/// Public ABI.
|
||||
OpaqueValue *NormalResult;
|
||||
|
||||
/// The executor that should be resumed to.
|
||||
/// Public ABI.
|
||||
ExecutorRef ResumeToExecutor;
|
||||
|
||||
void setErrorResult(SwiftError *error) {
|
||||
ErrorResult = error;
|
||||
}
|
||||
|
||||
bool isExecutorSwitchForced() const {
|
||||
return Flags.isExecutorSwitchForced();
|
||||
}
|
||||
};
|
||||
|
||||
/// An asynchronous context within a task that describes a general "Future".
|
||||
/// task.
|
||||
///
|
||||
/// This type matches the ABI of a function `<T> () async throws -> T`, which
|
||||
/// is the type used by `detach` and `Task.group.add` to create
|
||||
/// futures.
|
||||
class FutureAsyncContext : public AsyncContext {
|
||||
public:
|
||||
using AsyncContext::AsyncContext;
|
||||
};
|
||||
|
||||
/// This matches the ABI of a closure `() async throws -> ()`
|
||||
using AsyncVoidClosureEntryPoint =
|
||||
SWIFT_CC(swiftasync)
|
||||
void (SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *);
|
||||
|
||||
/// This matches the ABI of a closure `<T>() async throws -> T`
|
||||
using AsyncGenericClosureEntryPoint =
|
||||
SWIFT_CC(swiftasync)
|
||||
void(OpaqueValue *,
|
||||
SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT void *);
|
||||
|
||||
/// This matches the ABI of the resume function of a closure
|
||||
/// `() async throws -> ()`.
|
||||
using AsyncVoidClosureResumeEntryPoint =
|
||||
SWIFT_CC(swiftasync)
|
||||
void(SWIFT_ASYNC_CONTEXT AsyncContext *, SWIFT_CONTEXT SwiftError *);
|
||||
|
||||
class AsyncContextPrefix {
|
||||
public:
|
||||
// Async closure entry point adhering to compiler calling conv (e.g directly
|
||||
// passing the closure context instead of via the async context)
|
||||
AsyncVoidClosureEntryPoint *__ptrauth_swift_task_resume_function
|
||||
asyncEntryPoint;
|
||||
void *closureContext;
|
||||
SwiftError *errorResult;
|
||||
};
|
||||
|
||||
/// Storage that is allocated before the AsyncContext to be used by an adapter
|
||||
/// of Swift's async convention and the ResumeTask interface.
|
||||
class FutureAsyncContextPrefix {
|
||||
public:
|
||||
OpaqueValue *indirectResult;
|
||||
// Async closure entry point adhering to compiler calling conv (e.g directly
|
||||
// passing the closure context instead of via the async context)
|
||||
AsyncGenericClosureEntryPoint *__ptrauth_swift_task_resume_function
|
||||
asyncEntryPoint;
|
||||
void *closureContext;
|
||||
SwiftError *errorResult;
|
||||
};
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_ABI_TASK_BACKDEPLOY56_H
|
||||
@@ -1,71 +0,0 @@
|
||||
//===--- TaskPrivate.h - Concurrency library internal interface -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Internal functions for the concurrency library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H
|
||||
#define SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H
|
||||
|
||||
#include "Concurrency/Error.h"
|
||||
#include "Concurrency/Task.h"
|
||||
#include "swift/Runtime/Error.h"
|
||||
|
||||
namespace swift {
|
||||
namespace {
|
||||
|
||||
/// The layout of a context to call one of the following functions:
|
||||
///
|
||||
/// @_silgen_name("swift_task_future_wait")
|
||||
/// func _taskFutureGet<T>(_ task: Builtin.NativeObject) async -> T
|
||||
///
|
||||
/// @_silgen_name("swift_task_future_wait_throwing")
|
||||
/// func _taskFutureGetThrowing<T>(_ task: Builtin.NativeObject) async throws -> T
|
||||
///
|
||||
/// @_silgen_name("swift_asyncLet_wait")
|
||||
/// func _asyncLetGet<T>(_ task: Builtin.RawPointer) async -> T
|
||||
///
|
||||
/// @_silgen_name("swift_asyncLet_waitThrowing")
|
||||
/// func _asyncLetGetThrowing<T>(_ task: Builtin.RawPointer) async throws -> T
|
||||
///
|
||||
/// @_silgen_name("swift_taskGroup_wait_next_throwing")
|
||||
/// func _taskGroupWaitNext<T>(group: Builtin.RawPointer) async throws -> T?
|
||||
///
|
||||
class TaskFutureWaitAsyncContext : public AsyncContext {
|
||||
public:
|
||||
SwiftError *errorResult;
|
||||
|
||||
OpaqueValue *successResultPointer;
|
||||
|
||||
void fillWithSuccess(AsyncTask::FutureFragment *future) {
|
||||
fillWithSuccess(future->getStoragePtr(), future->getResultType(),
|
||||
successResultPointer);
|
||||
}
|
||||
void fillWithSuccess(OpaqueValue *src, const Metadata *successType,
|
||||
OpaqueValue *result) {
|
||||
successType->vw_initializeWithCopy(result, src);
|
||||
}
|
||||
|
||||
void fillWithError(AsyncTask::FutureFragment *future) {
|
||||
fillWithError(future->getError());
|
||||
}
|
||||
void fillWithError(SwiftError *error) {
|
||||
errorResult = error;
|
||||
swift_errorRetain(error);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_CONCURRENCY_TASKPRIVATE_BACKDEPLOY56_H
|
||||
@@ -1,166 +0,0 @@
|
||||
//===--- TaskStatusRecord.h - Structures to track task status --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift ABI describing "status records", the mechanism by which
|
||||
// tasks track dynamic information about their child tasks, custom
|
||||
// cancellation hooks, and other information which may need to be exposed
|
||||
// asynchronously outside of the task.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H
|
||||
#define SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H
|
||||
|
||||
#include "swift/ABI/MetadataValues.h"
|
||||
#include "Task.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// The abstract base class for all status records.
|
||||
///
|
||||
/// TaskStatusRecords are typically allocated on the stack (possibly
|
||||
/// in the task context), partially initialized, and then atomically
|
||||
/// added to the task with `swift_task_addTaskStatusRecord`. While
|
||||
/// registered with the task, a status record should only be
|
||||
/// modified in ways that respect the possibility of asynchronous
|
||||
/// access by a cancelling thread. In particular, the chain of
|
||||
/// status records must not be disturbed. When the task leaves
|
||||
/// the scope that requires the status record, the record can
|
||||
/// be unregistered from the task with `removeStatusRecord`,
|
||||
/// at which point the memory can be returned to the system.
|
||||
class TaskStatusRecord {
|
||||
public:
|
||||
TaskStatusRecordFlags Flags;
|
||||
TaskStatusRecord *Parent;
|
||||
|
||||
TaskStatusRecord(TaskStatusRecordKind kind,
|
||||
TaskStatusRecord *parent = nullptr)
|
||||
: Flags(kind) {
|
||||
resetParent(parent);
|
||||
}
|
||||
|
||||
TaskStatusRecord(const TaskStatusRecord &) = delete;
|
||||
TaskStatusRecord &operator=(const TaskStatusRecord &) = delete;
|
||||
|
||||
TaskStatusRecordKind getKind() const { return Flags.getKind(); }
|
||||
|
||||
TaskStatusRecord *getParent() const { return Parent; }
|
||||
|
||||
/// Change the parent of this unregistered status record to the
|
||||
/// given record.
|
||||
///
|
||||
/// This should be used when the record has been previously initialized
|
||||
/// without knowing what the true parent is. If we decide to cache
|
||||
/// important information (e.g. the earliest timeout) in the innermost
|
||||
/// status record, this is the method that should fill that in
|
||||
/// from the parent.
|
||||
void resetParent(TaskStatusRecord *newParent) {
|
||||
Parent = newParent;
|
||||
// TODO: cache
|
||||
}
|
||||
|
||||
/// Splice a record out of the status-record chain.
|
||||
///
|
||||
/// Unlike resetParent, this assumes that it's just removing one or
|
||||
/// more records from the chain and that there's no need to do any
|
||||
/// extra cache manipulation.
|
||||
void spliceParent(TaskStatusRecord *newParent) { Parent = newParent; }
|
||||
};
|
||||
|
||||
/// A deadline for the task. If this is reached, the task will be
|
||||
/// automatically cancelled. The deadline can also be queried and used
|
||||
/// in other ways.
|
||||
struct TaskDeadline {
|
||||
// FIXME: I don't really know what this should look like right now.
|
||||
// It's probably target-specific.
|
||||
uint64_t Value;
|
||||
|
||||
bool operator==(const TaskDeadline &other) const {
|
||||
return Value == other.Value;
|
||||
}
|
||||
bool operator<(const TaskDeadline &other) const {
|
||||
return Value < other.Value;
|
||||
}
|
||||
};
|
||||
|
||||
/// A status record which states that a task has one or
|
||||
/// more active child tasks.
|
||||
class ChildTaskStatusRecord : public TaskStatusRecord {
|
||||
AsyncTask *FirstChild;
|
||||
|
||||
public:
|
||||
ChildTaskStatusRecord(AsyncTask *child)
|
||||
: TaskStatusRecord(TaskStatusRecordKind::ChildTask), FirstChild(child) {}
|
||||
|
||||
ChildTaskStatusRecord(AsyncTask *child, TaskStatusRecordKind kind)
|
||||
: TaskStatusRecord(kind), FirstChild(child) {
|
||||
assert(kind == TaskStatusRecordKind::ChildTask);
|
||||
assert(!child->hasGroupChildFragment() &&
|
||||
"Group child tasks must be tracked in their respective "
|
||||
"TaskGroupTaskStatusRecord, and not as independent "
|
||||
"ChildTaskStatusRecord "
|
||||
"records.");
|
||||
}
|
||||
|
||||
/// Return the first child linked by this record. This may be null;
|
||||
/// if not, it (and all of its successors) are guaranteed to satisfy
|
||||
/// `isChildTask()`.
|
||||
AsyncTask *getFirstChild() const { return FirstChild; }
|
||||
|
||||
static AsyncTask *getNextChildTask(AsyncTask *task) {
|
||||
return task->childFragment()->getNextChild();
|
||||
}
|
||||
|
||||
using child_iterator = LinkedListIterator<AsyncTask, getNextChildTask>;
|
||||
llvm::iterator_range<child_iterator> children() const {
|
||||
return child_iterator::rangeBeginning(getFirstChild());
|
||||
}
|
||||
|
||||
static bool classof(const TaskStatusRecord *record) {
|
||||
return record->getKind() == TaskStatusRecordKind::ChildTask;
|
||||
}
|
||||
};
|
||||
|
||||
/// A cancellation record which states that a task has an arbitrary
|
||||
/// function that needs to be called if the task is cancelled.
|
||||
///
|
||||
/// The end of any call to the function will be ordered before the
|
||||
/// end of a call to unregister this record from the task. That is,
|
||||
/// code may call `removeStatusRecord` and freely
|
||||
/// assume after it returns that this function will not be
|
||||
/// subsequently used.
|
||||
class CancellationNotificationStatusRecord : public TaskStatusRecord {
|
||||
public:
|
||||
using FunctionType = SWIFT_CC(swift) void(SWIFT_CONTEXT void *);
|
||||
|
||||
private:
|
||||
FunctionType *__ptrauth_swift_cancellation_notification_function Function;
|
||||
void *Argument;
|
||||
|
||||
public:
|
||||
CancellationNotificationStatusRecord(FunctionType *fn, void *arg)
|
||||
: TaskStatusRecord(TaskStatusRecordKind::CancellationNotification),
|
||||
Function(fn), Argument(arg) {}
|
||||
|
||||
void run() { Function(Argument); }
|
||||
|
||||
static bool classof(const TaskStatusRecord *record) {
|
||||
return record->getKind() == TaskStatusRecordKind::CancellationNotification;
|
||||
}
|
||||
};
|
||||
|
||||
/// Return the current thread's active task reference.
|
||||
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
|
||||
AsyncTask *swift_task_getCurrent(void);
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_ABI_TASKSTATUS_BACKDEPLOY56_H
|
||||
@@ -1,103 +0,0 @@
|
||||
//===--- VoucherShims.h - Shims for OS vouchers --------------------*- C++ -*-//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2021 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Shims for interfacing with OS voucher calls.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H
|
||||
#define SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "swift/Runtime/Config.h"
|
||||
|
||||
// swift-corelibs-libdispatch has os/voucher_private.h but it doesn't work for
|
||||
// us yet, so only look for it on Apple platforms.
|
||||
#if __APPLE__ && __has_include(<os/voucher_private.h>)
|
||||
#define SWIFT_HAS_VOUCHER_HEADER 1
|
||||
#include <os/voucher_private.h>
|
||||
#endif
|
||||
|
||||
// A "dead" voucher pointer, indicating that a voucher has been removed from
|
||||
// a Job, distinct from a NULL voucher that could just mean no voucher was
|
||||
// present. This allows us to catch problems like adopting a voucher from the
|
||||
// same Job twice without restoring it.
|
||||
#define SWIFT_DEAD_VOUCHER ((voucher_t)-1)
|
||||
|
||||
// The OS has voucher support if it has the header or if it has ObjC interop.
|
||||
#if SWIFT_HAS_VOUCHER_HEADER || SWIFT_OBJC_INTEROP
|
||||
#define SWIFT_HAS_VOUCHERS 1
|
||||
#endif
|
||||
|
||||
#if SWIFT_HAS_VOUCHERS
|
||||
|
||||
#if SWIFT_HAS_VOUCHER_HEADER
|
||||
|
||||
#else
|
||||
|
||||
// If the header isn't available, declare the necessary calls here.
|
||||
|
||||
#include <os/object.h>
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
||||
OS_OBJECT_DECL_CLASS(voucher);
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
extern "C" voucher_t _Nullable voucher_copy(void);
|
||||
|
||||
// Consumes argument, returns retained value.
|
||||
extern "C" voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher);
|
||||
|
||||
#endif // __has_include(<os/voucher_private.h>)
|
||||
|
||||
static inline void swift_voucher_release(voucher_t _Nullable voucher) {
|
||||
// This NULL check isn't necessary, but NULL vouchers will be common, so
|
||||
// optimize for that.
|
||||
if (!voucher)
|
||||
return;
|
||||
if (voucher == SWIFT_DEAD_VOUCHER)
|
||||
return;
|
||||
os_release(voucher);
|
||||
}
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
// Declare some do-nothing stubs for OSes without voucher support.
|
||||
typedef void *voucher_t;
|
||||
static inline voucher_t _Nullable voucher_copy(void) { return nullptr; }
|
||||
static inline voucher_t _Nullable voucher_adopt(voucher_t _Nullable voucher) {
|
||||
return nullptr;
|
||||
}
|
||||
static inline void swift_voucher_release(voucher_t _Nullable voucher) {}
|
||||
#endif // __APPLE__
|
||||
|
||||
// Declare our own voucher_needs_adopt for when we don't get it from the SDK.
|
||||
// This declaration deliberately takes `void *` instead of `voucher_t`. When the
|
||||
// SDK provides one that takes `voucher_t`, then C++ overload resolution will
|
||||
// favor that one. When the SDK does not provide a declaration, then the call
|
||||
// site will invoke this stub instead.
|
||||
static inline bool voucher_needs_adopt(void * _Nullable voucher) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool swift_voucher_needs_adopt(voucher_t _Nullable voucher) {
|
||||
#if __APPLE__
|
||||
if (__builtin_available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *))
|
||||
return voucher_needs_adopt(voucher);
|
||||
return true;
|
||||
#else
|
||||
return voucher_needs_adopt(voucher);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SWIFT_CONCURRENCY_VOUCHERSHIMS_BACKDEPLOY56_H
|
||||
@@ -1,82 +0,0 @@
|
||||
//===--- Concurrency.h - Runtime interface for concurrency ------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The runtime interface for concurrency.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H
|
||||
|
||||
#include "Concurrency/Task.h"
|
||||
#include "Concurrency/TaskStatus.h"
|
||||
#include "Concurrency/AsyncLet.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
||||
|
||||
// Does the runtime use a cooperative global executor?
|
||||
#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
|
||||
#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 1
|
||||
#else
|
||||
#define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 0
|
||||
#endif
|
||||
|
||||
// Does the runtime integrate with libdispatch?
|
||||
#ifndef SWIFT_CONCURRENCY_ENABLE_DISPATCH
|
||||
#if SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR
|
||||
#define SWIFT_CONCURRENCY_ENABLE_DISPATCH 0
|
||||
#else
|
||||
#define SWIFT_CONCURRENCY_ENABLE_DISPATCH 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
class DefaultActor;
|
||||
class TaskOptionRecord;
|
||||
|
||||
struct SwiftError;
|
||||
|
||||
struct AsyncTaskAndContext {
|
||||
AsyncTask *Task;
|
||||
AsyncContext *InitialContext;
|
||||
};
|
||||
|
||||
/// This should have the same representation as an enum like this:
|
||||
/// enum NearestTaskDeadline {
|
||||
/// case none
|
||||
/// case alreadyCancelled
|
||||
/// case active(TaskDeadline)
|
||||
/// }
|
||||
/// TODO: decide what this interface should really be.
|
||||
struct NearestTaskDeadline {
|
||||
enum Kind : uint8_t {
|
||||
None,
|
||||
AlreadyCancelled,
|
||||
Active
|
||||
};
|
||||
|
||||
TaskDeadline Value;
|
||||
Kind ValueKind;
|
||||
};
|
||||
|
||||
|
||||
/// Caution: not all future-initializing functions actually throw, so
|
||||
/// this signature may be incorrect.
|
||||
using FutureAsyncSignature =
|
||||
AsyncSignature<void(void*), /*throws*/ true>;
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#endif // SWIFT_RUNTIME_CONCURRENCY_BACKDEPLOY56_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,157 +0,0 @@
|
||||
//===--- MutexPThread.h - Supports Mutex.h using PThreads -------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex, ConditionVariable, Read/Write lock, and Scoped lock implementations
|
||||
// using PThreads.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <os/lock.h>
|
||||
#define HAS_OS_UNFAIR_LOCK 1
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
|
||||
typedef pthread_cond_t ConditionHandle;
|
||||
typedef pthread_mutex_t ConditionMutexHandle;
|
||||
typedef pthread_rwlock_t ReadWriteLockHandle;
|
||||
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
typedef os_unfair_lock MutexHandle;
|
||||
#else
|
||||
typedef pthread_mutex_t MutexHandle;
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__HAIKU__) || defined(__wasi__)
|
||||
// At the moment CYGWIN pthreads implementation doesn't support the use of
|
||||
// constexpr for static allocation versions. The way they define things
|
||||
// results in a reinterpret_cast which violates constexpr.
|
||||
// WASI currently doesn't support threading/locking at all.
|
||||
#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 0
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 0
|
||||
#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 0
|
||||
#else
|
||||
#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1
|
||||
#endif
|
||||
|
||||
/// PThread low-level implementation that supports ConditionVariable
|
||||
/// found in Mutex.h
|
||||
///
|
||||
/// See ConditionVariable
|
||||
struct ConditionPlatformHelper {
|
||||
#if SWIFT_CONDITION_SUPPORTS_CONSTEXPR
|
||||
static constexpr
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
ConditionHandle
|
||||
staticInit() {
|
||||
return PTHREAD_COND_INITIALIZER;
|
||||
};
|
||||
static void init(ConditionHandle &condition);
|
||||
static void destroy(ConditionHandle &condition);
|
||||
static void notifyOne(ConditionHandle &condition);
|
||||
static void notifyAll(ConditionHandle &condition);
|
||||
static void wait(ConditionHandle &condition, ConditionMutexHandle &mutex);
|
||||
};
|
||||
|
||||
/// PThread low-level implementation that supports Mutex
|
||||
/// found in Mutex.h
|
||||
///
|
||||
/// See Mutex
|
||||
struct MutexPlatformHelper {
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
static constexpr
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
ConditionMutexHandle
|
||||
conditionStaticInit() {
|
||||
return PTHREAD_MUTEX_INITIALIZER;
|
||||
};
|
||||
#if SWIFT_MUTEX_SUPPORTS_CONSTEXPR
|
||||
static constexpr
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
MutexHandle
|
||||
staticInit() {
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
return OS_UNFAIR_LOCK_INIT;
|
||||
#else
|
||||
return PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
}
|
||||
static void init(ConditionMutexHandle &mutex, bool checked = false);
|
||||
static void destroy(ConditionMutexHandle &mutex);
|
||||
static void lock(ConditionMutexHandle &mutex);
|
||||
static void unlock(ConditionMutexHandle &mutex);
|
||||
static bool try_lock(ConditionMutexHandle &mutex);
|
||||
|
||||
// The ConditionMutexHandle versions handle everything on-Apple platforms.
|
||||
#if HAS_OS_UNFAIR_LOCK
|
||||
|
||||
static void init(MutexHandle &mutex, bool checked = false);
|
||||
static void destroy(MutexHandle &mutex);
|
||||
static void lock(MutexHandle &mutex);
|
||||
static void unlock(MutexHandle &mutex);
|
||||
static bool try_lock(MutexHandle &mutex);
|
||||
|
||||
// os_unfair_lock always checks for errors, so just call through.
|
||||
static void unsafeLock(MutexHandle &mutex) { lock(mutex); }
|
||||
static void unsafeUnlock(MutexHandle &mutex) { unlock(mutex); }
|
||||
#endif
|
||||
|
||||
// The unsafe versions don't do error checking.
|
||||
static void unsafeLock(ConditionMutexHandle &mutex) {
|
||||
(void)pthread_mutex_lock(&mutex);
|
||||
}
|
||||
static void unsafeUnlock(ConditionMutexHandle &mutex) {
|
||||
(void)pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
};
|
||||
|
||||
/// PThread low-level implementation that supports ReadWriteLock
|
||||
/// found in Mutex.h
|
||||
///
|
||||
/// See ReadWriteLock
|
||||
struct ReadWriteLockPlatformHelper {
|
||||
#if SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR
|
||||
static constexpr
|
||||
#else
|
||||
static
|
||||
#endif
|
||||
ReadWriteLockHandle
|
||||
staticInit() {
|
||||
return PTHREAD_RWLOCK_INITIALIZER;
|
||||
};
|
||||
|
||||
static void init(ReadWriteLockHandle &rwlock);
|
||||
static void destroy(ReadWriteLockHandle &rwlock);
|
||||
static void readLock(ReadWriteLockHandle &rwlock);
|
||||
static bool try_readLock(ReadWriteLockHandle &rwlock);
|
||||
static void readUnlock(ReadWriteLockHandle &rwlock);
|
||||
static void writeLock(ReadWriteLockHandle &rwlock);
|
||||
static bool try_writeLock(ReadWriteLockHandle &rwlock);
|
||||
static void writeUnlock(ReadWriteLockHandle &rwlock);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SWIFT_RUNTIME_MUTEX_PHTREAD_BACKDEPLOY56_H
|
||||
@@ -1,74 +0,0 @@
|
||||
//===--- MutexSingleThreaded.h - --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// No-op implementation of locks for single-threaded environments.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "swift/Runtime/Debug.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
typedef void* ConditionHandle;
|
||||
typedef void* ConditionMutexHandle;
|
||||
typedef void* MutexHandle;
|
||||
typedef void* ReadWriteLockHandle;
|
||||
|
||||
#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1
|
||||
|
||||
struct ConditionPlatformHelper {
|
||||
static constexpr ConditionHandle staticInit() {
|
||||
return nullptr;
|
||||
};
|
||||
static void init(ConditionHandle &condition) {}
|
||||
static void destroy(ConditionHandle &condition) {}
|
||||
static void notifyOne(ConditionHandle &condition) {}
|
||||
static void notifyAll(ConditionHandle &condition) {}
|
||||
static void wait(ConditionHandle &condition, MutexHandle &mutex) {
|
||||
fatalError(0, "single-threaded runtime cannot wait for condition");
|
||||
}
|
||||
};
|
||||
|
||||
struct MutexPlatformHelper {
|
||||
static constexpr MutexHandle staticInit() { return nullptr; }
|
||||
static constexpr ConditionMutexHandle conditionStaticInit() {
|
||||
return nullptr;
|
||||
}
|
||||
static void init(MutexHandle &mutex, bool checked = false) {}
|
||||
static void destroy(MutexHandle &mutex) {}
|
||||
static void lock(MutexHandle &mutex) {}
|
||||
static void unlock(MutexHandle &mutex) {}
|
||||
static bool try_lock(MutexHandle &mutex) { return true; }
|
||||
static void unsafeLock(MutexHandle &mutex) {}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {}
|
||||
};
|
||||
|
||||
struct ReadWriteLockPlatformHelper {
|
||||
static constexpr ReadWriteLockHandle staticInit() { return nullptr; }
|
||||
static void init(ReadWriteLockHandle &rwlock) {}
|
||||
static void destroy(ReadWriteLockHandle &rwlock) {}
|
||||
static void readLock(ReadWriteLockHandle &rwlock) {}
|
||||
static bool try_readLock(ReadWriteLockHandle &rwlock) { return true; }
|
||||
static void readUnlock(ReadWriteLockHandle &rwlock) {}
|
||||
static void writeLock(ReadWriteLockHandle &rwlock) {}
|
||||
static bool try_writeLock(ReadWriteLockHandle &rwlock) { return true; }
|
||||
static void writeUnlock(ReadWriteLockHandle &rwlock) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SWIFT_RUNTIME_MUTEX_SINGLE_THREADED_BACKDEPLOY56_H
|
||||
@@ -1,101 +0,0 @@
|
||||
//===--- MutexWin32.h - -----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Mutex, ConditionVariable, Read/Write lock, and Scoped lock implementations
|
||||
// using Windows Slim Reader/Writer Locks and Conditional Variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
namespace swift {
|
||||
|
||||
typedef CONDITION_VARIABLE ConditionHandle;
|
||||
typedef SRWLOCK ConditionMutexHandle;
|
||||
typedef SRWLOCK MutexHandle;
|
||||
typedef SRWLOCK ReadWriteLockHandle;
|
||||
|
||||
#define SWIFT_CONDITION_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_MUTEX_SUPPORTS_CONSTEXPR 1
|
||||
#define SWIFT_READWRITELOCK_SUPPORTS_CONSTEXPR 1
|
||||
|
||||
struct ConditionPlatformHelper {
|
||||
static constexpr ConditionHandle staticInit() {
|
||||
return CONDITION_VARIABLE_INIT;
|
||||
};
|
||||
static void init(ConditionHandle &condition) {
|
||||
InitializeConditionVariable(&condition);
|
||||
}
|
||||
static void destroy(ConditionHandle &condition) {}
|
||||
static void notifyOne(ConditionHandle &condition) {
|
||||
WakeConditionVariable(&condition);
|
||||
}
|
||||
static void notifyAll(ConditionHandle &condition) {
|
||||
WakeAllConditionVariable(&condition);
|
||||
}
|
||||
static void wait(ConditionHandle &condition, MutexHandle &mutex);
|
||||
};
|
||||
|
||||
struct MutexPlatformHelper {
|
||||
static constexpr MutexHandle staticInit() { return SRWLOCK_INIT; }
|
||||
static constexpr ConditionMutexHandle conditionStaticInit() {
|
||||
return SRWLOCK_INIT;
|
||||
}
|
||||
static void init(MutexHandle &mutex, bool checked = false) {
|
||||
InitializeSRWLock(&mutex);
|
||||
}
|
||||
static void destroy(MutexHandle &mutex) {}
|
||||
static void lock(MutexHandle &mutex) { AcquireSRWLockExclusive(&mutex); }
|
||||
static void unlock(MutexHandle &mutex) { ReleaseSRWLockExclusive(&mutex); }
|
||||
static bool try_lock(MutexHandle &mutex) {
|
||||
return TryAcquireSRWLockExclusive(&mutex) != 0;
|
||||
}
|
||||
// The unsafe versions don't do error checking.
|
||||
static void unsafeLock(MutexHandle &mutex) {
|
||||
AcquireSRWLockExclusive(&mutex);
|
||||
}
|
||||
static void unsafeUnlock(MutexHandle &mutex) {
|
||||
ReleaseSRWLockExclusive(&mutex);
|
||||
}
|
||||
};
|
||||
|
||||
struct ReadWriteLockPlatformHelper {
|
||||
static constexpr ReadWriteLockHandle staticInit() { return SRWLOCK_INIT; }
|
||||
static void init(ReadWriteLockHandle &rwlock) { InitializeSRWLock(&rwlock); }
|
||||
static void destroy(ReadWriteLockHandle &rwlock) {}
|
||||
static void readLock(ReadWriteLockHandle &rwlock) {
|
||||
AcquireSRWLockShared(&rwlock);
|
||||
}
|
||||
static bool try_readLock(ReadWriteLockHandle &rwlock) {
|
||||
return TryAcquireSRWLockShared(&rwlock) != 0;
|
||||
}
|
||||
static void readUnlock(ReadWriteLockHandle &rwlock) {
|
||||
ReleaseSRWLockShared(&rwlock);
|
||||
}
|
||||
static void writeLock(ReadWriteLockHandle &rwlock) {
|
||||
AcquireSRWLockExclusive(&rwlock);
|
||||
}
|
||||
static bool try_writeLock(ReadWriteLockHandle &rwlock) {
|
||||
return TryAcquireSRWLockExclusive(&rwlock) != 0;
|
||||
}
|
||||
static void writeUnlock(ReadWriteLockHandle &rwlock) {
|
||||
ReleaseSRWLockExclusive(&rwlock);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // SWIFT_RUNTIME_MUTEX_WIN32_BACKDEPLOY56_H
|
||||
@@ -1,54 +0,0 @@
|
||||
//===--- Once.h - Runtime support for lazy initialization -------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Swift runtime functions in support of lazy initialization.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H
|
||||
|
||||
#include "swift/Runtime/HeapObject.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace swift {
|
||||
|
||||
#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME
|
||||
|
||||
typedef bool swift_once_t;
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
// On OS X and iOS, swift_once_t matches dispatch_once_t.
|
||||
typedef long swift_once_t;
|
||||
|
||||
#elif defined(__CYGWIN__)
|
||||
|
||||
// On Cygwin, std::once_flag can not be used because it is larger than the
|
||||
// platform word.
|
||||
typedef uintptr_t swift_once_t;
|
||||
#else
|
||||
|
||||
// On other platforms swift_once_t is std::once_flag
|
||||
typedef std::once_flag swift_once_t;
|
||||
|
||||
#endif
|
||||
|
||||
/// Runs the given function with the given context argument exactly once.
|
||||
/// The predicate argument must point to a global or static variable of static
|
||||
/// extent of type swift_once_t.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
void swift_once(swift_once_t *predicate, void (*fn)(void *), void *context);
|
||||
|
||||
}
|
||||
|
||||
#endif // SWIFT_RUNTIME_ONCE_BACKDEPLOY56_H
|
||||
@@ -1,176 +0,0 @@
|
||||
//===--- ThreadLocal.h - Thread-local storage -------------------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declarations and macros for working with thread-local storage in the
|
||||
// Swift runtime.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H
|
||||
|
||||
#include <type_traits>
|
||||
#include "ThreadLocalStorage.h"
|
||||
|
||||
/// SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL - Does the current configuration
|
||||
/// allow the use of SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL?
|
||||
#if defined(__APPLE__)
|
||||
// The pthread TLS APIs work better than C++ TLS on Apple platforms.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
|
||||
#elif defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
|
||||
// We define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL to nothing in this
|
||||
// configuration and just use a global variable, so this is okay.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
|
||||
#elif __has_feature(tls)
|
||||
// If __has_feature reports that TLS is available, use it.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 1
|
||||
#elif !defined(__clang__)
|
||||
// If we're not using Clang, assume that __has_feature is unreliable
|
||||
// and that we can safely use TLS.
|
||||
#else
|
||||
// Otherwise we can't use TLS and have to fall back on something else.
|
||||
#define SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL 0
|
||||
#endif
|
||||
|
||||
/// SWIFT_RUNTIME_THREAD_LOCAL - Declare that something is a
|
||||
/// thread-local variable in the runtime.
|
||||
#if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
|
||||
// In a single-threaded runtime, thread-locals are global.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL
|
||||
#elif defined(__GNUC__)
|
||||
// In GCC-compatible compilers, we prefer __thread because it's understood
|
||||
// to guarantee a constant initializer, which permits more efficient access
|
||||
// patterns.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL __thread
|
||||
#else
|
||||
// Otherwise, just fall back on the standard C++ feature.
|
||||
#define SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL thread_local
|
||||
#endif
|
||||
|
||||
// Implementation of SWIFT_RUNTIME_DECLARE_THREAD_LOCAL
|
||||
#if !SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
#include <pthread.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
namespace swift {
|
||||
// Validate a type stored in thread-local storage, using static asserts. Such
|
||||
// types must fit in a pointer and be trivially copyable/destructible.
|
||||
#define VALIDATE_THREAD_LOCAL_TYPE(T) \
|
||||
static_assert(sizeof(T) <= sizeof(void *), \
|
||||
"cannot store more than a pointer"); \
|
||||
static_assert(std::is_trivially_copyable<T>::value, \
|
||||
"ThreadLocal values must be trivially copyable"); \
|
||||
static_assert(std::is_trivially_destructible<T>::value, \
|
||||
"ThreadLocal cleanup is not supported, stored types must be " \
|
||||
"trivially destructible");
|
||||
|
||||
// A wrapper class for thread-local storage.
|
||||
//
|
||||
// - On platforms that report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
// above, an object of this type is declared with
|
||||
// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL. This makes the object
|
||||
// itself thread-local, and no internal support is required.
|
||||
//
|
||||
// Note that this includes platforms that set
|
||||
// SWIFT_STDLIB_SINGLE_THREADED_RUNTIME, for which
|
||||
// SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL is empty;
|
||||
// thread-local declarations then create an ordinary global.
|
||||
//
|
||||
// - On platforms that don't report SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL,
|
||||
// we have to simulate thread-local storage. Fortunately, all of
|
||||
// these platforms (at least for now) support pthread_getspecific.
|
||||
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
template <class T>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
T value;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() { return value; }
|
||||
|
||||
void set(T newValue) { value = newValue; }
|
||||
};
|
||||
#else
|
||||
// A wrapper around a pthread_key_t that is lazily initialized using
|
||||
// dispatch_once.
|
||||
class ThreadLocalKey {
|
||||
// We rely on the zero-initialization of objects with static storage
|
||||
// duration.
|
||||
dispatch_once_t once;
|
||||
pthread_key_t key;
|
||||
|
||||
public:
|
||||
pthread_key_t getKey() {
|
||||
dispatch_once_f(&once, &key, [](void *ctx) {
|
||||
pthread_key_create(reinterpret_cast<pthread_key_t *>(ctx), nullptr);
|
||||
});
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
// A type representing a constant pthread_key_t, for use on platforms that
|
||||
// provide reserved keys.
|
||||
template <pthread_key_t constantKey>
|
||||
class ConstantThreadLocalKey {
|
||||
public:
|
||||
pthread_key_t getKey() { return constantKey; }
|
||||
};
|
||||
|
||||
template <class T, class Key>
|
||||
class ThreadLocal {
|
||||
VALIDATE_THREAD_LOCAL_TYPE(T)
|
||||
|
||||
Key key;
|
||||
|
||||
public:
|
||||
constexpr ThreadLocal() {}
|
||||
|
||||
T get() {
|
||||
void *storedValue = SWIFT_THREAD_GETSPECIFIC(key.getKey());
|
||||
T value;
|
||||
memcpy(&value, &storedValue, sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
void set(T newValue) {
|
||||
void *storedValue;
|
||||
memcpy(&storedValue, &newValue, sizeof(T));
|
||||
SWIFT_THREAD_SETSPECIFIC(key.getKey(), storedValue);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
/// SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME) - Declare a variable
|
||||
/// to be a thread-local variable. The declaration must have static
|
||||
/// storage duration; it may be prefixed with "static".
|
||||
///
|
||||
/// Because of the fallback path, the default-initialization of the
|
||||
/// type must be equivalent to a bitwise zero-initialization, and the
|
||||
/// type must be small and trivially copyable and destructible.
|
||||
#if SWIFT_RUNTIME_SUPPORTS_THREAD_LOCAL
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
SWIFT_RUNTIME_ATTRIBUTE_THREAD_LOCAL swift::ThreadLocal<TYPE> NAME
|
||||
#elif SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
swift::ThreadLocal<TYPE, ConstantThreadLocalKey<KEY>> NAME
|
||||
#else
|
||||
#define SWIFT_RUNTIME_DECLARE_THREAD_LOCAL(TYPE, NAME, KEY) \
|
||||
swift::ThreadLocal<TYPE, ThreadLocalKey> NAME
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_RUNTIME_THREADLOCAL_BACKDEPLOY56_H
|
||||
@@ -1,128 +0,0 @@
|
||||
//===--- ThreadLocalStorage.h - Thread-local storage interface. --*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H
|
||||
#define SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H
|
||||
|
||||
#include "swift/Runtime/Config.h"
|
||||
|
||||
// Depending on the target, we may be able to use dedicated TSD keys or
|
||||
// thread_local variables. When dedicated TSD keys aren't available,
|
||||
// wrap the target's API for thread-local data for things that don't want
|
||||
// to use thread_local.
|
||||
|
||||
// On Apple platforms, we have dedicated TSD keys.
|
||||
#if defined(__APPLE__)
|
||||
# define SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC 1
|
||||
#endif
|
||||
|
||||
#if SWIFT_TLS_HAS_RESERVED_PTHREAD_SPECIFIC
|
||||
// Use reserved TSD keys.
|
||||
# if __has_include(<pthread/tsd_private.h>)
|
||||
# include <pthread/tsd_private.h>
|
||||
# else
|
||||
// We still need to use the SPI for setting the destructor, so declare it here.
|
||||
extern "C" int pthread_key_init_np(int key, void (*destructor)(void *));
|
||||
# endif
|
||||
|
||||
// If the keys are not available from the header, define them ourselves. The values match
|
||||
// what tsd_private.h provides.
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY0
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY0 100
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY1
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY1 101
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY2
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY2 102
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY3
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY3 103
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY4
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY4 104
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY5
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY5 105
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY6
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY6 106
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY7
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY7 107
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY8
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY8 108
|
||||
# endif
|
||||
# ifndef __PTK_FRAMEWORK_SWIFT_KEY9
|
||||
# define __PTK_FRAMEWORK_SWIFT_KEY9 109
|
||||
# endif
|
||||
|
||||
|
||||
# define SWIFT_RUNTIME_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY0
|
||||
# define SWIFT_STDLIB_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY1
|
||||
# define SWIFT_COMPATIBILITY_50_TLS_KEY __PTK_FRAMEWORK_SWIFT_KEY2
|
||||
# define SWIFT_CONCURRENCY_TASK_KEY __PTK_FRAMEWORK_SWIFT_KEY3
|
||||
# define SWIFT_CONCURRENCY_EXECUTOR_TRACKING_INFO_KEY __PTK_FRAMEWORK_SWIFT_KEY4
|
||||
# define SWIFT_CONCURRENCY_FALLBACK_TASK_LOCAL_STORAGE_KEY \
|
||||
__PTK_FRAMEWORK_SWIFT_KEY5
|
||||
|
||||
#endif
|
||||
|
||||
// If the reserved key path didn't already provide get/setspecific macros,
|
||||
// wrap the platform's APIs.
|
||||
#ifndef SWIFT_THREAD_GETSPECIFIC
|
||||
|
||||
// Pick the right typedef for the key.
|
||||
# if defined(__linux__)
|
||||
# if defined(__ANDROID__)
|
||||
typedef int __swift_thread_key_t;
|
||||
# else
|
||||
typedef unsigned int __swift_thread_key_t;
|
||||
# endif
|
||||
# elif defined(__FreeBSD__)
|
||||
typedef int __swift_thread_key_t;
|
||||
# elif defined(__OpenBSD__)
|
||||
typedef int __swift_thread_key_t;
|
||||
# elif defined(_WIN32)
|
||||
typedef unsigned long __swift_thread_key_t;
|
||||
# elif defined(__HAIKU__)
|
||||
typedef int __swift_thread_key_t;
|
||||
# else
|
||||
typedef unsigned long __swift_thread_key_t;
|
||||
# endif
|
||||
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
// Windows has its own flavor of API.
|
||||
# include <io.h>
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <Windows.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
|
||||
"__swift_thread_key_t is not a DWORD");
|
||||
|
||||
# define SWIFT_THREAD_KEY_CREATE _stdlib_thread_key_create
|
||||
# define SWIFT_THREAD_GETSPECIFIC FlsGetValue
|
||||
# define SWIFT_THREAD_SETSPECIFIC(key, value) (FlsSetValue(key, value) == FALSE)
|
||||
|
||||
# elif !defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME)
|
||||
// Otherwise use the pthread API.
|
||||
# include <pthread.h>
|
||||
# define SWIFT_THREAD_KEY_CREATE pthread_key_create
|
||||
# define SWIFT_THREAD_GETSPECIFIC pthread_getspecific
|
||||
# define SWIFT_THREAD_SETSPECIFIC pthread_setspecific
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_RUNTIME_THREADLOCALSTORAGE_BACKDEPLOY56_H
|
||||
@@ -1,14 +1,8 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx13.0 -module-name main -emit-ir -o %t/new.ir
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx12.0 -module-name main -emit-ir -o %t/new.ir
|
||||
// RUN: %FileCheck %s --check-prefix=NEW < %t/new.ir
|
||||
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx12.0 -module-name main -emit-ir -o %t/backdeploy_56.ir
|
||||
// RUN: %FileCheck %s --check-prefix=BACKDEPLOY56 < %t/backdeploy_56.ir
|
||||
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -module-name main -emit-ir -o %t/backdeployed_concurrency.ir -disable-availability-checking
|
||||
// RUN: %FileCheck %s --check-prefixes=BACKDEPLOY_CONCURRENCY,BACKDEPLOY56 < %t/backdeployed_concurrency.ir
|
||||
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -module-name main -emit-ir -o %t/old.ir -disable-availability-checking
|
||||
// RUN: %FileCheck %s --check-prefix=OLD < %t/old.ir
|
||||
// RUN: %target-swift-frontend %s -target %target-cpu-apple-macosx10.15 -O -module-name main -emit-ir -o %t/optimized.ir -disable-availability-checking
|
||||
// RUN: %FileCheck %s --check-prefix=OPTIMIZED < %t/optimized.ir
|
||||
|
||||
@@ -16,15 +10,10 @@
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
// NEW-NOT: extern_weak
|
||||
|
||||
// BACKDEPLOY_CONCURRENCY: @"$sScPMn" = extern_weak global
|
||||
// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc i8* @swift_task_alloc
|
||||
// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc %swift.metadata_response @"$sScPMa"
|
||||
|
||||
// BACKDEPLOY_CONCURRENCY: declare extern_weak void @"_swift_FORCE_LOAD_$_swiftCompatibilityConcurrency"()
|
||||
// BACKDEPLOY56: declare extern_weak void @"_swift_FORCE_LOAD_$_swiftCompatibility56"()
|
||||
|
||||
// BACKDEPLOY_CONCURRENCY: declare extern_weak swiftcc i8 @"$sScP8rawValues5UInt8Vvg"
|
||||
// OLD: @"$sScPMn" = extern_weak global
|
||||
// OLD: declare extern_weak swiftcc i8* @swift_task_alloc
|
||||
// OLD: declare extern_weak swiftcc %swift.metadata_response @"$sScPMa"
|
||||
// OLD: declare extern_weak swiftcc i8 @"$sScP8rawValues5UInt8Vvg"
|
||||
|
||||
// OPTIMIZED: @swift_async_extendedFramePointerFlags = extern_weak global i8*
|
||||
// OPTIMIZED: @_swift_async_extendedFramePointerFlagsUser = linkonce_odr hidden global i8** @swift_async_extendedFramePointerFlags
|
||||
|
||||
Reference in New Issue
Block a user