File indexing completed on 2024-05-12 17:00:15

0001 /*
0002     SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "freebsdbackend.h"
0008 
0009 #include <systemstats/SensorObject.h>
0010 #include <systemstats/SensorProperty.h>
0011 #include <systemstats/SysctlSensor.h>
0012 
0013 #include <fcntl.h>
0014 #include <sys/types.h>
0015 #include <sys/sysctl.h>
0016 #include <unistd.h>
0017 
0018 template <typename T>
0019 bool readSysctl(const char *name, T *buffer, size_t size = sizeof(T))
0020 {
0021     return sysctlbyname(name, buffer, &size, nullptr, 0) != -1;
0022 }
0023 
0024 FreeBsdMemoryBackend::FreeBsdMemoryBackend(KSysGuard::SensorContainer* container)
0025     : MemoryBackend(container)
0026     , m_pageSize(getpagesize())
0027     , m_kd(nullptr)
0028 {
0029     char errorBuffer[_POSIX2_LINE_MAX];
0030     // Get a descriptor for accesing kernel memory which we need for querying swap info. /dev/null
0031     // indicates that we do not want to directly access kernel memory.
0032     m_kd = kvm_openfiles(nullptr, "/dev/null", nullptr, O_RDONLY, errorBuffer);
0033     if (!m_kd) {
0034         qWarning() << errorBuffer;
0035     }
0036 }
0037 
0038 void FreeBsdMemoryBackend::makeSensors()
0039 {
0040     auto totalSensor = new KSysGuard::SysctlSensor<unsigned long long>(QStringLiteral("total"), "hw.physmem",  m_physicalObject);
0041     m_total = totalSensor;
0042     m_sysctlSensors.append(totalSensor);
0043 
0044     m_used = new KSysGuard::SensorProperty(QStringLiteral("used"), m_physicalObject);
0045     m_application = new KSysGuard::SensorProperty(QStringLiteral("application"), m_physicalObject);
0046 
0047     auto capturedPagesToBytes = [this] (auto pages) {return pagesToBytes(pages);};
0048 
0049     auto freeSensor = new KSysGuard::SysctlSensor<uint32_t>(QStringLiteral("free"), "vm.stats.vm.v_free_count", m_physicalObject);
0050     freeSensor->setConversionFunction(capturedPagesToBytes);
0051     m_free = freeSensor;
0052     m_sysctlSensors.push_back(freeSensor);
0053 
0054     auto cacheSensor = new KSysGuard::SysctlSensor<uint32_t>(QStringLiteral("cache"),"vm.stats.vm.v_cache_count", m_physicalObject);
0055     cacheSensor->setConversionFunction(capturedPagesToBytes);
0056     m_cache = cacheSensor;
0057     m_sysctlSensors.push_back(cacheSensor);
0058 
0059     auto bufferSensor = new KSysGuard::SysctlSensor<uint64_t>(QStringLiteral("buffer"), "vfs.bufspace", m_physicalObject);
0060     m_buffer = bufferSensor;
0061     m_sysctlSensors.push_back(bufferSensor);
0062 
0063     m_swapTotal = new KSysGuard::SensorProperty(QStringLiteral("total"), m_swapObject);
0064     m_swapUsed = new KSysGuard::SensorProperty(QStringLiteral("used"), m_swapObject);
0065     m_swapFree = new KSysGuard::SensorProperty(QStringLiteral("free"), m_swapObject);
0066 
0067 }
0068 
0069 unsigned long long FreeBsdMemoryBackend::pagesToBytes(uint32_t pages)
0070 {
0071     return m_pageSize * pages;
0072 }
0073 
0074 void FreeBsdMemoryBackend::update()
0075 {
0076 
0077     kvm_swap swapInfo;
0078     // Calling it with just one swapInfo gets us the totals, passing 0 as the last argument is mandatory
0079     if (m_swapObject->isSubscribed() && m_kd && (kvm_getswapinfo(m_kd, &swapInfo, 1, 0) != -1)) {
0080         m_swapTotal->setValue(pagesToBytes(swapInfo.ksw_total));
0081         m_swapUsed->setValue(pagesToBytes(swapInfo.ksw_used));
0082         m_swapFree->setValue(pagesToBytes(swapInfo.ksw_total - swapInfo.ksw_used));
0083     }
0084 
0085     for (const auto sysctlSensor : m_sysctlSensors) {
0086         sysctlSensor->update();
0087     }
0088 
0089     m_used->setValue(m_total->value().toULongLong() - m_free->value().toULongLong());
0090 
0091     uint32_t activePages = 0;
0092     uint32_t inactivePages = 0;
0093     if (readSysctl("vm.stats.vm.v_active_count", &activePages) && readSysctl("vm.stats.vm.v_inactive_count", &inactivePages)) {
0094         m_application->setValue(pagesToBytes(activePages + inactivePages));
0095     }
0096 }
0097 
0098