[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:
Mike Ash
2025-09-04 14:33:49 -04:00
parent 61cb1a9126
commit 0116da253e
5 changed files with 36 additions and 11 deletions

View File

@@ -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]);

View File

@@ -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;

View File

@@ -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,

View File

@@ -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(

View File

@@ -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,