/*----------------------------------------------------------------------------*/

/*
 * demonstrate use of ANSI C signal handlers with the PMC library
 */

/*----------------------------------------------------------------------------*/

/* Compile with
 *   gcc -o menu11 -O `pmc_options` menu11.c -lpmc
 *
 * Try these examples:
 *   menu11 -g 0
 *   menu11 -g 1
 *   menu11 -g 1	[and type control-C after a few seconds]
 */

/*----------------------------------------------------------------------------*/

#include <pmc_lib.h>

/*----------------------------------------------------------------------------*/

/* for signal() with BSD behavior, on Linux 2.0.28 but not 2.0.36,
 * #define __USE_BSD_SIGNAL
 */
#include <signal.h>

/* catch these signals */
static int signals[] = { SIGHUP, SIGINT, SIGQUIT, SIGUSR1, SIGTERM };
	/* cannot catch SIGKILL or SIGSTOP */

/* number of signals being caught */
#define signals_n (sizeof(signals) / sizeof(signals[0]))

/*----------------------------------------------------------------------------*/

/* these are global for use by the signal handler */

pmc_control_t Ctl;
int Argc;
char ** Argv;

/*----------------------------------------------------------------------------*/

static void signal_handler(int signal_number)
{
  /* print some useful information */
  printf("signal %d received\n", signal_number);
  pmc_print_results(Argc, Argv, &Ctl);

  /* pick one */
	/* reset the signal to its default behavior */
	/* ANSI C does this automatically */
	signal(signal_number, SIG_DFL);

	/* reset the signal to its previous behavior */
	{ int s = signal_number; pmc_restore_signals(1, &s); }

	/* reset the signal to its current behavior */
	/* BSD does this automatically */
	signal(signal_number, signal_handler);

  /* force a call to pmc_close() */
  exit(signal_number);
}

/*----------------------------------------------------------------------------*/

int main(int argc, char *argv[])
{
  pmc_data_t t0, t1;
  pmc_cycles_t elapsed;
  int i;

  Argc = argc;
  Argv = argv;

  Ctl = pmc_control_null;

  pmc_catch_signals(signals_n, signals, signal_handler);

  if (pmc_getargs(stderr, argv[0], &argc, &argv, &Ctl) == FALSE)
    { exit(1); }

  if (pmc_open(0) == FALSE)	/* open /dev/pmc */
    { exit(1); }

  for (i = 0; i < Ctl.num_counters; i++)
    {
      if (pmc_select(&Ctl.counters[i]) == FALSE)
	{ printf("pmc_select() failed\n"); exit(1); }

      pmc_read(&t0);

      { /* do something */
	double j, k = 0, lim = 100000000;
	for (j = 0; j < lim; j++) { k += j; }
      }

      pmc_read(&t1);

      elapsed = pmc_accumulate(&Ctl.counters[i], &t1, &t0);
    }

  pmc_close();			/* close /dev/pmc */

  pmc_print_results(Argc, Argv, &Ctl);

  pmc_restore_signals(signals_n, signals);

  exit(0);
}

/*----------------------------------------------------------------------------*/
