mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
We were missing a field in `SwiftJob`, which broke various things. To avoid that problem in future, this PR adds a set of static asserts to check the layout of various structures and that we're using the same values as well. Also added some functions to the ABI, and fixed things so that if you enable the debug logging the library still builds (there was an extra `_` in `Actor.cpp` that caused a build failure). Finally, renamed `Hooks.cpp` to `ConcurrencyHooks.cpp`. rdar://135380149
303 lines
10 KiB
C
303 lines
10 KiB
C
///===--- ExecutorImpl.h - Global executor implementation interface --------===///
|
|
///
|
|
/// 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
|
|
///
|
|
///===----------------------------------------------------------------------===///
|
|
///
|
|
/// Contains the declarations you need to write a custom global
|
|
/// executor in plain C; this file intentionally does not include any
|
|
/// Swift ABI headers, because pulling those in necessitates use of
|
|
/// C++ and also pulls in a whole load of other things we don't need.
|
|
///
|
|
/// Note also that the global executor is expected to be statically
|
|
/// linked with swift_Concurrency, so we needn't worry about dynamic
|
|
/// linking from here.
|
|
///
|
|
///===----------------------------------------------------------------------===///
|
|
|
|
#ifndef SWIFT_CONCURRENCY_EXECUTORIMPL_H
|
|
#define SWIFT_CONCURRENCY_EXECUTORIMPL_H
|
|
|
|
#if !defined(__swift__) && __has_feature(ptrauth_calls)
|
|
#include <ptrauth.h>
|
|
#endif
|
|
#ifndef __ptrauth_objc_isa_pointer
|
|
#define __ptrauth_objc_isa_pointer
|
|
#endif
|
|
|
|
#include <inttypes.h>
|
|
#include <stdbool.h>
|
|
#include <stdlib.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef SWIFT_CC
|
|
#define SWIFT_CC(x) SWIFT_CC_##x
|
|
#define SWIFT_CC_swift __attribute__((swiftcall))
|
|
#endif
|
|
|
|
#ifndef SWIFT_RUNTIME_ATTRIBUTE_NORETURN
|
|
#define SWIFT_RUNTIME_ATTRIBUTE_NORETURN __attribute__((noreturn))
|
|
#endif
|
|
|
|
// -- C versions of types executors might need ---------------------------------
|
|
|
|
/// Represents a Swift type
|
|
typedef struct SwiftHeapMetadata SwiftHeapMetadata;
|
|
|
|
/// Jobs have flags, which currently encode a kind and a priority
|
|
typedef uint32_t SwiftJobFlags;
|
|
|
|
typedef size_t SwiftJobKind;
|
|
enum {
|
|
SwiftTaskJobKind = 0,
|
|
|
|
// Job kinds >= 192 are private to the implementation
|
|
SwiftFirstReservedJobKind = 192,
|
|
};
|
|
|
|
typedef size_t SwiftJobPriority;
|
|
enum {
|
|
SwiftUserInteractiveJobPriority = 0x21, /* UI */
|
|
SwiftUserInitiatedJobPriority = 0x19, /* IN */
|
|
SwiftDefaultJobPriority = 0x15, /* DEF */
|
|
SwiftUtilityJobPriority = 0x11, /* UT */
|
|
SwiftBackgroundJobPriority = 0x09, /* BG */
|
|
SwiftUnspecifiedJobPriority = 0x00, /* UN */
|
|
};
|
|
|
|
enum { SwiftJobPriorityBucketCount = 5 };
|
|
|
|
static inline int swift_priority_getBucketIndex(SwiftJobPriority priority) {
|
|
if (priority > SwiftUserInitiatedJobPriority)
|
|
return 0;
|
|
else if (priority > SwiftDefaultJobPriority)
|
|
return 1;
|
|
else if (priority > SwiftUtilityJobPriority)
|
|
return 2;
|
|
else if (priority > SwiftBackgroundJobPriority)
|
|
return 3;
|
|
else
|
|
return 4;
|
|
}
|
|
|
|
/// Used by the Concurrency runtime to represent a job. The `schedulerPrivate`
|
|
/// field may be freely used by the executor implementation.
|
|
typedef struct {
|
|
SwiftHeapMetadata const *__ptrauth_objc_isa_pointer metadata;
|
|
uintptr_t refCounts;
|
|
void *schedulerPrivate[2];
|
|
SwiftJobFlags flags;
|
|
} __attribute__((aligned(2 * sizeof(void *)))) SwiftJob;
|
|
|
|
/// Indexes in the schedulerPrivate array
|
|
enum {
|
|
SwiftJobNextWaitingTaskIndex = 0,
|
|
|
|
// These are only relevant for the Dispatch executor
|
|
SwiftJobDispatchHasLongObjectHeader = sizeof(void *) == sizeof(int),
|
|
SwiftJobDispatchLinkageIndex = SwiftJobDispatchHasLongObjectHeader ? 1 : 0,
|
|
SwiftJobDispatchQueueIndex = SwiftJobDispatchHasLongObjectHeader? 0 : 1
|
|
};
|
|
|
|
/// Get the kind of a job, by directly accessing the flags field.
|
|
static inline SwiftJobKind swift_job_getKind(SwiftJob *job) {
|
|
return (SwiftJobKind)(job->flags & 0xff);
|
|
}
|
|
|
|
/// Get the priority of a job, by directly accessing the flags field.
|
|
static inline SwiftJobPriority swift_job_getPriority(SwiftJob *job) {
|
|
return (SwiftJobPriority)((job->flags >> 8) & 0xff);
|
|
}
|
|
|
|
/// Allocate memory associated with a job.
|
|
void *swift_job_alloc(SwiftJob *job, size_t size);
|
|
|
|
/// Release memory allocated using `swift_job_alloc()`.
|
|
void swift_job_dealloc(SwiftJob *job, void *ptr);
|
|
|
|
/// Swift's refcounted objects start with this header
|
|
typedef struct {
|
|
SwiftHeapMetadata const *__ptrauth_objc_isa_pointer metadata;
|
|
} SwiftHeapObject;
|
|
|
|
/// A reference to an executor consists of two words; the first is a pointer
|
|
/// which may or may not be to a Swift heap object.
|
|
typedef struct {
|
|
SwiftHeapObject *identity;
|
|
uintptr_t implementation;
|
|
} SwiftExecutorRef;
|
|
|
|
/// Indicates whether or not an executor can be compared by just looking at
|
|
/// the `identity` field.
|
|
typedef unsigned SwiftExecutorKind;
|
|
enum {
|
|
SwiftExecutorOrdinaryKind = 0,
|
|
SwiftExecutorComplexEqualityKind = 1
|
|
};
|
|
|
|
typedef struct SwiftExecutorWitnessTable SwiftExecutorWitnessTable;
|
|
|
|
/// Return the generic executor.
|
|
static inline SwiftExecutorRef swift_executor_generic(void) {
|
|
return (SwiftExecutorRef){ NULL, 0 };
|
|
}
|
|
|
|
/// Return an ordinary executor with the specified identity and witness table.
|
|
static inline SwiftExecutorRef
|
|
swift_executor_ordinary(SwiftHeapObject *identity,
|
|
SwiftExecutorWitnessTable *witnessTable) {
|
|
return (SwiftExecutorRef){ identity,
|
|
(uintptr_t)witnessTable
|
|
| SwiftExecutorOrdinaryKind };
|
|
}
|
|
|
|
/// Return a complex equality executor with the specified identity and
|
|
/// witness table.
|
|
static inline SwiftExecutorRef
|
|
swift_executor_complexEquality(SwiftHeapObject *identity,
|
|
SwiftExecutorWitnessTable *witnessTable) {
|
|
return (SwiftExecutorRef){ identity,
|
|
(uintptr_t)witnessTable
|
|
| SwiftExecutorComplexEqualityKind };
|
|
}
|
|
|
|
/// Get the type of executor (ordinary vs complex equality).
|
|
static inline SwiftExecutorKind
|
|
swift_executor_getKind(SwiftExecutorRef executor) {
|
|
const uintptr_t mask = ~(uintptr_t)(sizeof(void *) - 1);
|
|
return executor.implementation & ~mask;
|
|
}
|
|
|
|
/// Return `true` if this is the generic executor.
|
|
static inline bool swift_executor_isGeneric(SwiftExecutorRef executor) {
|
|
return executor.identity == NULL;
|
|
}
|
|
|
|
/// Return `true` if this executor is in fact the default actor.
|
|
static inline bool swift_executor_isDefaultActor(SwiftExecutorRef executor) {
|
|
return !swift_executor_isGeneric(executor) && executor.implementation == 0;
|
|
}
|
|
|
|
/// Retrieve the identity of an executor.
|
|
static inline SwiftHeapObject *
|
|
swift_executor_getIdentity(SwiftExecutorRef executor) {
|
|
return executor.identity;
|
|
}
|
|
|
|
/// Test if an executor has a valid witness table.
|
|
static inline bool swift_executor_hasWitnessTable(SwiftExecutorRef executor) {
|
|
return (!swift_executor_isGeneric(executor)
|
|
&& !swift_executor_isDefaultActor(executor));
|
|
}
|
|
|
|
/// Retrieve the witness table of an executor.
|
|
static inline const SwiftExecutorWitnessTable *
|
|
swift_executor_getWitnessTable(SwiftExecutorRef executor) {
|
|
const uintptr_t mask = ~(uintptr_t)(sizeof(void *) - 1);
|
|
return (const SwiftExecutorWitnessTable *)(executor.implementation & mask);
|
|
}
|
|
|
|
/// Test if this is the main executor.
|
|
static inline bool swift_executor_isMain(SwiftExecutorRef executor) {
|
|
extern bool _swift_task_isMainExecutor_c(SwiftExecutorRef executor);
|
|
|
|
return _swift_task_isMainExecutor_c(executor);
|
|
}
|
|
|
|
/// Assert that we are isolated on the specified executor.
|
|
static inline bool
|
|
swift_executor_invokeSwiftCheckIsolated(SwiftExecutorRef executor) {
|
|
extern bool _swift_task_invokeSwiftCheckIsolated_c(SwiftExecutorRef executor);
|
|
|
|
return _swift_task_invokeSwiftCheckIsolated_c(executor);
|
|
}
|
|
|
|
/// Execute the specified job while running on the specified executor.
|
|
static inline void swift_job_run(SwiftJob *job, SwiftExecutorRef executor) {
|
|
extern void _swift_job_run_c(SwiftJob *job, SwiftExecutorRef executor);
|
|
|
|
_swift_job_run_c(job, executor);
|
|
}
|
|
|
|
/// A delay in nanoseconds.
|
|
typedef unsigned long long SwiftJobDelay;
|
|
|
|
/// Names of clocks supported by the Swift time functions.
|
|
typedef int SwiftClockId;
|
|
enum {
|
|
SwiftContinuousClock = 1,
|
|
SwiftSuspendingClock = 2
|
|
};
|
|
|
|
/// An accurate timestamp, with *up to* nanosecond precision.
|
|
typedef struct {
|
|
long long seconds;
|
|
long long nanoseconds;
|
|
} SwiftTime;
|
|
|
|
/// Get the current time from the specified clock
|
|
extern SwiftTime swift_time_now(SwiftClockId clock);
|
|
|
|
/// Get the resolution of the specified clock
|
|
extern SwiftTime swift_time_getResolution(SwiftClockId clock);
|
|
|
|
// -- Functions that executors must implement ----------------------------------
|
|
|
|
/// Enqueue a job on the global executor.
|
|
SWIFT_CC(swift) void swift_task_enqueueGlobalImpl(SwiftJob *job);
|
|
|
|
/// Enqueue a job on the global executor, with a specific delay before it
|
|
/// should execute.
|
|
SWIFT_CC(swift) void swift_task_enqueueGlobalWithDelayImpl(SwiftJobDelay delay,
|
|
SwiftJob *job);
|
|
|
|
/// Enqueue a job on the global executor, with a specific deadline before
|
|
/// which it must execute.
|
|
SWIFT_CC(swift) void swift_task_enqueueGlobalWithDeadlineImpl(long long sec,
|
|
long long nsec,
|
|
long long tsec,
|
|
long long tnsec,
|
|
int clock,
|
|
SwiftJob *job);
|
|
|
|
/// Enqueue a job on the main executor (which may or may not be the same as
|
|
/// the global executor).
|
|
SWIFT_CC(swift) void swift_task_enqueueMainExecutorImpl(SwiftJob *job);
|
|
|
|
/// Assert that the specified executor is the current executor.
|
|
SWIFT_CC(swift) void swift_task_checkIsolatedImpl(SwiftExecutorRef executor);
|
|
|
|
/// Get a reference to the main executor.
|
|
SWIFT_CC(swift) SwiftExecutorRef swift_task_getMainExecutorImpl(void);
|
|
|
|
/// Check if the specified executor is the main executor.
|
|
SWIFT_CC(swift) bool swift_task_isMainExecutorImpl(SwiftExecutorRef executor);
|
|
|
|
/// Drain the main executor's queue, processing jobs enqueued on it; this
|
|
/// should never return.
|
|
SWIFT_RUNTIME_ATTRIBUTE_NORETURN SWIFT_CC(swift) void
|
|
swift_task_asyncMainDrainQueueImpl(void);
|
|
|
|
/// Hand control of the current thread to the global executor until the
|
|
/// condition function returns `true`. Support for this function is optional,
|
|
/// but you should assert or provide a dummy implementation if your executor
|
|
/// does not support it.
|
|
SWIFT_CC(swift) void
|
|
swift_task_donateThreadToGlobalExecutorUntilImpl(bool (*condition)(void *),
|
|
void *conditionContext);
|
|
|
|
#ifdef __cplusplus
|
|
} // extern "C"
|
|
#endif
|
|
|
|
#endif // SWIFT_CONCURRENCY_EXECUTORIMPL_H
|