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 for 64-bit architectures as follows:
typedef struct _debug_timer64 { timer_t id; unsigned spare; struct _timer_info32 __info32; struct _timer_info64 info; } debug_timer64_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; uint32_t flags; int32_t tid; int32_t notify; clockid_t clockid; uint32_t 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; int sts; // fetch information about the timers for this pid sts = devctl (fd, DCMD_PROC_TIMERS, timers, sizeof (timers), &ntimers); if (sts != EOK) { fprintf (stderr, "%s: TIMERS err, proc %d, error %d (%s)\n", progname, pid, sts, strerror (sts)); 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:
For more information about timer tolerance and high-resolution timers, see Tolerant and high-resolution timers in the Understanding the Microkernel's Concept of Time chapter of the QNX Neutrino Programmer's Guide.
The header file also defines _NTO_TI_REPORT_TOLERANCE, which you use in the flags argument to TimerInfo(), and _NTO_TI_WAKEUP, which is only emitted into trace events. You won't find either of them set here.
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).