//===--- 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_H #define SWIFT_CONCURRENCY_TASKPRIVATE_H #include "swift/Runtime/Concurrency.h" #include "swift/ABI/Task.h" #include "swift/ABI/Metadata.h" #include "swift/Runtime/HeapObject.h" #include "swift/Runtime/Error.h" namespace swift { // Uncomment to enable helpful debug spew to stderr //#define SWIFT_TASK_PRINTF_DEBUG 1 class AsyncTask; class TaskGroup; /// Initialize the task-local allocator in the given task. void _swift_task_alloc_initialize(AsyncTask *task); void _swift_task_alloc_initialize_with_slab(AsyncTask *task, void *firstSlabBuffer, size_t bufferCapacity); /// Destroy the task-local allocator in the given task. void _swift_task_alloc_destroy(AsyncTask *task); /// Allocate task-local memory on behalf of a specific task, /// not necessarily the current one. Generally this should only be /// done on behalf of a child task. void *_swift_task_alloc_specific(AsyncTask *task, size_t size); /// dellocate task-local memory on behalf of a specific task, /// not necessarily the current one. Generally this should only be /// done on behalf of a child task. void _swift_task_dealloc_specific(AsyncTask *task, void *ptr); /// Given that we've already set the right executor as the active /// executor, run the given job. This does additional bookkeeping /// related to the active task. void runJobInEstablishedExecutorContext(Job *job); /// Clear the active task reference for the current thread. AsyncTask *_swift_task_clearCurrent(); AsyncTaskAndContext swift_task_create_async_let_future(size_t flags, const Metadata *futureResultType, void *closureEntry, void *closureContext); #if defined(SWIFT_STDLIB_SINGLE_THREADED_RUNTIME) #define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 1 #else #define SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR 0 #endif #if SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR /// Donate this thread to the global executor until either the /// given condition returns true or we've run out of cooperative /// tasks to run. void donateThreadToGlobalExecutorUntil(bool (*condition)(void*), void *context); #endif /// release() establishes a happens-before relation with a preceding acquire() /// on the same address. void _swift_tsan_acquire(void *addr); void _swift_tsan_release(void *addr); /// Special values used with DispatchQueueIndex to indicate the global and main /// executors. #define DISPATCH_QUEUE_GLOBAL_EXECUTOR (void *)1 #define DISPATCH_QUEUE_MAIN_EXECUTOR (void *)2 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" // FIXME: remove this and switch to a representation that uses // _dispatch_main_q somehow extern "C" SWIFT_CC(swift) ExecutorRef _swift_task_getMainExecutor(); #pragma clang diagnostic pop // ==== ------------------------------------------------------------------------ namespace { /// The layout of a context to call one of the following functions: /// /// @_silgen_name("swift_task_future_wait") /// func _taskFutureGet(_ task: Builtin.NativeObject) async -> T /// /// @_silgen_name("swift_task_future_wait_throwing") /// func _taskFutureGetThrowing(_ task: Builtin.NativeObject) async throws -> T /// /// @_silgen_name("swift_asyncLet_wait") /// func _asyncLetGet(_ task: Builtin.RawPointer) async -> T /// /// @_silgen_name("swift_asyncLet_waitThrowing") /// func _asyncLetGetThrowing(_ task: Builtin.RawPointer) async throws -> T /// class TaskFutureWaitAsyncContext : public AsyncContext { public: SwiftError *errorResult; OpaqueValue *successResultPointer; AsyncVoidClosureResumeEntryPoint *__ptrauth_swift_task_resume_function asyncResumeEntryPoint; 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); } }; /// The layout of a frame to call the following function: /// /// @_silgen_name("swift_taskGroup_wait_next_throwing") /// func _taskGroupWaitNext(group: Builtin.RawPointer) async throws -> T? /// class TaskGroupNextAsyncContext : public AsyncContext { public: SwiftError *errorResult; OpaqueValue *successResultPointer; AsyncVoidClosureResumeEntryPoint *__ptrauth_swift_task_resume_function asyncResumeEntryPoint; // Arguments. TaskGroup *group; const Metadata *successType; void fillWithSuccess(OpaqueValue *src, const Metadata *successType) { successType->vw_initializeWithCopy(successResultPointer, src); } void fillWithError(SwiftError *error) { errorResult = error; swift_errorRetain(error); } }; } // end anonymous namespace } // end namespace swift #endif