Finally, we can also find out about the interrupts that are associated with a process.

We use the DCMD_PROC_IRQS command, and expect to get back zero or more data structures, as we did in the DCMD_PROC_PAGEDATA, DCMD_PROC_MAPINFO, and DCMD_PROC_TIMERS examples above. The structure procfs_irq is the same as the debug_irq_t, which is defined as follows for 64-bit architectures:

typedef struct _debug_irq64 {
  pid_t                 pid;
  pthread_t             tid;
  uintptr32_t           __handler32;
  uintptr32_t           __area32;
  unsigned              flags;
  unsigned              latency;
  unsigned              mask_count;
  int                   id;
  unsigned              vector;
  struct __sigevent32   __event32;
  uintptr64_t           handler /* const struct sigevent *(*handler)(void *area, int id); */
  uintptr64_t           area;
  union {
            struct __sigevent32             event32;
            struct __sigevent64             event64;
            struct sigevent                 event;
} debug_irq_t;

To fetch the data, we use code similar to what we used with the timers and memory segments:

#define MAX_IRQS  512

static void
dump_procfs_irq (int fd, int pid)
  procfs_irq    irqs [MAX_IRQS];
  int           nirqs;
  int           i;
  int           sts;

  // fetch information about the IRQs for this pid
  sts = devctl (fd, DCMD_PROC_IRQS, irqs, sizeof (irqs), &nirqs);
  if (sts != EOK) {
    fprintf (stderr, "%s:  IRQS proc %d, error %d (%s)\n",
             progname, pid, sts, strerror (sts));
    exit (EXIT_FAILURE);

  if (nirqs > MAX_IRQS) {
    fprintf (stderr, "%s: proc %d > %d IRQs (%d) !!! ***\n",
             progname, pid, MAX_IRQS, nirqs);
    exit (EXIT_FAILURE);

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

Since our pipe command doesn't use interrupts either, I've once again selected devb-eide:

    Buffer   0
        pid        8200
        tid        2
        handler    0x00000000
        area       0xEFEA5FF0
        flags      0x0000000C
        latency    0
        mask_count 0
        id         3
        vector     14
        event (sigev_notify type 4)
            SIGEV_PULSE (sigev_coid 0x40000002,
                         sigev_value.sival_int 0,
                         sigev_priority 21, sigev_code 2)

    Buffer   1
        pid        8200
        tid        3
        handler    0x00000000
        area       0xEFEEFDA0
        flags      0x0000000C
        latency    0
        mask_count 0
        id         4
        vector     15
        event (sigev_notify type 4)
            SIGEV_PULSE (sigev_coid 0x40000005,
                         sigev_value.sival_int 0,
                         sigev_priority 21, sigev_code 2)

The members of the debug_irq_t shown above are as follows:

pid and tid
The pid and tid fields give the process ID and the thread ID (process ID 8200 in this example is devb-eide).
The flags value is hexadecimal 0x0C, which is composed of the bits _NTO_INTR_FLAGS_PROCESS and _NTO_INTR_FLAGS_TRK_MSK, meaning, respectively, that the interrupt belongs to the process (rather than the thread), and the kernel should keep track of the number of times that the interrupt is masked and unmasked.
The latency value, in nanoseconds, that the kernel uses in calculations for lazy interrupts. You can use InterruptCharacteristic() to set this latency.
Indicates the number of times the interrupt is masked (0 indicates the interrupt is not masked). Useful as a diagnostic aid when you are trying to determine why your interrupt fires only once. :-)
This is the interrupt identification number returned by InterruptAttach() or InterruptAttachEvent().
This is the interrupt vector for this particular interrupt. In our example, devb-eide is attached to two interrupt sources (as defined by the vector parameter; i.e., interrupts 14 and 15, the two EIDE controllers on my PC).
handler and area
Indicates the interrupt service routine address, and its associated parameter. The fact that the interrupt handler address is zero indicates that there is no real interrupt vector associated with the interrupts; rather, the event (a pulse in both cases) should be returned (i.e., the interrupt was attached with InterruptAttachEvent() rather than InterruptAttach()). In the case of the handler being zero, the area member is not important.
A standard struct sigevent that determines what the InterruptAttachEvent() should do when it fires.