File indexing completed on 2024-02-18 16:19:59

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2021 David Edmundson <davidedmundson@kde.org>
0006     SPDX-FileCopyrightText: 2020 Roman Gilg <subdiff@gmail.com>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #include "ftrace.h"
0012 
0013 #include <QDBusConnection>
0014 #include <QDebug>
0015 #include <QDir>
0016 #include <QFile>
0017 #include <QFileInfo>
0018 #include <QScopeGuard>
0019 #include <QTextStream>
0020 
0021 namespace KWin
0022 {
0023 KWIN_SINGLETON_FACTORY(KWin::FTraceLogger)
0024 
0025 FTraceLogger::FTraceLogger(QObject *parent)
0026     : QObject(parent)
0027 {
0028     if (qEnvironmentVariableIsSet("KWIN_PERF_FTRACE")) {
0029         setEnabled(true);
0030     } else {
0031         QDBusConnection::sessionBus().registerObject(QStringLiteral("/FTrace"), this, QDBusConnection::ExportScriptableContents);
0032     }
0033 }
0034 
0035 bool FTraceLogger::isEnabled() const
0036 {
0037     return m_file.isOpen();
0038 }
0039 
0040 void FTraceLogger::setEnabled(bool enabled)
0041 {
0042     QMutexLocker lock(&m_mutex);
0043     if (enabled == isEnabled()) {
0044         return;
0045     }
0046 
0047     if (enabled) {
0048         open();
0049     } else {
0050         m_file.close();
0051     }
0052     Q_EMIT enabledChanged();
0053 }
0054 
0055 bool FTraceLogger::open()
0056 {
0057     const QString path = filePath();
0058     if (path.isEmpty()) {
0059         return false;
0060     }
0061 
0062     m_file.setFileName(path);
0063     if (!m_file.open(QIODevice::WriteOnly)) {
0064         qWarning() << "No access to trace marker file at:" << path;
0065     }
0066     return true;
0067 }
0068 
0069 QString FTraceLogger::filePath()
0070 {
0071     if (qEnvironmentVariableIsSet("KWIN_PERF_FTRACE_FILE")) {
0072         return qgetenv("KWIN_PERF_FTRACE_FILE");
0073     }
0074 
0075     QFile mountsFile("/proc/mounts");
0076     if (!mountsFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
0077         qWarning() << "No access to mounts file. Can not determine trace marker file location.";
0078         return QString();
0079     }
0080 
0081     auto lineInfo = [](const QString &line) {
0082         const int start = line.indexOf(' ') + 1;
0083         const int end = line.indexOf(' ', start);
0084         const QString dirPath(line.mid(start, end - start));
0085         if (dirPath.isEmpty() || !QFileInfo::exists(dirPath)) {
0086             return QFileInfo();
0087         }
0088         return QFileInfo(QDir(dirPath), QStringLiteral("trace_marker"));
0089     };
0090     QFileInfo markerFileInfo;
0091     QTextStream mountsIn(&mountsFile);
0092     QString mountsLine = mountsIn.readLine();
0093 
0094     while (!mountsLine.isNull()) {
0095         if (mountsLine.startsWith("tracefs")) {
0096             const auto info = lineInfo(mountsLine);
0097             if (info.exists()) {
0098                 markerFileInfo = info;
0099                 break;
0100             }
0101         }
0102         if (mountsLine.startsWith("debugfs")) {
0103             markerFileInfo = lineInfo(mountsLine);
0104         }
0105         mountsLine = mountsIn.readLine();
0106     }
0107     mountsFile.close();
0108     if (!markerFileInfo.exists()) {
0109         qWarning() << "Could not determine trace marker file location from mounts.";
0110         return QString();
0111     }
0112 
0113     return markerFileInfo.absoluteFilePath();
0114 }
0115 
0116 FTraceDuration::~FTraceDuration()
0117 {
0118     FTraceLogger::self()->trace(m_message, " end_ctx=", m_context);
0119 }
0120 
0121 }