
/***************************************************************************
 *                                                                         *
 *   KCPULoad is copyright (c) 1999-2000, Markus Gustavsson                *
 *                         (c) 2002, Ben Burton                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef __KCPUPROC_H
#define __KCPUPROC_H

#include <cstdio>
#include <qglobal.h>

/**
 * A class used to read raw CPU load details from the system.
 *
 * See kcpuproc.cpp for details of supported operating systems.
 */
class KCPUProc {
public:
    /**
     * Constructor.
     *
     * In the constructor, a set of initial CPU tick readings are taken
     * and SMP support is determined.
     */
    KCPUProc();

    /**
     * Does this system appear to have SMP?
     */
    bool hasSMP() const;

    /**
     * Takes a fresh set of CPU tick readings.  The numerical statistics
     * returned refer to the time period between this reading and the
     * previous (or between this reading and the object's construction
     * if there was no previous reading).
     */
    void readLoad();

    /**
     * The percentage of ticks between the last reading and the previous
     * reading used by the user loop (compared to the nice, system and
     * idle loops).
     *
     * This is measured across all CPUs, CPU 0 and CPU 1 respectively.
     * The CPU-specific routines should only be used if SMP is available.
     *
     * Each of these routines involves a short arithmetical calculation.
     * If you're paranoid about running time, you might want to cache
     * the results.
     */
    int userPercent() const;
    int userPercent0() const;
    int userPercent1() const;

    /**
     * The percentage of ticks between the last reading and the previous
     * reading used by the system and nice loops (compared to the user and
     * idle loops).
     *
     * This is measured across all CPUs, CPU 0 and CPU 1 respectively.
     * The CPU-specific routines should only be used if SMP is available.
     *
     * Each of these routines involves a short arithmetical calculation.
     * If you're paranoid about running time, you might want to cache
     * the results.
     */
    int systemPercent() const;
    int systemPercent0() const;
    int systemPercent1() const;

    /**
     * The percentage of ticks between the last reading and the previous
     * reading used by the user, system and nice loops (compared to the
     * idle loop).
     *
     * This is measured across all CPUs, CPU 0 and CPU 1 respectively.
     * The CPU-specific routines should only be used if SMP is available.
     *
     * Each of these routines involves a short arithmetical calculation.
     * If you're paranoid about running time, you might want to cache
     * the results.
     */
    int totalPercent() const;
    int totalPercent0() const;
    int totalPercent1() const;

private:
    /**
     * SMP support.
     */
    bool smp;
        /**< Does this system appear to have SMP? */

    /**
     * Variables used in all modes.
     */
    int UT, ST, NT, IT;
        /**< Previous user/system/nice/idle tick readings for all CPUs. */
    int cUT, cST, cNT, cIT;
        /**< Current user/system/nice/idle tick readings for all CPUs. */
    int tot;
        /**< Difference between tick totals for the current and previous
             readings for all CPUs. */

    /**
     * Variables used only with SMP.
     */
    int UT0, ST0, NT0, IT0;
        /**< Previous user/system/nice/idle tick readings for CPU 0. */
    int cUT0, cST0, cNT0, cIT0;
        /**< Current user/system/nice/idle tick readings for CPU 0. */
    int tot0;
        /**< Difference between tick totals for the current and previous
             readings for CPU 0. */

    int UT1, ST1, NT1, IT1;
        /**< Previous user/system/nice/idle tick readings for CPU 1. */
    int cUT1, cST1, cNT1, cIT1;
        /**< Current user/system/nice/idle tick readings for CPU 1. */
    int tot1;
        /**< Difference between tick totals for the current and previous
             readings for CPU 1. */

    /**
     * OS-specific data members.
     */

    // ========== Linux-specific (begin) ==========
#ifdef Q_OS_LINUX
    FILE *fd;
        /**< The file /proc/stat. */
    char tag[32];
        /**< The token at the beginning of a line of /proc/stat. */
#endif
    // ========== Linux-specific (end) ==========
};

inline bool KCPUProc::hasSMP() const {
    return smp;
}

inline int KCPUProc::userPercent() const {
    return (tot > 0 ? (100 * (cUT - UT)) / tot : 0);
}
inline int KCPUProc::userPercent0() const {
    return (tot0 > 0 ? (100 * (cUT0 - UT0)) / tot0 : 0);
}
inline int KCPUProc::userPercent1() const {
    return (tot1 > 0 ? (100 * (cUT1 - UT1)) / tot1 : 0);
}

inline int KCPUProc::systemPercent() const {
    return (tot > 0 ? (100 * ((cST - ST) + (cNT - NT))) / tot : 0);
}
inline int KCPUProc::systemPercent0() const {
    return (tot0 > 0 ? (100 * ((cST0 - ST0) + (cNT0 - NT0))) / tot0 : 0);
}
inline int KCPUProc::systemPercent1() const {
    return (tot1 > 0 ? (100 * ((cST1 - ST1) + (cNT1 - NT1))) / tot1 : 0);
}

inline int KCPUProc::totalPercent() const {
    return (tot > 0 ?
        (100 * ((cUT - UT) + (cST - ST) + (cNT - NT))) / tot : 0);
}
inline int KCPUProc::totalPercent0() const {
    return (tot0 > 0 ?
        (100 * ((cUT0 - UT0) + (cST0 - ST0) + (cNT0 - NT0))) / tot0 : 0);
}
inline int KCPUProc::totalPercent1() const {
    return (tot1 > 0 ?
        (100 * ((cUT1 - UT1) + (cST1 - ST1) + (cNT1 - NT1))) / tot1 : 0);
}

#endif
