Skip to content

Commit f8d6012

Browse files
authored
Merge pull request #76483 from al45tair/eng/PR-135380149
[Concurrency] Build executors as their own separate object modules.
2 parents cd5d48d + cf77aa3 commit f8d6012

16 files changed

+1428
-347
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 31 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,13 @@ void swift_task_enqueueGlobal(Job *job);
720720
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
721721
void swift_task_checkIsolated(SerialExecutorRef executor);
722722

723+
/// Invoke a Swift executor's `checkIsolated` implementation; returns
724+
/// `true` if it invoked the Swift implementation, `false` otherwise.
725+
/// Executors will want to call this from their `swift_task_checkIsolatedImpl`
726+
/// implementation.
727+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
728+
bool swift_task_invokeSwiftCheckIsolated(SerialExecutorRef executor);
729+
723730
/// A count in nanoseconds.
724731
using JobDelay = unsigned long long;
725732

@@ -760,64 +767,22 @@ void swift_task_enqueueOnDispatchQueue(Job *job, HeapObject *queue);
760767

761768
#endif
762769

763-
/// A hook to take over global enqueuing.
764-
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobal_original)(Job *job);
765-
SWIFT_EXPORT_FROM(swift_Concurrency)
766-
SWIFT_CC(swift) void (*swift_task_enqueueGlobal_hook)(
767-
Job *job, swift_task_enqueueGlobal_original original);
770+
// Declare all the hooks
771+
#define SWIFT_CONCURRENCY_HOOK(returnType, name, ...) \
772+
typedef SWIFT_CC(swift) returnType (*name##_original)(__VA_ARGS__); \
773+
typedef SWIFT_CC(swift) returnType \
774+
(*name##_hook_t)(__VA_ARGS__, name##_original original); \
775+
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
768776

769-
/// A hook to take over global enqueuing with delay.
770-
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDelay_original)(
771-
unsigned long long delay, Job *job);
772-
SWIFT_EXPORT_FROM(swift_Concurrency)
773-
SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDelay_hook)(
774-
unsigned long long delay, Job *job,
775-
swift_task_enqueueGlobalWithDelay_original original);
776-
777-
typedef SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDeadline_original)(
778-
long long sec,
779-
long long nsec,
780-
long long tsec,
781-
long long tnsec,
782-
int clock, Job *job);
783-
SWIFT_EXPORT_FROM(swift_Concurrency)
784-
SWIFT_CC(swift) void (*swift_task_enqueueGlobalWithDeadline_hook)(
785-
long long sec,
786-
long long nsec,
787-
long long tsec,
788-
long long tnsec,
789-
int clock, Job *job,
790-
swift_task_enqueueGlobalWithDeadline_original original);
791-
792-
typedef SWIFT_CC(swift) void (*swift_task_checkIsolated_original)(SerialExecutorRef executor);
793-
SWIFT_EXPORT_FROM(swift_Concurrency)
794-
SWIFT_CC(swift) void (*swift_task_checkIsolated_hook)(
795-
SerialExecutorRef executor, swift_task_checkIsolated_original original);
777+
#define SWIFT_CONCURRENCY_HOOK0(returnType, name) \
778+
typedef SWIFT_CC(swift) returnType (*name##_original)(); \
779+
typedef SWIFT_CC(swift) returnType \
780+
(*name##_hook_t)(name##_original original); \
781+
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
796782

783+
#include "ConcurrencyHooks.def"
797784

798-
typedef SWIFT_CC(swift) bool (*swift_task_isOnExecutor_original)(
799-
HeapObject *executor,
800-
const Metadata *selfType,
801-
const SerialExecutorWitnessTable *wtable);
802-
SWIFT_EXPORT_FROM(swift_Concurrency)
803-
SWIFT_CC(swift) bool (*swift_task_isOnExecutor_hook)(
804-
HeapObject *executor,
805-
const Metadata *selfType,
806-
const SerialExecutorWitnessTable *wtable,
807-
swift_task_isOnExecutor_original original);
808-
809-
/// A hook to take over main executor enqueueing.
810-
typedef SWIFT_CC(swift) void (*swift_task_enqueueMainExecutor_original)(
811-
Job *job);
812-
SWIFT_EXPORT_FROM(swift_Concurrency)
813-
SWIFT_CC(swift) void (*swift_task_enqueueMainExecutor_hook)(
814-
Job *job, swift_task_enqueueMainExecutor_original original);
815-
816-
/// A hook to override the entrypoint to the main runloop used to drive the
817-
/// concurrency runtime and drain the main queue. This function must not return.
818-
/// Note: If the hook is wrapping the original function and the `compatOverride`
819-
/// is passed in, the `original` function pointer must be passed into the
820-
/// compatibility override function as the original function.
785+
// This is a compatibility hook, *not* a concurrency hook
821786
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_original)();
822787
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_override)(
823788
swift_task_asyncMainDrainQueue_original original);
@@ -913,11 +878,16 @@ extern "C" SWIFT_CC(swift)
913878
void swift_continuation_logFailedCheck(const char *message);
914879

915880
/// Drain the queue
916-
/// If the binary links CoreFoundation, uses CFRunLoopRun
917-
/// Otherwise it uses dispatchMain.
918881
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
919882
void swift_task_asyncMainDrainQueue [[noreturn]]();
920883

884+
/// Drain the global executor. This does the same as the above, but
885+
/// swift_task_asyncMainDrainQueue() is a compatibility override point,
886+
/// whereas this function has a concurrency hook. The default
887+
/// swift_task_asyncMainDrainQueue() implementation just calls this function.
888+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
889+
void swift_task_drainGlobalExecutor [[noreturn]]();
890+
921891
/// Establish that the current thread is running as the given
922892
/// executor, then run a job.
923893
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
@@ -951,6 +921,10 @@ SerialExecutorRef swift_task_getCurrentExecutor(void);
951921
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
952922
SerialExecutorRef swift_task_getMainExecutor(void);
953923

924+
/// Test if an executor is the main executor.
925+
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
926+
bool swift_task_isMainExecutor(SerialExecutorRef executor);
927+
954928
/// Return the preferred task executor of the current task,
955929
/// or ``TaskExecutorRef::undefined()`` if no preference.
956930
///
@@ -984,17 +958,13 @@ JobPriority swift_task_getCurrentThreadPriority(void);
984958
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
985959
void swift_task_startOnMainActor(AsyncTask* job);
986960

987-
#if SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR
988-
989961
/// Donate this thread to the global executor until either the
990962
/// given condition returns true or we've run out of cooperative
991963
/// tasks to run.
992964
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
993965
void swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void*),
994966
void *context);
995967

996-
#endif
997-
998968
enum swift_clock_id : int {
999969
swift_clock_id_continuous = 1,
1000970
swift_clock_id_suspending = 2
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===--- Concurrency.h - Runtime interface for concurrency ------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Hooks for concurrency
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
// To use this file, define the following macros:
18+
//
19+
// SWIFT_CONCURRENCY_HOOK(returnType, name, ...)
20+
// SWIFT_CONCURRENCY_HOOK0(returnType, name)
21+
// SWIFT_CONCURRENCY_HOOK_OVERRIDE0(returnType, name)
22+
//
23+
// Then include the file somewhere.
24+
25+
#ifndef SWIFT_CONCURRENCY_HOOK
26+
#define SWIFT_CONCURRENCY_HOOK(returnType, name, ...)
27+
#endif
28+
29+
#ifndef SWIFT_CONCURRENCY_HOOK0
30+
#define SWIFT_CONCURRENCY_HOOK0(returnType, name)
31+
#endif
32+
33+
// .............................................................................
34+
35+
SWIFT_CONCURRENCY_HOOK(void, swift_task_enqueueGlobal, Job *job);
36+
37+
SWIFT_CONCURRENCY_HOOK(void, swift_task_enqueueGlobalWithDelay,
38+
unsigned long long delay, Job *job);
39+
40+
SWIFT_CONCURRENCY_HOOK(void, swift_task_enqueueGlobalWithDeadline,
41+
long long sec,
42+
long long nsec,
43+
long long tsec,
44+
long long tnsec,
45+
int clock, Job *job);
46+
47+
SWIFT_CONCURRENCY_HOOK(void, swift_task_checkIsolated, SerialExecutorRef executor);
48+
49+
SWIFT_CONCURRENCY_HOOK(bool, swift_task_isOnExecutor,
50+
HeapObject *executor,
51+
const Metadata *selfType,
52+
const SerialExecutorWitnessTable *wtable);
53+
54+
SWIFT_CONCURRENCY_HOOK(void, swift_task_enqueueMainExecutor, Job *job);
55+
56+
SWIFT_CONCURRENCY_HOOK0(SerialExecutorRef, swift_task_getMainExecutor);
57+
58+
SWIFT_CONCURRENCY_HOOK(bool, swift_task_isMainExecutor, SerialExecutorRef);
59+
60+
SWIFT_CONCURRENCY_HOOK(void, swift_task_donateThreadToGlobalExecutorUntil,
61+
bool (*condition)(void *), void *context);
62+
63+
// .............................................................................
64+
65+
#undef SWIFT_CONCURRENCY_HOOK
66+
#undef SWIFT_CONCURRENCY_HOOK0
67+
#undef SWIFT_CONCURRENCY_HOOK_OVERRIDE0

stdlib/public/Concurrency/Actor.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#define SWIFT_OBJC_INTEROP 1
4444
#endif
4545
#include "llvm/ADT/PointerIntPair.h"
46+
4647
#include "TaskPrivate.h"
4748
#include "VoucherSupport.h"
4849

@@ -2239,7 +2240,7 @@ static void swift_task_enqueueImpl(Job *job, SerialExecutorRef serialExecutorRef
22392240
}
22402241
SWIFT_TASK_DEBUG_LOG("enqueue job %p on serial serialExecutor %p, taskExecutor = %p", job,
22412242
serialExecutorRef.getIdentity(),
2242-
__taskExecutorRef.getIdentity());
2243+
_taskExecutorRef.getIdentity());
22432244
#endif
22442245

22452246
assert(job && "no job provided");

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ else()
4343
message(FATAL_ERROR "Invalid value for SWIFT_CONCURRENCY_GLOBAL_EXECUTOR (\"${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}\").")
4444
endif()
4545

46-
if(NOT SWIFT_CONCURRENCY_USES_DISPATCH)
47-
48-
endif()
49-
5046
if(NOT swift_concurrency_async_fp_mode)
5147
set(swift_concurrency_async_fp_mode "always")
5248
endif()
@@ -78,8 +74,10 @@ set(SWIFT_RUNTIME_CONCURRENCY_C_SOURCES
7874
AsyncLet.cpp
7975
Clock.cpp
8076
GlobalExecutor.cpp
77+
ConcurrencyHooks.cpp
8178
EmbeddedSupport.cpp
8279
Error.cpp
80+
ExecutorChecks.cpp
8381
Setup.cpp
8482
Task.cpp
8583
TaskAlloc.cpp
@@ -92,6 +90,27 @@ set(SWIFT_RUNTIME_CONCURRENCY_C_SOURCES
9290
linker-support/magic-symbols-for-install-name.c
9391
)
9492

93+
if("${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "dispatch")
94+
set(SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES
95+
DispatchGlobalExecutor.cpp
96+
)
97+
elseif("${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "singlethreaded")
98+
set(SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES
99+
CooperativeGlobalExecutor.cpp
100+
)
101+
elseif("${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "hooked" OR
102+
"${SWIFT_CONCURRENCY_GLOBAL_EXECUTOR}" STREQUAL "none")
103+
set(SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES
104+
NonDispatchGlobalExecutor.cpp
105+
)
106+
endif()
107+
108+
set(LLVM_OPTIONAL_SOURCES
109+
CooperativeGlobalExecutor.cpp
110+
DispatchGlobalExecutor.cpp
111+
NonDispatchGlobalExecutor.cpp
112+
)
113+
95114
set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
96115
Actor.swift
97116
AsyncLet.swift
@@ -158,6 +177,7 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES
158177

159178
add_swift_target_library(swift_Concurrency ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB
160179
${SWIFT_RUNTIME_CONCURRENCY_C_SOURCES}
180+
${SWIFT_RUNTIME_CONCURRENCY_EXECUTOR_SOURCES}
161181
${SWIFT_RUNTIME_CONCURRENCY_SWIFT_SOURCES}
162182

163183
SWIFT_MODULE_DEPENDS_ANDROID Android
@@ -230,7 +250,7 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
230250
set(extra_c_compile_flags -D__MACH__ -D__APPLE__ -ffreestanding)
231251
set(extra_swift_compile_flags -Xcc -D__MACH__ -Xcc -D__APPLE__ -Xcc -ffreestanding)
232252
endif()
233-
253+
234254
set(SWIFT_SDK_embedded_THREADING_PACKAGE none)
235255
set(SWIFT_SDK_embedded_ARCH_${mod}_MODULE "${mod}")
236256
set(SWIFT_SDK_embedded_LIB_SUBDIR "embedded")
@@ -243,6 +263,8 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
243263
IS_STDLIB IS_FRAGILE
244264

245265
${SWIFT_RUNTIME_CONCURRENCY_C_SOURCES}
266+
CooperativeGlobalExecutor.cpp
267+
246268
# TODO: Only a subset of Swift Concurrency .swift sources, for now.
247269
Actor.swift
248270
AsyncLet.swift
@@ -298,4 +320,25 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB AND SWIFT_SHOULD_BUILD_EMBEDDED_CONCURRENC
298320

299321
add_dependencies(embedded-concurrency embedded-concurrency-${mod})
300322
endforeach()
323+
324+
# Copy the ExecutorImpl.h header into the local include directory
325+
# and install it in the compiler toolchain
326+
add_custom_command(
327+
OUTPUT "${SWIFT_INCLUDE_DIR}/swift/ExecutorImpl.h"
328+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/ExecutorImpl.h"
329+
COMMAND "${CMAKE_COMMAND}" "-E" "copy"
330+
"${CMAKE_CURRENT_SOURCE_DIR}/ExecutorImpl.h"
331+
"${SWIFT_INCLUDE_DIR}/swift")
332+
333+
add_custom_target("copy_executor_impl_header"
334+
DEPENDS "${SWIFT_INCLUDE_DIR}/swift/ExecutorImpl.h"
335+
COMMENT "Copying executor implementation header to ${SWIFT_INCLUDE_DIR}/swift")
336+
337+
swift_install_in_component(FILES
338+
"${CMAKE_CURRENT_SOURCE_DIR}/ExecutorImpl.h"
339+
DESTINATION "include/swift"
340+
COMPONENT compiler)
341+
342+
add_dependencies(embedded-concurrency "copy_executor_impl_header")
301343
endif()
344+

0 commit comments

Comments
 (0)