DCMD_PROC_TIMERS

We can find out about the timers that are associated with a process.

We use the DCMD_PROC_TIMERS command, and expect to get back zero or more data structures, as we did in the DCMD_PROC_PAGEDATA and DCMD_PROC_MAPINFO examples above. The structure is defined as follows:

typedef struct _debug_timer {
  timer_t             id;
  unsigned            spare;
  struct _timer_info  info;
} debug_timer_t;

This structure relies on the struct _timer_info type (defined in <sys/platform.h>, and paraphrased slightly):

struct _timer_info {
  struct _itimer      itime;
  struct _itimer      otime;
  _Uint32t            flags;
  _Int32t             tid;
  _Int32t             notify;
  clockid_t           clockid;
  _Uint32t            overruns;
  struct sigevent     event;
};

This data type, struct _timer_info is used with the TimerInfo() function call.

To fetch the data, we utilize code that's almost identical to that used for the memory segments (above):

#define MAX_TIMERS  512

static void
dump_procfs_timer (int fd, int pid)
{
  procfs_timer  timers [MAX_TIMERS];
  int           ntimers;
  int           i;

  // fetch information about the timers for this pid
  if (devctl (fd, DCMD_PROC_TIMERS, timers, sizeof (timers),
              &ntimers) != EOK) {
    fprintf (stderr, "%s: TIMERS err, proc %d, errno %d (%s)\n",
             progname, pid, errno, strerror (errno));
    exit (EXIT_FAILURE);
  }

  if (ntimers > MAX_TIMERS) {
    fprintf (stderr, "%s: proc %d has > %d timers (%d) !!!\n",
             progname, pid, MAX_TIMERS, ntimers);
    exit (EXIT_FAILURE);
  }

  printf ("Info from DCMD_PROC_TIMERS\n");
  for (i = 0; i < ntimers; i++) {
    // print information here
  }
  printf ("\n");
}

Since our pipe command doesn't use timers, let's look at the devb-eide driver instead. It has four timers; I've selected just one:

  Buffer   2 timer ID 2
    itime    1063180.652506618 s,      0.250000000 interval s
    otime          0.225003825 s,      0.250000000 interval s
    flags     0x00000001
    tid       0
    notify    196612 (0x30004)
    clockid   0
    overruns  0
    event (sigev_notify type 4)
      SIGEV_PULSE (sigev_coid 1073741832,
                   sigev_value.sival_int 0,
                   sigev_priority -1, sigev_code 1)

The fields are as follows:

itime
This represents the time when the timer will fire, if it is active (i.e. the flags member has the bit _NTO_TI_ACTIVE set). If the timer is not active, but has been active in the past, then this will contain the time that it fired last, or was going to fire (in case the timer was canceled before firing).
otime
Time remaining before the timer expires.
flags
One or more of the flags _NTO_TI_ACTIVE (the timer is active), _NTO_TI_ABSOLUTE (the timer is waiting for an absolute time to occur; otherwise, the timer is considered relative), _NTO_TI_TOD_BASED (the timer is based relative to the beginning of the world (January 1, 1970, 00:00:00 GMT); otherwise, the timer is based relative to the time that Neutrino was started on the machine (see the system page qtime boot_time member)), and _NTO_TI_EXPIRED (the timer has expired).
tid
The thread to which the timer is directed (or the value 0 if it's directed to the process).
notify
The notification type (only the bottom 16 bits are interesting; the rest are used internally).
clockid
This is the clock ID (e.g. CLOCK_REALTIME).
overruns
This is a count of the number of timer overruns.
event
This is a struct sigevent that indicates the type of event that should be delivered when the timer fires. For the example above, it's a SIGEV_PULSE, meaning that a pulse is sent. The fields listed after the SIGEV_PULSE pertain to the pulse delivery type (e.g. connection ID, etc.).

In the example above, the flags member has only the bit _NTO_TI_ACTIVE (the value 0x0001) set, which means that the timer is active. Since the _NTO_TI_TOD_BASED flag is not set, however, it indicates that the timer is relative to the time that the machine was booted. So the next time the timer will fire is 1063180.652506618 seconds past the time that the machine was booted (or 12 days, 7 hours, 19 minutes, and 40.652506618 seconds past the boot time). This timer might be used for flushing the write cache — at the time the snapshot was taken, the machine had already been up for 12 days, 7 hours, 19 minutes, and some number of seconds.

The notify type (when examined in hexadecimal) shows 0x0004 as the bottom 16 bits, which is a notification type of SIGEV_PULSE (which agrees with the data in the event structure).