mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
242 lines
8.4 KiB
C++
242 lines
8.4 KiB
C++
///===--- Hooks.cpp - Concurrency hook variables --------------------------===///
|
|
///
|
|
/// 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
|
|
///
|
|
///===----------------------------------------------------------------------===///
|
|
///
|
|
/// Defines all of the hook variables.
|
|
///
|
|
///===----------------------------------------------------------------------===///
|
|
|
|
#include "swift/ABI/Task.h"
|
|
#include "swift/Runtime/Concurrency.h"
|
|
#include "swift/Runtime/HeapObject.h"
|
|
#include "swift/shims/Visibility.h"
|
|
#include "ExecutorImpl.h"
|
|
#include "TaskPrivate.h"
|
|
|
|
// Define all the hooks
|
|
#define SWIFT_CONCURRENCY_HOOK(returnType, name, ...) \
|
|
swift::name##_hook_t swift::name##_hook = nullptr
|
|
#define SWIFT_CONCURRENCY_HOOK0(returnType, name) \
|
|
swift::name##_hook_t swift::name##_hook = nullptr
|
|
#define SWIFT_CONCURRENCY_HOOK_OVERRIDE0(returnType, name) \
|
|
swift::name##_hook_t swift::name##_hook = nullptr
|
|
|
|
#include "swift/Runtime/ConcurrencyHooks.def"
|
|
|
|
using namespace swift;
|
|
|
|
// Define the external entry points; because the Impl functions use the C
|
|
// types from `ExecutorHooks.h`, we need to make an Orig version containing
|
|
// appropriate type casts in each case.
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_enqueueGlobalOrig(Job *job) {
|
|
swift_task_enqueueGlobalImpl(reinterpret_cast<SwiftJob *>(job));
|
|
}
|
|
|
|
void
|
|
swift::swift_task_enqueueGlobal(Job *job) {
|
|
_swift_tsan_release(job);
|
|
|
|
concurrency::trace::job_enqueue_global(job);
|
|
|
|
if (SWIFT_UNLIKELY(swift_task_enqueueGlobal_hook)) {
|
|
swift_task_enqueueGlobal_hook(job, swift_task_enqueueGlobalOrig);
|
|
} else {
|
|
swift_task_enqueueGlobalOrig(job);
|
|
}
|
|
}
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_enqueueGlobalWithDelayOrig(JobDelay delay, Job *job) {
|
|
swift_task_enqueueGlobalWithDelayImpl(
|
|
static_cast<SwiftJobDelay>(delay), reinterpret_cast<SwiftJob *>(job));
|
|
}
|
|
|
|
void
|
|
swift::swift_task_enqueueGlobalWithDelay(JobDelay delay, Job *job) {
|
|
concurrency::trace::job_enqueue_global_with_delay(delay, job);
|
|
|
|
if (SWIFT_UNLIKELY(swift_task_enqueueGlobalWithDelay_hook))
|
|
swift_task_enqueueGlobalWithDelay_hook(
|
|
delay, job, swift_task_enqueueGlobalWithDelayOrig);
|
|
else
|
|
swift_task_enqueueGlobalWithDelayOrig(delay, job);
|
|
}
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_enqueueGlobalWithDeadlineOrig(
|
|
long long sec,
|
|
long long nsec,
|
|
long long tsec,
|
|
long long tnsec,
|
|
int clock, Job *job) {
|
|
swift_task_enqueueGlobalWithDeadlineImpl(sec, nsec, tsec, tnsec, clock,
|
|
reinterpret_cast<SwiftJob *>(job));
|
|
}
|
|
|
|
void
|
|
swift::swift_task_enqueueGlobalWithDeadline(
|
|
long long sec,
|
|
long long nsec,
|
|
long long tsec,
|
|
long long tnsec,
|
|
int clock, Job *job) {
|
|
if (SWIFT_UNLIKELY(swift_task_enqueueGlobalWithDeadline_hook))
|
|
swift_task_enqueueGlobalWithDeadline_hook(
|
|
sec, nsec, tsec, tnsec, clock, job,
|
|
swift_task_enqueueGlobalWithDeadlineOrig);
|
|
else
|
|
swift_task_enqueueGlobalWithDeadlineOrig(sec, nsec, tsec, tnsec, clock, job);
|
|
}
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_checkIsolatedOrig(SerialExecutorRef executor) {
|
|
swift_task_checkIsolatedImpl(*reinterpret_cast<SwiftExecutorRef *>(&executor));
|
|
}
|
|
|
|
void
|
|
swift::swift_task_checkIsolated(SerialExecutorRef executor) {
|
|
if (SWIFT_UNLIKELY(swift_task_checkIsolated_hook))
|
|
swift_task_checkIsolated_hook(executor, swift_task_checkIsolatedOrig);
|
|
else
|
|
swift_task_checkIsolatedOrig(executor);
|
|
}
|
|
|
|
SWIFT_CC(swift) static int8_t
|
|
swift_task_isIsolatingCurrentContextOrig(SerialExecutorRef executor) {
|
|
return swift_task_isIsolatingCurrentContextImpl(
|
|
*reinterpret_cast<SwiftExecutorRef *>(&executor));
|
|
}
|
|
|
|
int8_t
|
|
swift::swift_task_isIsolatingCurrentContext(SerialExecutorRef executor) {
|
|
if (SWIFT_UNLIKELY(swift_task_isIsolatingCurrentContext_hook)) {
|
|
return swift_task_isIsolatingCurrentContext_hook(
|
|
executor, swift_task_isIsolatingCurrentContextOrig);
|
|
} else {
|
|
return swift_task_isIsolatingCurrentContextOrig(executor);
|
|
}
|
|
}
|
|
|
|
// Implemented in Swift because we need to obtain the user-defined flags on the executor ref.
|
|
//
|
|
// We could inline this with effort, though.
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
|
|
extern "C" SWIFT_CC(swift)
|
|
swift::SerialExecutorRef _task_serialExecutor_getExecutorRef(
|
|
swift::HeapObject *executor, const swift::Metadata *selfType,
|
|
const swift::SerialExecutorWitnessTable *wtable);
|
|
#pragma clang diagnostic pop
|
|
|
|
/// WARNING: This method is expected to CRASH in new runtimes, and cannot be
|
|
/// used to implement "log warnings" mode. We would need a new entry point to
|
|
/// implement a "only log warnings" actor isolation checking mode, and it would
|
|
/// no be able handle more complex situations, as `SerialExecutor.checkIsolated`
|
|
/// is able to (by calling into dispatchPrecondition on old runtimes).
|
|
static SWIFT_CC(swift) bool
|
|
swift_task_isOnExecutorImpl(swift::HeapObject *executor,
|
|
const swift::Metadata *selfType,
|
|
const swift::SerialExecutorWitnessTable *wtable)
|
|
{
|
|
auto executorRef = _task_serialExecutor_getExecutorRef(executor,
|
|
selfType,
|
|
wtable);
|
|
return swift_task_isCurrentExecutor(executorRef);
|
|
}
|
|
|
|
bool
|
|
swift::swift_task_isOnExecutor(HeapObject *executor,
|
|
const Metadata *selfType,
|
|
const SerialExecutorWitnessTable *wtable) {
|
|
if (SWIFT_UNLIKELY(swift_task_isOnExecutor_hook))
|
|
return swift_task_isOnExecutor_hook(
|
|
executor, selfType, wtable, swift_task_isOnExecutorImpl);
|
|
else
|
|
return swift_task_isOnExecutorImpl(executor, selfType, wtable);
|
|
}
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_enqueueMainExecutorOrig(Job *job) {
|
|
swift_task_enqueueMainExecutorImpl(reinterpret_cast<SwiftJob *>(job));
|
|
}
|
|
|
|
void
|
|
swift::swift_task_enqueueMainExecutor(Job *job) {
|
|
concurrency::trace::job_enqueue_main_executor(job);
|
|
if (SWIFT_UNLIKELY(swift_task_enqueueMainExecutor_hook))
|
|
swift_task_enqueueMainExecutor_hook(job, swift_task_enqueueMainExecutorOrig);
|
|
else
|
|
swift_task_enqueueMainExecutorOrig(job);
|
|
}
|
|
|
|
SWIFT_CC(swift) static swift::SerialExecutorRef
|
|
swift_task_getMainExecutorOrig() {
|
|
auto ref = swift_task_getMainExecutorImpl();
|
|
return *reinterpret_cast<SerialExecutorRef *>(&ref);
|
|
}
|
|
|
|
swift::SerialExecutorRef
|
|
swift::swift_task_getMainExecutor() {
|
|
if (SWIFT_UNLIKELY(swift_task_getMainExecutor_hook))
|
|
return swift_task_getMainExecutor_hook(swift_task_getMainExecutorOrig);
|
|
else {
|
|
return swift_task_getMainExecutorOrig();
|
|
}
|
|
}
|
|
|
|
SWIFT_CC(swift) static bool
|
|
swift_task_isMainExecutorOrig(SerialExecutorRef executor) {
|
|
return swift_task_isMainExecutorImpl(
|
|
*reinterpret_cast<SwiftExecutorRef *>(&executor));
|
|
}
|
|
|
|
bool
|
|
swift::swift_task_isMainExecutor(SerialExecutorRef executor) {
|
|
if (SWIFT_UNLIKELY(swift_task_isMainExecutor_hook))
|
|
return swift_task_isMainExecutor_hook(
|
|
executor, swift_task_isMainExecutorOrig);
|
|
else
|
|
return swift_task_isMainExecutorOrig(executor);
|
|
}
|
|
|
|
SWIFT_CC(swift) static void
|
|
swift_task_donateThreadToGlobalExecutorUntilOrig(bool (*condition)(void *),
|
|
void *context) {
|
|
return swift_task_donateThreadToGlobalExecutorUntilImpl(condition, context);
|
|
}
|
|
|
|
void swift::
|
|
swift_task_donateThreadToGlobalExecutorUntil(bool (*condition)(void *),
|
|
void *context) {
|
|
if (SWIFT_UNLIKELY(swift_task_donateThreadToGlobalExecutorUntil_hook))
|
|
return swift_task_donateThreadToGlobalExecutorUntil_hook(
|
|
condition, context,
|
|
swift_task_donateThreadToGlobalExecutorUntilOrig);
|
|
else
|
|
return swift_task_donateThreadToGlobalExecutorUntilOrig(condition, context);
|
|
}
|
|
|
|
SWIFT_CC(swift)
|
|
__attribute__((__cold__)) bool
|
|
swift::_swift_task_setTimeSpentRunningTracked(bool isTracked) {
|
|
return AsyncTask::setTimeSpentRunningTracked(isTracked);
|
|
}
|
|
|
|
SWIFT_CC(swift)
|
|
__attribute__((__cold__)) bool
|
|
swift::_swift_task_getTimeSpentRunning(AsyncTask *task,
|
|
uint64_t *outNanoseconds) {
|
|
*outNanoseconds = task->getTimeSpentRunning();
|
|
return AsyncTask::isTimeSpentRunningTracked();
|
|
}
|