VirtualBox

Changeset 9904 in vbox


Ignore:
Timestamp:
Jun 25, 2008 11:03:03 AM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
32323
Message:

Global and per-VM CPU usage API added

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/system.h

    r8245 r9904  
    3434#include <iprt/types.h>
    3535
     36#define IPRT_USAGE_MULTIPLIER UINT64_C(1000000000)
     37
     38/* This structure holds both computed and raw values of overall CPU load counters. */
     39typedef struct
     40{
     41    uint32_t u32User;
     42    uint32_t u32System;
     43    uint32_t u32Idle;
     44    /* Internal raw counter values. */
     45    uint32_t u32RawUser;
     46    uint32_t u32RawNice;
     47    uint32_t u32RawSystem;
     48    uint32_t u32RawIdle;
     49} RTCPUUSAGESTATS;
     50typedef RTCPUUSAGESTATS *PRTCPUUSAGESTATS;
     51
     52/* This structure holds both computed and raw values of per-VM CPU load counters. */
     53typedef struct
     54{
     55    uint32_t u32User;
     56    uint32_t u32System;
     57    /* Internal raw counter values. */
     58    uint64_t u64RawTotal;
     59    uint32_t u32RawProcUser;
     60    uint32_t u32RawProcSystem;
     61} RTPROCCPUUSAGESTATS;
     62typedef RTPROCCPUUSAGESTATS *PRTPROCCPUUSAGESTATS;
     63
    3664
    3765__BEGIN_DECLS
     
    5684RTDECL(uint64_t) RTSystemProcessorGetActiveMask(void);
    5785
     86/**
     87 * Gets the current figures of overall system processor usage.
     88 * 
     89 * @remarks To get meaningful stats this function has to be
     90 *          called twice with a bit of delay between calls. This
     91 *          is due to the fact that at least two samples of
     92 *          system usage stats are needed to calculate the load.
     93 * 
     94 * @returns IPRT status code.
     95 * @param   pStats  Pointer to the structure that contains the
     96 *                  results. Note that this structure is
     97 *                  modified with each call to this function and
     98 *                  is used to provide both in and out values.
     99 */
     100RTDECL(int) RTSystemProcessorGetUsageStats(PRTCPUUSAGESTATS pStats);
     101
     102/**
     103 * Gets the current processor usage for a partucilar process.
     104 * 
     105 * @remarks To get meaningful stats this function has to be
     106 *          called twice with a bit of delay between calls. This
     107 *          is due to the fact that at least two samples of
     108 *          system usage stats are needed to calculate the load.
     109 * 
     110 * @returns IPRT status code.
     111 * @param   pid     VM process id.
     112 * @param   pStats  Pointer to the structure that contains the
     113 *                  results. Note that this structure is
     114 *                  modified with each call to this function and
     115 *                  is used to provide both in and out values.
     116 * 
     117 * @todo    Perharps this function should be moved somewhere
     118 *          else.
     119 */
     120RTDECL(int) RTProcessGetProcessorUsageStats(RTPROCESS pid, PRTPROCCPUUSAGESTATS pStats);
    58121
    59122/** @} */
  • trunk/src/VBox/Main/HostImpl.cpp

    r9335 r9904  
    168168#endif /* VBOX_WITH_USB */
    169169
     170#ifdef VBOX_WITH_RESOURCE_USAGE_API
     171    /*
     172     * Start resource usage sampler.
     173     */
     174    //printf("Creating sampling timer with Host::staticSamplerCallback, this=%p\n", this);
     175    int rc = RTTimerCreate(&m_pUsageSampler, VBOX_USAGE_SAMPLER_INTERVAL, Host::staticSamplerCallback, this);
     176    if (RT_FAILURE(rc))
     177    {
     178        AssertMsgFailed(("Failed to create resource usage sampling timer, rc=%d!\n", rc));
     179        return E_FAIL;
     180    }
     181#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     182
    170183    setReady(true);
    171184    return S_OK;
    172185}
     186
     187#ifdef VBOX_WITH_RESOURCE_USAGE_API
     188void Host::staticSamplerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     189{
     190    ((Host*)pvUser)->usageSamplerCallback();
     191}
     192
     193void Host::usageSamplerCallback()
     194{
     195    int rc = RTSystemProcessorGetUsageStats(&m_CpuStats);
     196    if (RT_FAILURE(rc))
     197    {
     198        AssertMsgFailed(("Failed to get CPU stats, rc=%d!\n", rc));
     199    }
     200    //printf("Host::usageSamplerCallback: user=%u%% system=%u%% &m_CpuStats=%p this=%p\n",
     201    //     m_CpuStats.u32User / 10000000, m_CpuStats.u32System / 10000000, &m_CpuStats, this);
     202    //printf("user=%.2f system=%.2f idle=%.2f\n", m_CpuStats.u32User/10000000., m_CpuStats.u32System/10000000., m_CpuStats.u32Idle/10000000.);
     203}
     204#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    173205
    174206/**
     
    197229    mUSBDeviceFilters.clear();
    198230#endif
     231
     232#ifdef VBOX_WITH_RESOURCE_USAGE_API
     233    /*
     234     * Destroy resource usage sampler.
     235     */
     236    int rc = RTTimerDestroy(m_pUsageSampler);
     237    if (RT_FAILURE(rc))
     238    {
     239        AssertMsgFailed(("Failed to destroy resource usage sampling timer, rc=%d!\n", rc));
     240    }
     241#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    199242
    200243    setReady (FALSE);
     
    10831126    return E_NOTIMPL;
    10841127#endif
     1128}
     1129
     1130/**
     1131 * Obtains the results of the latest measurement of overall CPU
     1132 * usage on this host.
     1133 *
     1134 * @returns error code.
     1135 *
     1136 * @param   user      out   % of CPU time spent in user mode.
     1137 * @param   system    out   % of CPU time spent in kernel mode.
     1138 * @param   idle      out   % of idle CPU time.
     1139 *
     1140 */
     1141STDMETHODIMP Host::GetProcessorUsage(ULONG *user, ULONG *system, ULONG *idle)
     1142{
     1143#ifdef VBOX_WITH_RESOURCE_USAGE_API
     1144    *user   = m_CpuStats.u32User;
     1145    *system = m_CpuStats.u32System;
     1146    *idle   = m_CpuStats.u32Idle;
     1147
     1148    return S_OK;
     1149#else /* !VBOX_WITH_RESOURCE_USAGE_API */
     1150    return E_NOTIMPL;
     1151#endif /* !VBOX_WITH_RESOURCE_USAGE_API */
    10851152}
    10861153
  • trunk/src/VBox/Main/MachineImpl.cpp

    r9900 r9904  
    378378    AssertReturn (aConfigFile, E_INVALIDARG);
    379379    AssertReturn (aMode != Init_New || (aName != NULL && *aName != '\0'),
    380                               E_INVALIDARG);
     380                  E_INVALIDARG);
    381381    AssertReturn (aMode != Init_Registered || aId != NULL, E_FAIL);
    382382
     
    497497    }
    498498
     499#ifdef VBOX_WITH_RESOURCE_USAGE_API
     500    /*
     501     * Start resource usage sampler.
     502     */
     503    printf("Creating sampling timer with Machine::staticSamplerCallback, this=%p\n", this);
     504    int result = RTTimerCreate(&m_pUsageSampler, VBOX_USAGE_SAMPLER_INTERVAL, Machine::staticSamplerCallback, this);
     505    if (RT_FAILURE(result))
     506    {
     507        AssertMsgFailed(("Failed to create resource usage sampling timer, rc=%d!\n", result));
     508        rc = E_FAIL;
     509    }
     510#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     511
    499512    LogFlowThisFunc (("mName='%ls', mRegistered=%RTbool, mAccessible=%RTbool "
    500513                      "rc=%08X\n",
     
    620633     */
    621634    AutoMultiWriteLock2 alock (mParent, this);
     635
     636#ifdef VBOX_WITH_RESOURCE_USAGE_API
     637    /*
     638     * Destroy resource usage sampler.
     639     */
     640    int rc = RTTimerDestroy(m_pUsageSampler);
     641    if (RT_FAILURE(rc))
     642    {
     643        AssertMsgFailed(("Failed to destroy resource usage sampling timer, rc=%d!\n", rc));
     644    }
     645#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    622646
    623647    if (!mData->mSession.mMachine.isNull())
     
    678702    LogFlowThisFuncLeave();
    679703}
     704
     705#ifdef VBOX_WITH_RESOURCE_USAGE_API
     706void Machine::staticSamplerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     707{
     708    ((Machine*)pvUser)->usageSamplerCallback();
     709}
     710
     711void Machine::usageSamplerCallback()
     712{
     713    //LogFlowThisFunc(("mData->mSession.mPid = %u &m_CpuStats = %p)\n", mData->mSession.mPid, &m_CpuStats));
     714    if (mData->mSession.mPid != NIL_RTPROCESS) {
     715        int rc = RTProcessGetProcessorUsageStats(mData->mSession.mPid, &m_CpuStats);
     716        if (RT_FAILURE(rc))
     717        {
     718            AssertMsgFailed(("Failed to get CPU stats, rc=%d!\n", rc));
     719        }
     720    }
     721    else
     722    {
     723        m_CpuStats.u32User   = 0;
     724        m_CpuStats.u32System = 0;
     725    }
     726//  printf("Machine::usageSamplerCallback: user=%u%% system=%u%% &m_CpuStats=%p this=%p\n",
     727//         m_CpuStats.u32User / 10000000, m_CpuStats.u32System / 10000000, &m_CpuStats, this);
     728    //printf("user=%.2f system=%.2f\n", m_CpuStats.u32User/10000000., m_CpuStats.u32System/10000000.);
     729}
     730#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     731
    680732
    681733// IMachine properties
     
    27922844}
    27932845
     2846/**
     2847 * Obtains the results of the latest measurement of CPU usage by
     2848 * this machine.
     2849 *
     2850 * @returns error code.
     2851 *
     2852 * @param   user      out   % of CPU time spent in user mode.
     2853 * @param   system    out   % of CPU time spent in kernel mode.
     2854 *
     2855 */
     2856STDMETHODIMP Machine::GetProcessorUsage(ULONG *user, ULONG *system)
     2857{
     2858#ifdef VBOX_WITH_RESOURCE_USAGE_API
     2859    *user   = m_CpuStats.u32User;
     2860    *system = m_CpuStats.u32System;
     2861//  printf("Machine::GetProcessorUsage: user=%u%% system=%u%% &m_CpuStats=%p this=%p\n",
     2862//         m_CpuStats.u32User / 10000000, m_CpuStats.u32System / 10000000, &m_CpuStats, this);
     2863    return S_OK;
     2864#else /* !VBOX_WITH_RESOURCE_USAGE_API */
     2865    return E_NOTIMPL;
     2866#endif /* !VBOX_WITH_RESOURCE_USAGE_API */
     2867}
     2868
    27942869
    27952870// public methods for internal purposes
     
    85318606}
    85328607
     8608/**
     8609 * Obtains the results of the latest measurement of CPU usage by
     8610 * this machine.
     8611 *
     8612 * @returns error code.
     8613 *
     8614 * @param   user      out   % of CPU time spent in user mode.
     8615 * @param   system    out   % of CPU time spent in kernel mode.
     8616 *
     8617 */
     8618STDMETHODIMP SessionMachine::GetProcessorUsage(ULONG *user, ULONG *system)
     8619{
     8620    return mPeer->GetProcessorUsage(user, system);
     8621}
     8622
    85338623// public methods only for internal purposes
    85348624/////////////////////////////////////////////////////////////////////////////
  • trunk/src/VBox/Main/Makefile.kmk

    r9728 r9904  
    155155ifdef VBOX_WITHOUT_LINUX_COMPILER_H
    156156VBoxSVC_DEFS += VBOX_WITHOUT_LINUX_COMPILER_H
     157endif
     158ifdef VBOX_WITH_RESOURCE_USAGE_API
     159VBoxSVC_DEFS += VBOX_WITH_RESOURCE_USAGE_API
    157160endif
    158161
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r9883 r9904  
    24952495  <interface
    24962496     name="IMachine" extends="$unknown"
    2497      uuid="ceb17b5b-fd1f-424f-9dd3-2ab04c06eefc"
     2497     uuid="d6181581-e7c7-418a-b3b6-2da10b11a763"
    24982498     wsmap="managed"
    24992499     >
     
    35043504    </method>
    35053505
     3506    <method name="getProcessorUsage">
     3507      <desc>
     3508        Returns the current processor usage measured over all cores of all
     3509        processors in the host system.
     3510
     3511        <note>
     3512          The maximum value is 1000000000 which means that all cores of all CPUs
     3513          are completely used.
     3514        </note>
     3515      </desc>
     3516      <param name="user" type="unsigned long" dir="out">
     3517        <desc>The pecentage of processor time spent executing in user
     3518          mode.
     3519        </desc>
     3520      </param>
     3521      <param name="system" type="unsigned long" dir="out">
     3522        <desc>The pecentage of processor time spent executing in kernel
     3523          mode.
     3524        </desc>
     3525      </param>
     3526    </method>
     3527
    35063528  </interface>
    35073529
     
    47944816  <interface
    47954817     name="IHost" extends="$unknown"
    4796      uuid="81729c26-1aec-46f5-b7c0-cc7364738fdb"
     4818     uuid="a42a480f-d554-4be0-b11c-6c2e54dd1274"
    47974819     wsmap="managed"
    47984820     >
     
    50205042    </method>
    50215043
     5044    <method name="getProcessorUsage">
     5045      <desc>
     5046        Returns the current processor usage measured over all cores of all
     5047        processors in the host system.
     5048
     5049        <note>
     5050          The maximum value is 1000000000 which means that all cores of all CPUs
     5051          are completely used.
     5052        </note>
     5053      </desc>
     5054      <param name="user" type="unsigned long" dir="out">
     5055        <desc>The pecentage of processor time spent executing in user
     5056          mode.
     5057        </desc>
     5058      </param>
     5059      <param name="system" type="unsigned long" dir="out">
     5060        <desc>The pecentage of processor time spent executing in kernel
     5061          mode.
     5062        </desc>
     5063      </param>
     5064      <param name="idle" type="unsigned long" dir="out">
     5065        <desc>The pecentage of processor time spent doing nothing.
     5066        </desc>
     5067      </param>
     5068    </method>
    50225069  </interface>
    50235070
  • trunk/src/VBox/Main/include/HostImpl.h

    r8765 r9904  
    3636# include "win/svchlp.h"
    3737#endif
     38
     39#ifdef VBOX_WITH_RESOURCE_USAGE_API
     40#include "iprt/timer.h"
     41#include "iprt/system.h"
     42
     43/* Each second we obtain new CPU load stats. */
     44#define VBOX_USAGE_SAMPLER_INTERVAL 1000
     45#endif /* VBOX_WITH_RESOURCE_USAGE_API */
     46
    3847
    3948class VirtualBox;
     
    100109    STDMETHOD(InsertUSBDeviceFilter) (ULONG aPosition, IHostUSBDeviceFilter *aFilter);
    101110    STDMETHOD(RemoveUSBDeviceFilter) (ULONG aPosition, IHostUSBDeviceFilter **aFilter);
     111
     112    STDMETHOD(GetProcessorUsage) (ULONG *user, ULONG *system, ULONG *idle);
    102113
    103114    // public methods only for internal purposes
     
    167178    USBProxyService *mUSBProxyService;
    168179#endif /* VBOX_WITH_USB */
     180
     181#ifdef VBOX_WITH_RESOURCE_USAGE_API
     182    /** Static timer callback. */
     183    static void staticSamplerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     184    /** Member timer callback. */
     185    void usageSamplerCallback();
     186
     187    /** Pointer to the usage sampling timer. */
     188    PRTTIMER m_pUsageSampler;
     189    /** Time stamp of the last taken sample. */
     190    //uint64_t m_tsLastSampleTaken;
     191    /** Structure to hold processor usage stats. */
     192    RTCPUUSAGESTATS m_CpuStats;
     193#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    169194};
    170195
  • trunk/src/VBox/Main/include/MachineImpl.h

    r9883 r9904  
    4848#include <iprt/thread.h>
    4949#include <iprt/time.h>
     50#ifdef VBOX_WITH_RESOURCE_USAGE_API
     51#include <iprt/system.h>
     52#include <iprt/timer.h>
     53#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    5054
    5155#include <list>
     
    519523    STDMETHOD(SetConfigRegistryValue) (INPTR BSTR aKey, INPTR BSTR aValue);
    520524
     525    STDMETHOD(GetProcessorUsage) (ULONG *user, ULONG *system);
     526
    521527    // public methods only for internal purposes
    522528
     
    739745    friend class SessionMachine;
    740746    friend class SnapshotMachine;
     747
     748#ifdef VBOX_WITH_RESOURCE_USAGE_API
     749    /** Static timer callback. */
     750    static void staticSamplerCallback(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     751    /** Member timer callback. */
     752    void usageSamplerCallback();
     753    /** Pointer to the usage sampling timer. */
     754    PRTTIMER m_pUsageSampler;
     755    /** Structure to hold processor usage stats. */
     756    RTPROCCPUUSAGESTATS m_CpuStats;
     757#endif /* VBOX_WITH_RESOURCE_USAGE_API */
    741758};
    742759
     
    809826        IConsole *aInitiator, MachineState_T *aMachineState, IProgress **aProgress);
    810827
     828    /* We need to override and call real Machine's method. */
     829    STDMETHOD(GetProcessorUsage) (ULONG *user, ULONG *system);
     830
    811831    // public methods only for internal purposes
    812832
  • trunk/src/VBox/Main/testcase/tstAPI.cpp

    r8155 r9904  
    919919#endif
    920920
     921#if 1
     922    for (int i = 0; i < 10; i++)
     923    {
     924        ComPtr <IHost> host;
     925        CHECK_RC_BREAK (virtualBox->COMGETTER(Host) (host.asOutParam()));
     926        ULONG user, system, idle;
     927        host->GetProcessorUsage(&user, &system, &idle);
     928        printf("user=%u system=%u idle=%u\n", user/10000000, system/10000000, idle/10000000);
     929        sleep(1);
     930    }
     931#endif
     932
     933#if 1
     934    {
     935        ComPtr <IMachine> machine;
     936        Bstr name = argc > 1 ? argv [1] : "dsl";
     937        printf ("Getting a machine object named '%ls'...\n", name.raw());
     938        CHECK_RC_BREAK (virtualBox->FindMachine (name, machine.asOutParam()));
     939        Guid guid;
     940        CHECK_RC_BREAK (machine->COMGETTER(Id) (guid.asOutParam()));
     941        printf ("Opening a remote session for this machine...\n");
     942        ComPtr <IProgress> progress;
     943        CHECK_RC_BREAK (virtualBox->OpenRemoteSession (session, guid, Bstr("gui"),
     944                                                       NULL, progress.asOutParam()));
     945        printf ("Waiting for the session to open...\n");
     946        CHECK_RC_BREAK (progress->WaitForCompletion (-1));
     947        ComPtr <IMachine> sessionMachine;
     948        printf ("Getting sessioned machine object...\n");
     949        CHECK_RC_BREAK (session->COMGETTER(Machine) (sessionMachine.asOutParam()));
     950        ComPtr <IConsole> console;
     951        printf ("Getting console object...\n");
     952        CHECK_RC_BREAK (session->COMGETTER(Console) (console.asOutParam()));
     953        for (int i = 0; i < 10; i++)
     954        {
     955            ComPtr <IHost> host;
     956            CHECK_RC_BREAK (virtualBox->COMGETTER(Host) (host.asOutParam()));
     957            ULONG user, system;
     958            sessionMachine->GetProcessorUsage(&user, &system);
     959            printf("VM: user=%u system=%u\n", user/10000000, system/10000000);
     960            sleep(1);
     961        }
     962        printf ("Press enter to pause the VM execution in the remote session...");
     963        getchar();
     964        CHECK_RC (console->Pause());
     965        for (int i = 0; i < 10; i++)
     966        {
     967            ComPtr <IHost> host;
     968            CHECK_RC_BREAK (virtualBox->COMGETTER(Host) (host.asOutParam()));
     969            ULONG user, system;
     970            sessionMachine->GetProcessorUsage(&user, &system);
     971            printf("VM: user=%u system=%u\n", user/10000000, system/10000000);
     972            sleep(1);
     973        }
     974        printf ("Press enter to power off VM...");
     975        getchar();
     976        CHECK_RC (console->PowerDown());
     977        printf ("Press enter to close this session...");
     978        getchar();
     979        session->Close();
     980    }
     981#endif
     982
    921983    printf ("Press enter to release Session and VirtualBox instances...");
    922984    getchar();
  • trunk/src/VBox/Runtime/r3/os2/system-os2.cpp

    r8245 r9904  
    6666}
    6767
     68RTDECL(int) RTSystemProcessorGetUsageStats(PRTCPUUSAGESTATS pStats)
     69{
     70    /* @todo Implement! */
     71    return VERR_NOT_IMPLEMENTED;
     72}
     73
     74RTDECL(int) RTProcessGetProcessorUsageStats(RTPROCESS pid, PRTPROCCPUUSAGESTATS pStats)
     75{
     76    /* @todo Implement! */
     77    return VERR_NOT_IMPLEMENTED;
     78}
     79
  • trunk/src/VBox/Runtime/r3/posix/system-posix.cpp

    r8245 r9904  
    3535#include <iprt/system.h>
    3636#include <iprt/assert.h>
     37#include <iprt/err.h>
     38#include <iprt/string.h>
     39#include <iprt/mem.h>
    3740
    3841#include <unistd.h>
     42#include <stdio.h>
    3943#if !defined(RT_OS_SOLARIS)
    4044# include <sys/sysctl.h>
     
    8892}
    8993
     94/**
     95 * Gets the current figures of overall system processor usage.
     96 * 
     97 * @remarks To get meaningful stats this function has to be
     98 *          called twice with a bit of delay between calls. This
     99 *          is due to the fact that at least two samples of
     100 *          system usage stats are needed to calculate the load.
     101 * 
     102 * @returns None.
     103 */
     104RTDECL(int) RTSystemProcessorGetUsageStats(PRTCPUUSAGESTATS pStats)
     105{
     106    int rc = VINF_SUCCESS;
     107    uint32_t u32UserNow, u32NiceNow, u32SystemNow, u32IdleNow;
     108    uint32_t u32UserDelta, u32SystemDelta, u32IdleDelta, u32BusyDelta, u32TotalDelta;
     109    FILE *f = fopen("/proc/stat", "r");
     110
     111    if (f)
     112    {
     113        if (fscanf(f, "cpu %u %u %u %u", &u32UserNow, &u32NiceNow, &u32SystemNow, &u32IdleNow) == 4)
     114        {
     115            u32UserDelta   = (u32UserNow - pStats->u32RawUser) + (u32NiceNow - pStats->u32RawNice);
     116            u32SystemDelta = u32SystemNow - pStats->u32RawSystem;
     117            u32IdleDelta   = u32IdleNow - pStats->u32RawIdle;
     118            u32BusyDelta   = u32UserDelta + u32SystemDelta;
     119            u32TotalDelta  = u32BusyDelta + u32IdleDelta;
     120            pStats->u32User   = (uint32_t)(IPRT_USAGE_MULTIPLIER * u32UserDelta / u32TotalDelta);
     121            pStats->u32System = (uint32_t)(IPRT_USAGE_MULTIPLIER * u32SystemDelta / u32TotalDelta);
     122            pStats->u32Idle   = (uint32_t)(IPRT_USAGE_MULTIPLIER * u32IdleDelta / u32TotalDelta);
     123            /* Update the base. */
     124            pStats->u32RawUser   = u32UserNow;
     125            pStats->u32RawNice   = u32NiceNow;
     126            pStats->u32RawSystem = u32SystemNow;
     127            pStats->u32RawIdle   = u32IdleNow;
     128        }
     129        else
     130            rc = VERR_FILE_IO_ERROR;
     131        fclose(f);
     132    }
     133    else
     134        rc = VERR_ACCESS_DENIED;
     135
     136    return rc;
     137}
     138
     139/**
     140 * Gets the current processor usage for a partucilar process.
     141 * 
     142 * @remarks To get meaningful stats this function has to be
     143 *          called twice with a bit of delay between calls. This
     144 *          is due to the fact that at least two samples of
     145 *          system usage stats are needed to calculate the load.
     146 * 
     147 * @returns None.
     148 */
     149RTDECL(int) RTProcessGetProcessorUsageStats(RTPROCESS pid, PRTPROCCPUUSAGESTATS pStats)
     150{
     151    int rc = VINF_SUCCESS;
     152    uint32_t u32UserNow, u32NiceNow, u32SystemNow, u32IdleNow;
     153    uint32_t u32UserDelta, u32SystemDelta;
     154    uint64_t u64TotalNow, u64TotalDelta;
     155    FILE *f = fopen("/proc/stat", "r");
     156
     157    if (f)
     158    {
     159        if (fscanf(f, "cpu %u %u %u %u", &u32UserNow, &u32NiceNow, &u32SystemNow, &u32IdleNow) == 4)
     160        {
     161            char *pszName;
     162            pid_t pid2;
     163            char c;
     164            int iTmp;
     165            unsigned uTmp;
     166            unsigned long ulTmp, ulUserNow, ulSystemNow;
     167            char buf[80]; /* @todo: this should be tied to max allowed proc name. */
     168
     169            u64TotalNow = (uint64_t)u32UserNow + u32NiceNow + u32SystemNow + u32IdleNow;
     170            fclose(f);
     171            RTStrAPrintf(&pszName, "/proc/%d/stat", pid);
     172            //printf("Opening %s...\n", pszName);
     173            f = fopen(pszName, "r");
     174            RTMemFree(pszName);
     175
     176            if (f)
     177            {
     178                if (fscanf(f, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu",
     179                           &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
     180                           &ulTmp, &ulTmp, &ulTmp, &ulTmp, &ulUserNow, &ulSystemNow) == 15)
     181                {
     182                    Assert((pid_t)pid == pid2);
     183                    u32UserDelta      = ulUserNow - pStats->u32RawProcUser;
     184                    u32SystemDelta    = ulSystemNow - pStats->u32RawProcSystem;
     185                    u64TotalDelta     = u64TotalNow - pStats->u64RawTotal;
     186                    pStats->u32User   = (uint32_t)(IPRT_USAGE_MULTIPLIER * u32UserDelta / u64TotalDelta);
     187                    pStats->u32System = (uint32_t)(IPRT_USAGE_MULTIPLIER * u32SystemDelta / u64TotalDelta);
     188//                  printf("%d: user=%u%% system=%u%% / raw user=%u raw system=%u total delta=%u\n", pid,
     189//                         pStats->u32User / 10000000, pStats->u32System / 10000000,
     190//                         pStats->u32RawProcUser, pStats->u32RawProcSystem, u64TotalDelta);
     191                    /* Update the base. */
     192                    pStats->u32RawProcUser   = ulUserNow;
     193                    pStats->u32RawProcSystem = ulSystemNow;
     194                    pStats->u64RawTotal      = u64TotalNow;
     195//                  printf("%d: updated raw user=%u raw system=%u raw total=%u\n", pid,
     196//                         pStats->u32RawProcUser, pStats->u32RawProcSystem, pStats->u64RawTotal);
     197                }
     198                else
     199                    rc = VERR_FILE_IO_ERROR;
     200            }
     201            else
     202                rc = VERR_ACCESS_DENIED;
     203        }
     204        else
     205            rc = VERR_FILE_IO_ERROR;
     206        fclose(f);
     207    }
     208    else
     209        rc = VERR_ACCESS_DENIED;
     210
     211    return rc;
     212}
  • trunk/src/VBox/Runtime/r3/win/system-win.cpp

    r8245 r9904  
    6161}
    6262
     63RTDECL(int) RTSystemProcessorGetUsageStats(PRTCPUUSAGESTATS pStats)
     64{
     65    /* @todo Implement! */
     66    return VERR_NOT_IMPLEMENTED;
     67}
     68
     69RTDECL(int) RTProcessGetProcessorUsageStats(RTPROCESS pid, PRTPROCCPUUSAGESTATS pStats)
     70{
     71    /* @todo Implement! */
     72    return VERR_NOT_IMPLEMENTED;
     73}
     74
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette