mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[Concurrency] Emit async task running/waitingOn metadata inline into CPUTrace.
This allows tracking async code execution throughout a task's lifetime. rdar://137230240
This commit is contained in:
@@ -728,10 +728,11 @@ public:
|
||||
return record_iterator::rangeBeginning(getInnermostRecord());
|
||||
}
|
||||
|
||||
void traceStatusChanged(AsyncTask *task, bool isStarting) {
|
||||
void traceStatusChanged(AsyncTask *task, bool isStarting, bool wasRunning) {
|
||||
concurrency::trace::task_status_changed(
|
||||
task, static_cast<uint8_t>(getStoredPriority()), isCancelled(),
|
||||
isStoredPriorityEscalated(), isStarting, isRunning(), isEnqueued());
|
||||
isStoredPriorityEscalated(), isStarting, isRunning(), isEnqueued(),
|
||||
wasRunning);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -971,7 +972,7 @@ inline void AsyncTask::flagAsRunning() {
|
||||
if (_private()._status().compare_exchange_weak(oldStatus, newStatus,
|
||||
/* success */ std::memory_order_relaxed,
|
||||
/* failure */ std::memory_order_relaxed)) {
|
||||
newStatus.traceStatusChanged(this, true);
|
||||
newStatus.traceStatusChanged(this, true, oldStatus.isRunning());
|
||||
adoptTaskVoucher(this);
|
||||
swift_task_enterThreadLocalContext(
|
||||
(char *)&_private().ExclusivityAccessSet[0]);
|
||||
|
||||
@@ -94,8 +94,9 @@ static void withStatusRecordLock(
|
||||
status, newStatus,
|
||||
/*success*/ SWIFT_MEMORY_ORDER_CONSUME,
|
||||
/*failure*/ std::memory_order_relaxed)) {
|
||||
bool wasRunning = status.isRunning();
|
||||
status = newStatus;
|
||||
status.traceStatusChanged(task, false);
|
||||
status.traceStatusChanged(task, false, wasRunning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -130,7 +131,7 @@ static void withStatusRecordLock(
|
||||
status, newStatus,
|
||||
/*success*/ std::memory_order_relaxed,
|
||||
/*failure*/ std::memory_order_relaxed)) {
|
||||
newStatus.traceStatusChanged(task, false);
|
||||
newStatus.traceStatusChanged(task, false, status.isRunning());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -196,7 +197,7 @@ bool swift::addStatusRecord(AsyncTask *task, TaskStatusRecord *newRecord,
|
||||
if (task->_private()._status().compare_exchange_weak(oldStatus, newStatus,
|
||||
/*success*/ std::memory_order_release,
|
||||
/*failure*/ std::memory_order_relaxed)) {
|
||||
newStatus.traceStatusChanged(task, false);
|
||||
newStatus.traceStatusChanged(task, false, oldStatus.isRunning());
|
||||
return true;
|
||||
} else {
|
||||
// Retry
|
||||
@@ -302,7 +303,7 @@ void swift::removeStatusRecord(AsyncTask *task, TaskStatusRecord *record,
|
||||
oldStatus, newStatus,
|
||||
/*success*/ std::memory_order_relaxed,
|
||||
/*failure*/ std::memory_order_relaxed)) {
|
||||
newStatus.traceStatusChanged(task, false);
|
||||
newStatus.traceStatusChanged(task, false, oldStatus.isRunning());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -904,7 +905,7 @@ static void swift_task_cancelImpl(AsyncTask *task) {
|
||||
}
|
||||
}
|
||||
|
||||
newStatus.traceStatusChanged(task, false);
|
||||
newStatus.traceStatusChanged(task, false, oldStatus.isRunning());
|
||||
if (newStatus.getInnermostRecord() == nullptr) {
|
||||
// No records, nothing to propagate
|
||||
return;
|
||||
|
||||
@@ -63,7 +63,8 @@ void task_create(AsyncTask *task, AsyncTask *parent, TaskGroup *group,
|
||||
void task_destroy(AsyncTask *task);
|
||||
|
||||
void task_status_changed(AsyncTask *task, uint8_t maxPriority, bool isCancelled,
|
||||
bool isEscalated, bool isStarting, bool isRunning, bool isEnqueued);
|
||||
bool isEscalated, bool isStarting, bool isRunning,
|
||||
bool isEnqueued, bool wasRunning);
|
||||
|
||||
void task_flags_changed(AsyncTask *task, uint8_t jobPriority, bool isChildTask,
|
||||
bool isFuture, bool isGroupChildTask,
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#include <os/log.h>
|
||||
#include <os/signpost.h>
|
||||
|
||||
#if defined(__arm64__) && __has_include(<os/apt_private.h>)
|
||||
#include <os/apt_private.h>
|
||||
#endif
|
||||
|
||||
// Compatibility notes:
|
||||
//
|
||||
// These signposts can be read by external software that isn't synced with the
|
||||
@@ -210,7 +214,24 @@ inline void task_destroy(AsyncTask *task) {
|
||||
|
||||
inline void task_status_changed(AsyncTask *task, uint8_t maxPriority,
|
||||
bool isCancelled, bool isEscalated,
|
||||
bool isStarting, bool isRunning, bool isEnqueued) {
|
||||
bool isStarting, bool isRunning,
|
||||
bool isEnqueued, bool wasRunning) {
|
||||
#if !TARGET_OS_SIMULATOR
|
||||
#if OS_APT_SPI_VERSION >= 20241023
|
||||
uint64_t taskId = task->getTaskId();
|
||||
if (isRunning) {
|
||||
if (SWIFT_RUNTIME_WEAK_CHECK(os_apt_msg_async_task_running_4swift)) {
|
||||
SWIFT_RUNTIME_WEAK_USE(os_apt_msg_async_task_running_4swift(taskId));
|
||||
}
|
||||
} else if (!isRunning && wasRunning) {
|
||||
#if OS_APT_SPI_VERSION >= 20250710
|
||||
if (SWIFT_RUNTIME_WEAK_CHECK(os_apt_msg_async_task_stopped_4swift)) {
|
||||
SWIFT_RUNTIME_WEAK_USE(os_apt_msg_async_task_stopped_4swift(taskId));
|
||||
}
|
||||
#endif // OS_APT_SPI_VERSION >= 20250710
|
||||
}
|
||||
#endif // OS_APT_SPI_VERSION >= 20241023
|
||||
#endif // !TARGET_OS_SIMULATOR
|
||||
ENSURE_LOGS();
|
||||
auto id = os_signpost_id_make_with_pointer(TaskLog, task);
|
||||
os_signpost_event_emit(
|
||||
|
||||
@@ -56,7 +56,8 @@ inline void task_resume(AsyncTask *task) {}
|
||||
|
||||
inline void task_status_changed(AsyncTask *task, uint8_t maxPriority,
|
||||
bool isCancelled, bool isEscalated,
|
||||
bool isStarting, bool isRunning, bool isEnqueued) {}
|
||||
bool isStarting, bool isRunning,
|
||||
bool isEnqueued, bool wasRunning) {}
|
||||
|
||||
inline void task_flags_changed(AsyncTask *task, uint8_t jobPriority,
|
||||
bool isChildTask, bool isFuture,
|
||||
|
||||
Reference in New Issue
Block a user