DosPerfSysCall

From EDM2
Jump to: navigation, search

Retrieve system performance information.

Syntax

DosPerfSysCall(ulCommand, ulParm1, ulParm2, ulParm3);

Parameters

ulCommand (ULONG) - input
Command
DosPerfSysCall accepts the following command:
CMD_KI_RDCNT (0x63): Read CPU utilization information in both uniprocessor and symmetric multi-processor (SMP) environments by taking a snapshot of the time stamp counters. To determine CPU utilization, the application must compute the difference between two time stamp snapshots using 64-bit arithmetic. See the example code for details.
ulParm1 (ULONG) - in/out 
Command specific parameter 1
Parameter usage depends on the command specified:
CMD_KI_RDCNT : Pointer to an array of CPUUTIL structures, with one entry for each processor. On a 4-way SMP machine, the array definition would be:
CPUUTIL CPUUtil[4];   /* For processor IDs 0, 1, 2, and 3 */
since processor numbers and arrays are both 0-based. ulParm1 would be set to the address of CPUUtil[0].

ulParm2 and ulParm3 are not used and should be set to zero.

ulParm2 (ULONG) - in/out
Command specific parameter 2
Parameter usage depends on the command specified:
CMD_KI_RDCNT 0 (reserved)
ulParm3 (ULONG) - in/out
Command specific parameter 3
Parameter usage depends on the command specified:
CMD_KI_RDCNT 0 (reserved)

Return Code

ulrc (APIRET) - returns
DosPerfSysCall returns one of the following values:
  • 0 NO_ERROR
  • 1 ERROR_INVALID_FUNCTION

Remarks

DosPerfSysCall is a general purpose performance function. This function accepts four parameters. The first parameter is the command requested. The other three parameters are command specific. DosPerfSysCall is intended to be extended by IBM in the future for other performance related functions.

Some functions of DosPerfSysCall may have a dependency on Intel Pentium or Pentium-Pro support. If a function cannot be provided because OS/2 is not running on an processor with the required features, a return code will indicate an attempt to use an unsupported function.

The perfutil.h file referenced in the example code may or may not be shipped as part of the Toolkit. In the event that it is not, its contents are:

#ifdef __cplusplus
  extern "C" {
#endif

#ifndef  PERFCALL_INCLUDED
#define  PERFCALL_INCLUDED

/*
   DosPerfSysCall Function Prototype
*/

/* The  ordinal for DosPerfSysCall (in BSEORD.H) */
/* is defined as ORD_DOS32PERFSYSCALL         */

APIRET APIENTRY DosPerfSysCall(ULONG ulCommand, ULONG ulParm1, ULONG ulParm2, ULONG ulParm3);

/***
 *
 * CPU Utilization
 * ---------------
 *
 **/

#define   CMD_KI_RDCNT    (0x63)

 typedef struct _CPUUTIL {
   ULONG ulTimeLow;     /* Low 32 bits of time stamp      */
   ULONG ulTimeHigh;    /* High 32 bits of time stamp     */
   ULONG ulIdleLow;     /* Low 32 bits of idle time       */
   ULONG ulIdleHigh;    /* High 32 bits of idle time      */
   ULONG ulBusyLow;     /* Low 32 bits of busy time       */
   ULONG ulBusyHigh;    /* High 32 bits of busy time      */
   ULONG ulIntrLow;     /* Low 32 bits of interrupt time  */
   ULONG ulIntrHigh;    /* High 32 bits of interrupt time */
  } CPUUTIL;

 typedef CPUUTIL *PCPUUTIL;

#ifdef __cplusplus
  }
#endif

It may also be necessary to define the ordinal for this function:

#define ORD_DOS32PERFSYSCALL            976

Example Code

This example uses DosPerfSysCall to obtain CPU Utilization information on a uniprocessor.

#define INCL_BASE

#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <perfutil.h>

/*
   Convert 8-byte (low, high) time value to double
*/
#define LL2F(high, low) (4294967296.0*(high)+(low))

/* This is a 1 processor example */

void main (int argc, char *argv[])
{
    APIRET      rc;
    int         i, iter, sleep_sec;
    double      ts_val, ts_val_prev;
    double      idle_val, idle_val_prev;
    double      busy_val, busy_val_prev;
    double      intr_val, intr_val_prev;
    CPUUTIL     CPUUtil;

    if ((argc < 2) || (*argv[1] < '1') || (*argv[1] > '9')) {
        fprintf(stderr, "usage: %s [1-9]\n", argv[0]);
        exit(0);
    }
    sleep_sec = *argv[1] - '0';

    iter = 0;
    do {
        rc = DosPerfSysCall(CMD_KI_RDCNT,(ULONG) &CPUUtil,0,0);
        if (rc) {
            fprintf(stderr, "CMD_KI_RDCNT failed rc = %d\n",rc);
            exit(1);
        }
        ts_val = LL2F(CPUUtil.ulTimeHigh, CPUUtil.ulTimeLow);
        idle_val = LL2F(CPUUtil.ulIdleHigh, CPUUtil.ulIdleLow);
        busy_val = LL2F(CPUUtil.ulBusyHigh, CPUUtil.ulBusyLow);
        intr_val = LL2F(CPUUtil.ulIntrHigh, CPUUtil.ulIntrLow);

        if (iter > 0) {
            double  ts_delta = ts_val - ts_val_prev;
            printf("idle: %4.2f%%  busy: %4.2f%%  intr: %4.2f%%\n",
                   (idle_val - idle_val_prev)/ts_delta*100.0,
                   (busy_val - busy_val_prev)/ts_delta*100.0,
                   (intr_val - intr_val_prev)/ts_delta*100.0);
        }

        ts_val_prev = ts_val;
        idle_val_prev = idle_val;
        busy_val_prev = busy_val;
        intr_val_prev = intr_val;

        iter++;
        DosSleep(1000*sleep_sec);

    } while (1);
}

Related Functions