File indexing completed on 2024-12-01 11:09:55

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 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #pragma once
0011 
0012 #include <kwinglobals.h>
0013 
0014 #include <QFile>
0015 #include <QMutex>
0016 #include <QMutexLocker>
0017 #include <QObject>
0018 #include <QTextStream>
0019 
0020 namespace KWin
0021 {
0022 /**
0023  * FTraceLogger is a singleton utility for writing log messages using ftrace
0024  *
0025  * Usage: Either:
0026  *  Set the KWIN_PERF_FTRACE environment variable before starting the application
0027  *  Calling on DBus /FTrace org.kde.kwin.FTrace.setEnabled true
0028  * After having created the ftrace mount
0029  */
0030 class KWIN_EXPORT FTraceLogger : public QObject
0031 {
0032     Q_OBJECT
0033     Q_CLASSINFO("D-Bus Interface", "org.kde.kwin.FTrace");
0034     Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY enabledChanged)
0035 
0036 public:
0037     /**
0038      * Enabled through DBus and logging has started
0039      */
0040     bool isEnabled() const;
0041 
0042     /**
0043      * Main log function
0044      * Takes any number of arguments that can be written into QTextStream
0045      */
0046     template<typename... Args>
0047     void trace(Args... args)
0048     {
0049         Q_ASSERT(isEnabled());
0050         QMutexLocker lock(&m_mutex);
0051         if (!m_file.isOpen()) {
0052             return;
0053         }
0054         QTextStream stream(&m_file);
0055         (stream << ... << args) << Qt::endl;
0056     }
0057 
0058 Q_SIGNALS:
0059     void enabledChanged();
0060 
0061 public Q_SLOTS:
0062     Q_SCRIPTABLE void setEnabled(bool enabled);
0063 
0064 private:
0065     static QString filePath();
0066     bool open();
0067     QFile m_file;
0068     QMutex m_mutex;
0069     KWIN_SINGLETON(FTraceLogger)
0070 };
0071 
0072 class KWIN_EXPORT FTraceDuration
0073 {
0074 public:
0075     template<typename... Args>
0076     FTraceDuration(Args... args)
0077     {
0078         static QAtomicInteger<quint32> s_context = 0;
0079         QTextStream stream(&m_message);
0080         (stream << ... << args);
0081         stream.flush();
0082         m_context = ++s_context;
0083         FTraceLogger::self()->trace(m_message, " begin_ctx=", m_context);
0084     }
0085 
0086     ~FTraceDuration();
0087 
0088 private:
0089     QByteArray m_message;
0090     quint32 m_context;
0091 };
0092 
0093 } // namespace KWin
0094 
0095 /**
0096  * Optimised macro, arguments are only copied if tracing is enabled
0097  */
0098 #define fTrace(...)                              \
0099     if (KWin::FTraceLogger::self()->isEnabled()) \
0100         KWin::FTraceLogger::self()->trace(__VA_ARGS__);
0101 
0102 /**
0103  * Will insert two markers into the log. Once when called, and the second at the end of the relevant block
0104  * In GPUVis this will appear as a timed block with begin_ctx and end_ctx markers
0105  */
0106 #define fTraceDuration(...) \
0107     std::unique_ptr<KWin::FTraceDuration> _duration(KWin::FTraceLogger::self()->isEnabled() ? new KWin::FTraceDuration(__VA_ARGS__) : nullptr);