Skip to content

Commit 26b5fa6

Browse files
committed
[Concurrency] Rename ExecutorHooks.h, tidy up the interface.
`ExecutorHooks.h` is now nothing to do with hooks, so rename it. Also there are some additional functions it should declare, and a couple of places where we've slightly messed up the boundary, for instance `swift_task_asyncMainDrainQueue` was defined in `Task.cpp` rather than in the executor implementations, which is wrong, so fix that too. `CooperativeGlobalExecutor.cpp` now builds against the interface from `ExecutorImpl.h`, rather than including the all the concurrency headers. rdar://135380149
1 parent efe5d66 commit 26b5fa6

File tree

10 files changed

+678
-288
lines changed

10 files changed

+678
-288
lines changed

include/swift/Runtime/Concurrency.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -780,17 +780,17 @@ void swift_task_enqueueOnDispatchQueue(Job *job, HeapObject *queue);
780780
(*name##_hook_t)(name##_original original); \
781781
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
782782

783-
#define SWIFT_CONCURRENCY_HOOK_OVERRIDE0(returnType, name) \
784-
typedef SWIFT_CC(swift) returnType (*name##_original)(); \
785-
typedef SWIFT_CC(swift) returnType (*name##_override)( \
786-
name##_original original); \
787-
typedef SWIFT_CC(swift) returnType \
788-
(*name##_hook_t)(name##_original original, \
789-
name##_override compatOverride); \
790-
SWIFT_EXPORT_FROM(swift_Concurrency) name##_hook_t name##_hook
791-
792783
#include "ConcurrencyHooks.def"
793784

785+
// This is a compatibility hook, *not* a concurrency hook
786+
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_original)();
787+
typedef SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_override)(
788+
swift_task_asyncMainDrainQueue_original original);
789+
SWIFT_EXPORT_FROM(swift_Concurrency)
790+
SWIFT_CC(swift) void (*swift_task_asyncMainDrainQueue_hook)(
791+
swift_task_asyncMainDrainQueue_original original,
792+
swift_task_asyncMainDrainQueue_override compatOverride);
793+
794794
/// Initialize the runtime storage for a default actor.
795795
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
796796
void swift_defaultActor_initialize(DefaultActor *actor);
@@ -878,11 +878,16 @@ extern "C" SWIFT_CC(swift)
878878
void swift_continuation_logFailedCheck(const char *message);
879879

880880
/// Drain the queue
881-
/// If the binary links CoreFoundation, uses CFRunLoopRun
882-
/// Otherwise it uses dispatchMain.
883881
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
884882
void swift_task_asyncMainDrainQueue [[noreturn]]();
885883

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+
886891
/// Establish that the current thread is running as the given
887892
/// executor, then run a job.
888893
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
@@ -953,17 +958,13 @@ JobPriority swift_task_getCurrentThreadPriority(void);
953958
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
954959
void swift_task_startOnMainActor(AsyncTask* job);
955960

956-
#if SWIFT_CONCURRENCY_COOPERATIVE_GLOBAL_EXECUTOR
957-
958961
/// Donate this thread to the global executor until either the
959962
/// given condition returns true or we've run out of cooperative
960963
/// tasks to run.
961964
SWIFT_EXPORT_FROM(swift_Concurrency) SWIFT_CC(swift)
962965
void swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void*),
963966
void *context);
964967

965-
#endif
966-
967968
enum swift_clock_id : int {
968969
swift_clock_id_continuous = 1,
969970
swift_clock_id_suspending = 2

include/swift/Runtime/ConcurrencyHooks.def

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@
3030
#define SWIFT_CONCURRENCY_HOOK0(returnType, name)
3131
#endif
3232

33-
#ifndef SWIFT_CONCURRENCY_HOOK_OVERRIDE0
34-
#define SWIFT_CONCURRENCY_HOOK_OVERRIDE0(returnType, name)
35-
#endif
36-
3733
// .............................................................................
3834

3935
SWIFT_CONCURRENCY_HOOK(void, swift_task_enqueueGlobal, Job *job);
@@ -61,12 +57,8 @@ SWIFT_CONCURRENCY_HOOK0(SerialExecutorRef, swift_task_getMainExecutor);
6157

6258
SWIFT_CONCURRENCY_HOOK(bool, swift_task_isMainExecutor, SerialExecutorRef);
6359

64-
/// A hook to override the entrypoint to the main runloop used to drive the
65-
/// concurrency runtime and drain the main queue. This function must not return.
66-
/// Note: If the hook is wrapping the original function and the `compatOverride`
67-
/// is passed in, the `original` function pointer must be passed into the
68-
/// compatibility override function as the original function.
69-
SWIFT_CONCURRENCY_HOOK_OVERRIDE0(void, swift_task_asyncMainDrainQueue);
60+
SWIFT_CONCURRENCY_HOOK(void, swift_task_donateThreadToGlobalExecutorUntil,
61+
bool (*condition)(void *), void *context);
7062

7163
// .............................................................................
7264

stdlib/public/Concurrency/CooperativeGlobalExecutor.cpp

Lines changed: 62 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@
1515
/// This file is included into GlobalExecutor.cpp only when
1616
/// the cooperative global executor is enabled. It is expected to
1717
/// declare the following functions:
18+
/// swift_task_asyncMainDrainQueueImpl
19+
/// swift_task_checkIsolatedImpl
20+
/// swift_task_donateThreadToGlobalExecutorUntilImpl
1821
/// swift_task_enqueueGlobalImpl
22+
/// swift_task_enqueueGlobalWithDeadlineImpl
1923
/// swift_task_enqueueGlobalWithDelayImpl
2024
/// swift_task_enqueueMainExecutorImpl
21-
/// swift_task_checkIsolatedImpl
25+
/// swift_task_getMainExecutorImpl
26+
/// swift_task_isMainExecutorImpl
2227
/// as well as any cooperative-executor-specific functions in the runtime.
2328
///
2429
///===------------------------------------------------------------------===///
2530

26-
#include "swift/Runtime/Concurrency.h"
31+
#include "swift/shims/Visibility.h"
2732

2833
#include <chrono>
2934
#ifndef SWIFT_THREADING_NONE
@@ -39,92 +44,92 @@
3944
# define NSEC_PER_SEC 1000000000ull
4045
#endif
4146

42-
#include "ExecutorHooks.h"
47+
#include "ExecutorImpl.h"
4348

4449
using namespace swift;
4550

4651
namespace {
4752

4853
struct JobQueueTraits {
49-
static Job *&storage(Job *cur) {
50-
return reinterpret_cast<Job*&>(cur->SchedulerPrivate[0]);
54+
static SwiftJob *&storage(SwiftJob *cur) {
55+
return reinterpret_cast<SwiftJob*&>(cur->schedulerPrivate[0]);
5156
}
5257

53-
static Job *getNext(Job *job) {
58+
static SwiftJob *getNext(SwiftJob *job) {
5459
return storage(job);
5560
}
56-
static void setNext(Job *job, Job *next) {
61+
static void setNext(SwiftJob *job, SwiftJob *next) {
5762
storage(job) = next;
5863
}
59-
enum { prioritiesCount = PriorityBucketCount };
60-
static int getPriorityIndex(Job *job) {
61-
return getPriorityBucketIndex(job->getPriority());
64+
enum { prioritiesCount = SwiftJobPriorityBucketCount };
65+
static int getPriorityIndex(SwiftJob *job) {
66+
return swift_priority_getBucketIndex(swift_job_getPriority(job));
6267
}
6368
};
64-
using JobPriorityQueue = PriorityQueue<Job*, JobQueueTraits>;
69+
using JobPriorityQueue = PriorityQueue<SwiftJob*, JobQueueTraits>;
6570

6671
using JobDeadline = std::chrono::time_point<std::chrono::steady_clock>;
6772

6873
template <bool = (sizeof(JobDeadline) <= sizeof(void*) &&
6974
alignof(JobDeadline) <= alignof(void*))>
7075
struct JobDeadlineStorage;
7176

72-
/// Specialization for when JobDeadline fits in SchedulerPrivate.
77+
/// Specialization for when JobDeadline fits in schedulerPrivate.
7378
template <>
7479
struct JobDeadlineStorage<true> {
75-
static JobDeadline &storage(Job *job) {
76-
return reinterpret_cast<JobDeadline&>(job->SchedulerPrivate[1]);
80+
static JobDeadline &storage(SwiftJob *job) {
81+
return reinterpret_cast<JobDeadline&>(job->schedulerPrivate[1]);
7782
}
78-
static JobDeadline get(Job *job) {
83+
static JobDeadline get(SwiftJob *job) {
7984
return storage(job);
8085
}
81-
static void set(Job *job, JobDeadline deadline) {
86+
static void set(SwiftJob *job, JobDeadline deadline) {
8287
new(static_cast<void*>(&storage(job))) JobDeadline(deadline);
8388
}
84-
static void destroy(Job *job) {
89+
static void destroy(SwiftJob *job) {
8590
storage(job).~JobDeadline();
8691
}
8792
};
8893

89-
/// Specialization for when JobDeadline doesn't fit in SchedulerPrivate.
94+
/// Specialization for when JobDeadline doesn't fit in schedulerPrivate.
9095
template <>
9196
struct JobDeadlineStorage<false> {
92-
static JobDeadline *&storage(Job *job) {
93-
return reinterpret_cast<JobDeadline*&>(job->SchedulerPrivate[1]);
97+
static JobDeadline *&storage(SwiftJob *job) {
98+
return reinterpret_cast<JobDeadline*&>(job->schedulerPrivate[1]);
9499
}
95-
static JobDeadline get(Job *job) {
100+
static JobDeadline get(SwiftJob *job) {
96101
return *storage(job);
97102
}
98-
static void set(Job *job, JobDeadline deadline) {
103+
static void set(SwiftJob *job, JobDeadline deadline) {
99104
storage(job) = new JobDeadline(deadline);
100105
}
101-
static void destroy(Job *job) {
106+
static void destroy(SwiftJob *job) {
102107
delete storage(job);
103108
}
104109
};
105110

106111
} // end anonymous namespace
107112

108113
static JobPriorityQueue JobQueue;
109-
static Job *DelayedJobQueue = nullptr;
114+
static SwiftJob *DelayedJobQueue = nullptr;
110115

111116
/// Insert a job into the cooperative global queue.
112117
SWIFT_CC(swift)
113-
void swift::swift_task_enqueueGlobalImpl(Job *job) {
118+
void swift_task_enqueueGlobalImpl(SwiftJob *job) {
114119
assert(job && "no job provided");
115120
JobQueue.enqueue(job);
116121
}
117122

118123
/// Enqueues a task on the main executor.
119124
SWIFT_CC(swift)
120-
void swift::swift_task_enqueueMainExecutorImpl(Job *job) {
125+
void swift_task_enqueueMainExecutorImpl(SwiftJob *job) {
121126
// The cooperative executor does not distinguish between the main
122127
// queue and the global queue.
123128
swift_task_enqueueGlobalImpl(job);
124129
}
125130

126-
static void insertDelayedJob(Job *newJob, JobDeadline deadline) {
127-
Job **position = &DelayedJobQueue;
131+
static void insertDelayedJob(SwiftJob *newJob, JobDeadline deadline) {
132+
SwiftJob **position = &DelayedJobQueue;
128133
while (auto cur = *position) {
129134
// If we find a job with a later deadline, insert here.
130135
// Note that we maintain FIFO order.
@@ -142,14 +147,14 @@ static void insertDelayedJob(Job *newJob, JobDeadline deadline) {
142147
}
143148

144149
SWIFT_CC(swift)
145-
void swift::swift_task_checkIsolatedImpl(SerialExecutorRef executor) {
146-
swift_task_invokeSwiftCheckIsolated(executor);
150+
void swift_task_checkIsolatedImpl(SwiftExecutorRef executor) {
151+
swift_executor_invokeSwiftCheckIsolated(executor);
147152
}
148153

149154
/// Insert a job into the cooperative global queue with a delay.
150155
SWIFT_CC(swift)
151-
void swift::swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
152-
Job *newJob) {
156+
void swift_task_enqueueGlobalWithDelayImpl(SwiftJobDelay delay,
157+
SwiftJob *newJob) {
153158
assert(newJob && "no job provided");
154159

155160
auto deadline = std::chrono::steady_clock::now()
@@ -161,18 +166,16 @@ void swift::swift_task_enqueueGlobalWithDelayImpl(JobDelay delay,
161166
}
162167

163168
SWIFT_CC(swift)
164-
void swift::swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
165-
long long nsec,
166-
long long tsec,
167-
long long tnsec,
168-
int clock, Job *newJob) {
169+
void swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
170+
long long nsec,
171+
long long tsec,
172+
long long tnsec,
173+
int clock, SwiftJob *newJob) {
169174
assert(newJob && "no job provided");
170175

171-
long long nowSec;
172-
long long nowNsec;
173-
swift_get_time(&nowSec, &nowNsec, (swift_clock_id)clock);
176+
SwiftTime now = swift_time_now(clock);
174177

175-
uint64_t delta = (sec - nowSec) * NSEC_PER_SEC + nsec - nowNsec;
178+
uint64_t delta = (sec - now.seconds) * NSEC_PER_SEC + nsec - now.nanoseconds;
176179

177180
auto deadline = std::chrono::steady_clock::now()
178181
+ std::chrono::duration_cast<JobDeadline::duration>(
@@ -225,7 +228,7 @@ static void sleepThisThreadUntil(JobDeadline deadline) {
225228
}
226229

227230
/// Claim the next job from the cooperative global queue.
228-
static Job *claimNextFromCooperativeGlobalQueue() {
231+
static SwiftJob *claimNextFromCooperativeGlobalQueue() {
229232
while (true) {
230233
// Move any delayed jobs that are now ready into the primary queue.
231234
recognizeReadyDelayedJobs();
@@ -247,22 +250,31 @@ static Job *claimNextFromCooperativeGlobalQueue() {
247250
}
248251
}
249252

250-
void swift::
251-
swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void *),
252-
void *conditionContext) {
253+
SWIFT_CC(swift) void
254+
swift_task_donateThreadToGlobalExecutorUntilImpl(bool (*condition)(void *),
255+
void *conditionContext) {
253256
while (!condition(conditionContext)) {
254257
auto job = claimNextFromCooperativeGlobalQueue();
255258
if (!job) return;
256-
swift_job_run(job, SerialExecutorRef::generic());
259+
swift_job_run(job, swift_executor_generic());
260+
}
261+
}
262+
263+
SWIFT_RUNTIME_ATTRIBUTE_NORETURN SWIFT_CC(swift)
264+
void swift_task_asyncMainDrainQueueImpl() {
265+
while (true) {
266+
auto job = claimNextFromCooperativeGlobalQueue();
267+
assert(job && "We should never run out of jobs on the async main queue.");
268+
swift_job_run(job, swift_executor_generic());
257269
}
258270
}
259271

260272
SWIFT_CC(swift)
261-
SerialExecutorRef swift::swift_task_getMainExecutorImpl() {
262-
return SerialExecutorRef::generic();
273+
SwiftExecutorRef swift_task_getMainExecutorImpl() {
274+
return swift_executor_generic();
263275
}
264276

265277
SWIFT_CC(swift)
266-
bool swift::swift_task_isMainExecutorImpl(SerialExecutorRef executor) {
267-
return executor.isGeneric();
278+
bool swift_task_isMainExecutorImpl(SwiftExecutorRef executor) {
279+
return swift_executor_isGeneric(executor);
268280
}

0 commit comments

Comments
 (0)