EVCOUNT(9) | Kernel Developer's Manual | EVCOUNT(9)

# NAME

`evcount`, `evcount_attach`, `evcount_detach`, `evcount_percpu`, `evcount_inc` — generic interrupt and event counter kernel API

# SYNOPSIS

`#include <sys/evcount.h>`

void
`evcount_attach`(struct evcount *ec, const char *name, void *data);

void
`evcount_percpu`(struct evcount *ec);

void
`evcount_inc`(struct evcount *ec);

void
`evcount_detach`(struct evcount *ec);

# DESCRIPTION

The `evcount` API provides an interface for generic event and interrupt counting, whose statistics are made available to machine-independent sysctl(2) nodes.

## Overview

With `evcount`, an architecture can collect interrupt counting for any device. All registered counters will be made available under the kern.evcount sysctl(2) node as a flat list. The following is a sample list of counters provided by some common architectures:

clock
  Interrupt counter for the system clock
stat
  Second-level interrupt decrementer counter
rtc
  Real-time clock counter
prof
  System profiler counter
pciide0
  PCI IDE controller counter (see pciide(4))
uhci0
  USB 1.0 controller counter (see usb(4))

See intro(4) for a list of devices for any of which `evcount` may track interrupt counting.

The systat(1) and vmstat(8) utilities can be used to view interrupts collected by `evcount`.

## The API

The evcount structure has the following definition:

    struct evcount {
    	u_int64_t		ec_count;	/* main counter */
    	int			ec_id;		/* counter ID */
    	const char		*ec_name;	/* counter name */
    	void			*ec_data;	/* user data */
    	struct cpumem		*ec_cpumem;	/* per-cpu counter */

    	TAILQ_ENTRY(evcount)	next;
    };

The `evcount_attach`(ec, name, data) function adds the given event counter to the system's counter list. name provides the counter name, which is modeled after a device, such as “clock” or “pciide0”. data provides a chunk of data that will be made available through the sysctl(2) call.

The `evcount_percpu`(ec) function configures ec with one counter for each CPU in the system. It should be used when ec's corresponding interrupt can occur simultaneously on multiple CPUs. It must be called immediately after `evcount_attach`() is called for a given counter.

The `evcount_inc`(ec) function increments the given counter.

The `evcount_detach`(ec) function removes the given event counter ec from the counter list.

# EXAMPLES

The following is an outline of code that provides routines to register and de-register interrupt handlers for devices, plugging the counting of interrupts generated by them during system operation into the `evcount` framework.

    #include <sys/evcount.h>
    #include <machine/intr.h>

    /*
     * machine/intr.h provides a structure, intrhand, which is
     * machine-dependent but is usually similar to this:
     *
     *	struct intrhand {
     *		int		(*ih_fun)(void *);
     *		void		 *ih_arg;
     *		int		  ih_level;
     *		struct intrhand  *ih_next;
     *		int		  ih_irq;
     *		struct evcount    ih_count;
     *	}
     */

    /*
     * Register an interrupt handler.
     */
    void *
    intr_establish(void *lcv, int irq, int type, int level,
    	       int (*ih_fun)(void *), void *ih_arg, char *name)
    {
    	struct intrhand *ih, **p;

    	/*
    	 * Allocate memory for the handler, sanity-check incoming
    	 * values (IRQ#, etc.), and link the handler into
    	 * machine-dependent data structures.
    	 */

    	/*
    	 * Fill out the handler.
    	 */
    	ih->ih_fun = ih_fun;
    	ih->ih_arg = ih_arg;
    	ih->ih_next = NULL;
    	ih->ih_level = level;
    	ih->ih_irq = irq;

    	/*
    	 * Attach it.
    	 */
    	evcount_attach(&ih->ih_count, name, &ih->ih_irq);

    	return (ih);
    }

    /*
     * Deregister an interrupt handler.
     */
    void
    intr_disestablish(void *lcp, void *arg)
    {
    	struct intrhand *ih = arg;

    	/*
    	 * Sanity-check incoming values (IRQ, etc.) and remove
    	 * the interrupt handler from machine-dependent data
    	 * structures.
    	 */

    	evcount_detach(&ih->ih_count);

    	/*
    	 * Free up memory and install a null interrupt handler.
    	 */
    }

An interrupt handler for a device will be registered during autoconf(9) with a call to the above `intr_establish`().

The main external interrupt handler, which handles all system interrupts, will select the appropriate handler for the device that created the interrupt when an interrupt is generated. In this case, the handler is the routine assigned to ih_fun, and `evcount` will be made aware of interrupt occurrence.

# SEE ALSO

systat(1), sysctl(2), queue(3), intro(4), vmstat(8), autoconf(9), counters_alloc(9)

# AUTHORS

The `evcount` API was written by Artur Grabowski and Aaron Campbell for OpenBSD 3.6.

November 10, 2022 | Debian