diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index ea69c393..847d835e 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -171,7 +171,7 @@
-
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index e8819751..b433d2e9 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -6,6 +6,7 @@
+
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 21f7d268..eba3b1e7 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -32,9 +32,10 @@ include_directories("libraries/frozen/include")
find_package(mbedtls REQUIRED CONFIG)
-# Define a static library for Perfetto.
+# Perfetto SDK
include_directories(libraries/perfetto/sdk)
add_library(perfetto STATIC libraries/perfetto/sdk/perfetto.cc)
+target_compile_options(perfetto PRIVATE -Wno-everything)
include_directories(${source_DIR}/skyline)
@@ -45,7 +46,7 @@ add_library(skyline SHARED
${source_DIR}/skyline/common/settings.cpp
${source_DIR}/skyline/common/signal.cpp
${source_DIR}/skyline/common/uuid.cpp
- ${source_DIR}/skyline/common/tracing.cpp
+ ${source_DIR}/skyline/common/trace.cpp
${source_DIR}/skyline/nce/guest.S
${source_DIR}/skyline/nce.cpp
${source_DIR}/skyline/jvm.cpp
diff --git a/app/src/main/cpp/emu_jni.cpp b/app/src/main/cpp/emu_jni.cpp
index 6a52a10c..898e804b 100644
--- a/app/src/main/cpp/emu_jni.cpp
+++ b/app/src/main/cpp/emu_jni.cpp
@@ -10,7 +10,7 @@
#include "skyline/common.h"
#include "skyline/common/signal.h"
#include "skyline/common/settings.h"
-#include "skyline/common/tracing.h"
+#include "skyline/common/trace.h"
#include "skyline/loader/loader.h"
#include "skyline/vfs/android_asset_filesystem.h"
#include "skyline/os.h"
@@ -80,14 +80,14 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
env->ReleaseStringUTFChars(appFilesPathJstring, appFilesPath);
auto romUri{env->GetStringUTFChars(romUriJstring, nullptr)};
- logger->Info("Launching ROM {}", romUri);
+ logger->InfoNoPrefix("Launching ROM {}", romUri);
env->ReleaseStringUTFChars(romUriJstring, romUri);
os->Execute(romFd, static_cast(romType));
} catch (std::exception &e) {
- logger->Error(e.what());
+ logger->Error("An exception has occurred: {}", e.what());
} catch (const skyline::signal::SignalException &e) {
- logger->Error(e.what());
+ logger->Error("An exception has occurred: {}", e.what());
} catch (...) {
logger->Error("An unknown exception has occurred");
}
@@ -96,10 +96,10 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(
InputWeak.reset();
- logger->Info("Emulation has ended");
+ logger->InfoNoPrefix("Emulation has ended");
auto end{std::chrono::steady_clock::now()};
- logger->Info("Done in: {} ms", (std::chrono::duration_cast(end - start).count()));
+ logger->InfoNoPrefix("Done in: {} ms", (std::chrono::duration_cast(end - start).count()));
close(romFd);
}
diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h
index 762b1926..41209836 100644
--- a/app/src/main/cpp/skyline/common.h
+++ b/app/src/main/cpp/skyline/common.h
@@ -145,6 +145,14 @@ namespace skyline {
else
return object;
}
+
+ /**
+ * @brief {fmt}::format but with FmtCast built into it
+ */
+ template
+ auto Format(S formatString, Args &&... args) {
+ return fmt::format(formatString, FmtCast(args)...);
+ }
}
/**
diff --git a/app/src/main/cpp/skyline/common/trace.cpp b/app/src/main/cpp/skyline/common/trace.cpp
new file mode 100644
index 00000000..323acf4f
--- /dev/null
+++ b/app/src/main/cpp/skyline/common/trace.cpp
@@ -0,0 +1,3 @@
+#include "trace.h"
+
+PERFETTO_TRACK_EVENT_STATIC_STORAGE(); //!< Expands into a structure with static storage for all track events
diff --git a/app/src/main/cpp/skyline/common/trace.h b/app/src/main/cpp/skyline/common/trace.h
new file mode 100644
index 00000000..78435aa9
--- /dev/null
+++ b/app/src/main/cpp/skyline/common/trace.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include
+#include
+#include
+
+#define TRACE_EVENT_FMT(category, formatString, ...) TRACE_EVENT("kernel", nullptr, [&](perfetto::EventContext ctx) { \
+ ctx.event()->set_name(skyline::util::Format(formatString, __VA_ARGS__)); \
+})
+
+PERFETTO_DEFINE_CATEGORIES(
+ perfetto::Category("scheduler").SetDescription("Events from the HLE scheduler"),
+ perfetto::Category("kernel").SetDescription("Events from parts of the HLE kernel"),
+ perfetto::Category("guest").SetDescription("Events relating to guest code"),
+ perfetto::Category("gpu").SetDescription("Events from the emulated GPU"),
+ perfetto::Category("service").SetDescription("Events from the HLE sysmodule implementations")
+);
+
+namespace skyline::trace {
+ /**
+ * @brief Perfetto track IDs for custom tracks, counting down from U64 max to avoid conflicts
+ */
+ enum class TrackIds : u64 {
+ Presentation = std::numeric_limits::max(),
+ };
+}
diff --git a/app/src/main/cpp/skyline/common/tracing.cpp b/app/src/main/cpp/skyline/common/tracing.cpp
deleted file mode 100644
index 012cb1b7..00000000
--- a/app/src/main/cpp/skyline/common/tracing.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "tracing.h"
-
-PERFETTO_TRACK_EVENT_STATIC_STORAGE();
diff --git a/app/src/main/cpp/skyline/common/tracing.h b/app/src/main/cpp/skyline/common/tracing.h
deleted file mode 100644
index 9b96172a..00000000
--- a/app/src/main/cpp/skyline/common/tracing.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-
-PERFETTO_DEFINE_CATEGORIES(perfetto::Category("sched").SetDescription("Events from the scheduler"),
- perfetto::Category("kernel").SetDescription("Events from parts of the kernel"),
- perfetto::Category("guest").SetDescription("Events relating to guest code"),
- perfetto::Category("gpu").SetDescription("Events from the emulated GPU"));
-
-namespace skyline::tracing {
- /**
- * @brief Perfetto track IDs for custom tracks, counting down from U64 max to avoid conflicts
- */
- enum class TrackIds : u64 {
- Presentation = std::numeric_limits::max()
- };
-}
\ No newline at end of file
diff --git a/app/src/main/cpp/skyline/gpu/presentation_engine.cpp b/app/src/main/cpp/skyline/gpu/presentation_engine.cpp
index 184b28dd..1f75249c 100644
--- a/app/src/main/cpp/skyline/gpu/presentation_engine.cpp
+++ b/app/src/main/cpp/skyline/gpu/presentation_engine.cpp
@@ -9,7 +9,7 @@ extern skyline::u16 Fps;
extern skyline::u32 FrameTime;
namespace skyline::gpu {
- PresentationEngine::PresentationEngine(const DeviceState &state) : state(state), vsyncEvent(std::make_shared(state, true)), bufferEvent(std::make_shared(state, true)), presentationTrack(static_cast(tracing::TrackIds::Presentation), perfetto::ProcessTrack::Current()) {
+ PresentationEngine::PresentationEngine(const DeviceState &state) : state(state), vsyncEvent(std::make_shared(state, true)), bufferEvent(std::make_shared(state, true)), presentationTrack(static_cast(trace::TrackIds::Presentation), perfetto::ProcessTrack::Current()) {
auto desc{presentationTrack.Serialize()};
desc.set_name("Presentation");
perfetto::TrackEvent::SetTrackDescriptor(presentationTrack, desc);
diff --git a/app/src/main/cpp/skyline/gpu/presentation_engine.h b/app/src/main/cpp/skyline/gpu/presentation_engine.h
index 9e1bb7a0..41b3503d 100644
--- a/app/src/main/cpp/skyline/gpu/presentation_engine.h
+++ b/app/src/main/cpp/skyline/gpu/presentation_engine.h
@@ -3,7 +3,7 @@
#pragma once
-#include
+#include
#include
#include "texture.h"
diff --git a/app/src/main/cpp/skyline/gpu/texture.cpp b/app/src/main/cpp/skyline/gpu/texture.cpp
index 5bbe4e7e..6daca687 100644
--- a/app/src/main/cpp/skyline/gpu/texture.cpp
+++ b/app/src/main/cpp/skyline/gpu/texture.cpp
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
-#include
+#include
#include
#include
#include
diff --git a/app/src/main/cpp/skyline/kernel/scheduler.cpp b/app/src/main/cpp/skyline/kernel/scheduler.cpp
index 41ef946d..8cbda4c5 100644
--- a/app/src/main/cpp/skyline/kernel/scheduler.cpp
+++ b/app/src/main/cpp/skyline/kernel/scheduler.cpp
@@ -3,7 +3,7 @@
#include
#include
-#include
+#include
#include "types/KThread.h"
#include "scheduler.h"
@@ -13,19 +13,18 @@ namespace skyline::kernel {
Scheduler::Scheduler(const DeviceState &state) : state(state) {}
void Scheduler::SignalHandler(int signal, siginfo *info, ucontext *ctx, void **tls) {
- TRACE_EVENT_END("guest");
-
if (*tls) {
+ TRACE_EVENT_END("guest");
const auto &state{*reinterpret_cast(*tls)->state};
if (signal == PreemptionSignal)
state.thread->isPreempted = false;
state.scheduler->Rotate(false);
YieldPending = false;
state.scheduler->WaitSchedule();
+ TRACE_EVENT_BEGIN("guest", "Guest");
} else {
YieldPending = true;
}
- TRACE_EVENT_BEGIN("guest", "Guest");
}
Scheduler::CoreContext &Scheduler::GetOptimalCoreForThread(const std::shared_ptr &thread) {
@@ -154,7 +153,7 @@ namespace skyline::kernel {
return !core->queue.empty() && core->queue.front() == thread;
}};
- TRACE_EVENT("sched", "WaitSchedule");
+ TRACE_EVENT("scheduler", "WaitSchedule");
if (loadBalance && thread->affinityMask.count() > 1) {
std::chrono::milliseconds loadBalanceThreshold{PreemptiveTimeslice * 2}; //!< The amount of time that needs to pass unscheduled for a thread to attempt load balancing
while (!thread->scheduleCondition.wait_for(lock, loadBalanceThreshold, wakeFunction)) {
@@ -182,7 +181,7 @@ namespace skyline::kernel {
auto &thread{state.thread};
auto *core{&cores.at(thread->coreId)};
- TRACE_EVENT("sched", "TimedWaitSchedule");
+ TRACE_EVENT("scheduler", "TimedWaitSchedule");
std::unique_lock lock(core->mutex);
if (thread->scheduleCondition.wait_for(lock, timeout, [&]() {
if (!thread->affinityMask.test(thread->coreId)) [[unlikely]] {
diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp
index 7e0899bc..5690f790 100644
--- a/app/src/main/cpp/skyline/kernel/svc.cpp
+++ b/app/src/main/cpp/skyline/kernel/svc.cpp
@@ -3,7 +3,7 @@
#include
#include
-#include
+#include
#include
#include "results.h"
#include "svc.h"
@@ -287,11 +287,10 @@ namespace skyline::kernel::svc {
constexpr i64 yieldWithCoreMigration{-1};
constexpr i64 yieldToAnyThread{-2};
- TRACE_EVENT("kernel", "SleepThread");
-
i64 in{static_cast(state.ctx->gpr.x0)};
if (in > 0) {
state.logger->Debug("Sleeping for {}ns", in);
+ TRACE_EVENT("kernel", "SleepThread", "duration", in);
struct timespec spec{
.tv_sec = static_cast(in / 1000000000),
@@ -302,22 +301,30 @@ namespace skyline::kernel::svc {
nanosleep(&spec, nullptr);
} else {
switch (in) {
- case yieldWithCoreMigration:
+ case yieldWithCoreMigration: {
state.logger->Debug("Waking any appropriate parked threads and yielding");
+ TRACE_EVENT("kernel", "YieldWithCoreMigration");
state.scheduler->WakeParkedThread();
- [[fallthrough]];
- case yieldWithoutCoreMigration:
- if (in == yieldWithoutCoreMigration)
- state.logger->Debug("Cooperative yield");
state.scheduler->Rotate();
state.scheduler->WaitSchedule();
break;
+ }
- case yieldToAnyThread:
+ case yieldWithoutCoreMigration: {
+ state.logger->Debug("Cooperative yield");
+ TRACE_EVENT("kernel", "YieldWithoutCoreMigration");
+ state.scheduler->Rotate();
+ state.scheduler->WaitSchedule();
+ break;
+ }
+
+ case yieldToAnyThread: {
state.logger->Debug("Parking current thread");
+ TRACE_EVENT("kernel", "YieldToAnyThread");
state.scheduler->ParkThread();
state.scheduler->WaitSchedule(false);
break;
+ }
default:
break;
@@ -453,6 +460,7 @@ namespace skyline::kernel::svc {
void ClearEvent(const DeviceState &state) {
KHandle handle{state.ctx->gpr.w0};
+ TRACE_EVENT_FMT("kernel", "ClearEvent 0x{:X}", handle);
try {
std::static_pointer_cast(state.process->GetHandle(handle))->ResetSignal();
state.logger->Debug("Clearing 0x{:X}", handle);
@@ -543,6 +551,7 @@ namespace skyline::kernel::svc {
void ResetSignal(const DeviceState &state) {
KHandle handle{state.ctx->gpr.w0};
+ TRACE_EVENT_FMT("kernel", "ResetSignal 0x{:X}", handle);
try {
auto object{state.process->GetHandle(handle)};
switch (object->objectType) {
@@ -601,11 +610,13 @@ namespace skyline::kernel::svc {
i64 timeout{static_cast(state.ctx->gpr.x3)};
if (waitHandles.size() == 1) {
state.logger->Debug("Waiting on 0x{:X} for {}ns", waitHandles[0], timeout);
+ TRACE_EVENT_FMT("kernel", "WaitSynchronization 0x{:X}", waitHandles[0]);
} else if (Logger::LogLevel::Debug <= state.logger->configLevel) {
std::string handleString;
for (const auto &handle : waitHandles)
handleString += fmt::format("* 0x{:X}\n", handle);
state.logger->Debug("Waiting on handles:\n{}Timeout: {}ns", handleString, timeout);
+ TRACE_EVENT("kernel", "WaitSynchronizationMultiple");
}
std::unique_lock lock(type::KSyncObject::syncObjectMutex);
@@ -707,6 +718,7 @@ namespace skyline::kernel::svc {
}
state.logger->Debug("Locking 0x{:X}", mutex);
+ TRACE_EVENT_FMT("kernel", "MutexLock 0x{:X}", mutex);
KHandle ownerHandle{state.ctx->gpr.w0};
KHandle requesterHandle{state.ctx->gpr.w2};
@@ -729,6 +741,8 @@ namespace skyline::kernel::svc {
return;
}
+ TRACE_EVENT_FMT("kernel", "MutexUnlock 0x{:X}", mutex);
+
state.logger->Debug("Unlocking 0x{:X}", mutex);
state.process->MutexUnlock(mutex);
state.logger->Debug("Unlocked 0x{:X}", mutex);
diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp
index b9ab5a59..71c13f8c 100644
--- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp
+++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp
@@ -3,8 +3,8 @@
#include
#include
+#include
#include
-
#include "KProcess.h"
namespace skyline::kernel::type {
@@ -104,6 +104,8 @@ namespace skyline::kernel::type {
constexpr u32 HandleWaitersBit{1UL << 30}; //!< A bit which denotes if a mutex psuedo-handle has waiters or not
Result KProcess::MutexLock(u32 *mutex, KHandle ownerHandle, KHandle tag) {
+ TRACE_EVENT_FMT("kernel", "MutexLock 0x{:X}", mutex);
+
std::shared_ptr owner;
try {
owner = GetHandle(ownerHandle);
@@ -142,6 +144,8 @@ namespace skyline::kernel::type {
}
void KProcess::MutexUnlock(u32 *mutex) {
+ TRACE_EVENT_FMT("kernel", "MutexUnlock 0x{:X}", mutex);
+
std::lock_guard lock(state.thread->waiterMutex);
auto &waiters{state.thread->waiters};
auto nextOwnerIt{std::find_if(waiters.begin(), waiters.end(), [mutex](const std::shared_ptr &thread) { return thread->waitKey == mutex; })};
@@ -203,6 +207,8 @@ namespace skyline::kernel::type {
}
Result KProcess::ConditionalVariableWait(u32 *key, u32 *mutex, KHandle tag, i64 timeout) {
+ TRACE_EVENT_FMT("kernel", "ConditionalVariableWait 0x{:X} (0x{:X})", key, mutex);
+
{
std::lock_guard lock(syncWaiterMutex);
auto queue{syncWaiters.equal_range(key)};
@@ -242,6 +248,8 @@ namespace skyline::kernel::type {
}
void KProcess::ConditionalVariableSignal(u32 *key, i32 amount) {
+ TRACE_EVENT_FMT("kernel", "ConditionalVariableSignal 0x{:X}", key);
+
std::lock_guard lock(syncWaiterMutex);
auto queue{syncWaiters.equal_range(key)};
@@ -254,6 +262,8 @@ namespace skyline::kernel::type {
}
Result KProcess::WaitForAddress(u32 *address, u32 value, i64 timeout, bool (*arbitrationFunction)(u32 *, u32)) {
+ TRACE_EVENT_FMT("kernel", "WaitForAddress 0x{:X}", address);
+
{
std::lock_guard lock(syncWaiterMutex);
if (!arbitrationFunction(address, value)) [[unlikely]]
@@ -287,6 +297,8 @@ namespace skyline::kernel::type {
}
Result KProcess::SignalToAddress(u32 *address, u32 value, i32 amount, bool(*mutateFunction)(u32 *address, u32 value, u32 waiterCount)) {
+ TRACE_EVENT_FMT("kernel", "SignalToAddress 0x{:X}", address);
+
std::lock_guard lock(syncWaiterMutex);
auto queue{syncWaiters.equal_range(address)};
diff --git a/app/src/main/cpp/skyline/kernel/types/KThread.cpp b/app/src/main/cpp/skyline/kernel/types/KThread.cpp
index e144c088..35d5ce6f 100644
--- a/app/src/main/cpp/skyline/kernel/types/KThread.cpp
+++ b/app/src/main/cpp/skyline/kernel/types/KThread.cpp
@@ -4,7 +4,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include "KProcess.h"
diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp
index 3a66afed..9c5390e6 100644
--- a/app/src/main/cpp/skyline/nce.cpp
+++ b/app/src/main/cpp/skyline/nce.cpp
@@ -4,7 +4,7 @@
#include
#include
#include "common/signal.h"
-#include "common/tracing.h"
+#include "common/trace.h"
#include "os.h"
#include "jvm.h"
#include "kernel/types/KProcess.h"
@@ -21,6 +21,7 @@ namespace skyline::nce {
auto svc{kernel::svc::SvcTable[svcId]};
try {
if (svc) [[likely]] {
+ TRACE_EVENT("kernel", perfetto::StaticString{svc.name});
(svc.function)(state);
} else [[unlikely]] {
throw exception("Unimplemented SVC 0x{:X}", svcId);
diff --git a/app/src/main/cpp/skyline/services/base_service.cpp b/app/src/main/cpp/skyline/services/base_service.cpp
index fa9f7125..58fab6e6 100644
--- a/app/src/main/cpp/skyline/services/base_service.cpp
+++ b/app/src/main/cpp/skyline/services/base_service.cpp
@@ -2,6 +2,7 @@
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include
+#include
#include "base_service.h"
namespace skyline::service {
@@ -27,6 +28,7 @@ namespace skyline::service {
state.logger->Warn("Cannot find function in service '{0}': 0x{1:X} ({1})", GetName(), static_cast(request.payload->value));
return {};
}
+ TRACE_EVENT("service", perfetto::StaticString{function.name});
try {
return function(session, request, response);
} catch (const std::exception &e) {
diff --git a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp
index ffce3e71..c9f5a702 100644
--- a/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp
+++ b/app/src/main/cpp/skyline/services/nvdrv/devices/nvdevice.cpp
@@ -2,6 +2,7 @@
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include
+#include
#include "nvdevice.h"
namespace skyline::service::nvdrv::device {
@@ -38,6 +39,7 @@ namespace skyline::service::nvdrv::device {
state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd);
return NvStatus::NotImplemented;
}
+ TRACE_EVENT("service", perfetto::StaticString{function.name});
try {
return function(type, buffer, inlineBuffer);
} catch (const std::exception &e) {
diff --git a/app/src/main/cpp/skyline/services/serviceman.cpp b/app/src/main/cpp/skyline/services/serviceman.cpp
index 352bc1ae..79bd735f 100644
--- a/app/src/main/cpp/skyline/services/serviceman.cpp
+++ b/app/src/main/cpp/skyline/services/serviceman.cpp
@@ -2,7 +2,7 @@
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include
-#include
+#include
#include "sm/IUserInterface.h"
#include "settings/ISettingsServer.h"
#include "settings/ISystemSettingsServer.h"