Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/counter/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 11 kB image not shown  

Quelle  counter_watch_events.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Counter Watch Events - Test various counter watch events in a userspace application
 *
 * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
 * Author: Fabrice Gasnier <fabrice.gasnier@foss.st.com>.
 */


#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/counter.h>
#include <linux/kernel.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

static struct counter_watch simple_watch[] = {
 {
  /* Component data: Count 0 count */
  .component.type = COUNTER_COMPONENT_COUNT,
  .component.scope = COUNTER_SCOPE_COUNT,
  .component.parent = 0,
  /* Event type: overflow or underflow */
  .event = COUNTER_EVENT_OVERFLOW_UNDERFLOW,
  /* Device event channel 0 */
  .channel = 0,
 },
};

static const char * const counter_event_type_name[] = {
 "COUNTER_EVENT_OVERFLOW",
 "COUNTER_EVENT_UNDERFLOW",
 "COUNTER_EVENT_OVERFLOW_UNDERFLOW",
 "COUNTER_EVENT_THRESHOLD",
 "COUNTER_EVENT_INDEX",
 "COUNTER_EVENT_CHANGE_OF_STATE",
 "COUNTER_EVENT_CAPTURE",
 "COUNTER_EVENT_DIRECTION_CHANGE",
};

static const char * const counter_component_type_name[] = {
 "COUNTER_COMPONENT_NONE",
 "COUNTER_COMPONENT_SIGNAL",
 "COUNTER_COMPONENT_COUNT",
 "COUNTER_COMPONENT_FUNCTION",
 "COUNTER_COMPONENT_SYNAPSE_ACTION",
 "COUNTER_COMPONENT_EXTENSION",
};

static const char * const counter_scope_name[] = {
 "COUNTER_SCOPE_DEVICE",
 "COUNTER_SCOPE_SIGNAL",
 "COUNTER_SCOPE_COUNT",
};

static void print_watch(struct counter_watch *watch, int nwatch)
{
 int i;

 /* prints the watch array in C-like structure */
 printf("watch[%d] = {\n", nwatch);
 for (i = 0; i < nwatch; i++) {
  printf(" [%d] =\t{\n"
         "\t\t.component.type = %s\n"
         "\t\t.component.scope = %s\n"
         "\t\t.component.parent = %d\n"
         "\t\t.component.id = %d\n"
         "\t\t.event = %s\n"
         "\t\t.channel = %d\n"
         "\t},\n",
         i,
         counter_component_type_name[watch[i].component.type],
         counter_scope_name[watch[i].component.scope],
         watch[i].component.parent,
         watch[i].component.id,
         counter_event_type_name[watch[i].event],
         watch[i].channel);
 }
 printf("};\n");
}

static void print_usage(void)
{
 fprintf(stderr, "Usage:\n\n"
  "counter_watch_events [options] [-w ]\n"
  "counter_watch_events [options] [-w ] [-w ]...\n"
  "\n"
  "When no --watch option has been provided, simple watch example is used:\n"
  "counter_watch_events [options] -w comp_count,scope_count,evt_ovf_udf\n"
  "\n"
  "Test various watch events for given counter device.\n"
  "\n"
  "Options:\n"
  " -d, --debug Prints debug information\n"
  " -h, --help Prints usage\n"
  " -n, --device-num Use /dev/counter [default: /dev/counter0]\n"
  " -l, --loop Loop for events [default: 0 (forever)]\n"
  " -w, --watch comma-separated list of watch options\n"
  "\n"
  "Watch options:\n"
  " scope_device (COUNTER_SCOPE_DEVICE) [default: scope_device]\n"
  " scope_signal (COUNTER_SCOPE_SIGNAL)\n"
  " scope_count (COUNTER_SCOPE_COUNT)\n"
  "\n"
  " comp_none (COUNTER_COMPONENT_NONE) [default: comp_none]\n"
  " comp_signal (COUNTER_COMPONENT_SIGNAL)\n"
  " comp_count (COUNTER_COMPONENT_COUNT)\n"
  " comp_function (COUNTER_COMPONENT_FUNCTION)\n"
  " comp_synapse_action (COUNTER_COMPONENT_SYNAPSE_ACTION)\n"
  " comp_extension (COUNTER_COMPONENT_EXTENSION)\n"
  "\n"
  " evt_ovf (COUNTER_EVENT_OVERFLOW) [default: evt_ovf]\n"
  " evt_udf (COUNTER_EVENT_UNDERFLOW)\n"
  " evt_ovf_udf (COUNTER_EVENT_OVERFLOW_UNDERFLOW)\n"
  " evt_threshold (COUNTER_EVENT_THRESHOLD)\n"
  " evt_index (COUNTER_EVENT_INDEX)\n"
  " evt_change_of_state (COUNTER_EVENT_CHANGE_OF_STATE)\n"
  " evt_capture (COUNTER_EVENT_CAPTURE)\n"
  " evt_direction_change (COUNTER_EVENT_DIRECTION_CHANGE)\n"
  "\n"
  " chan= channel for this watch [default: 0]\n"
  " id= component id for this watch [default: 0]\n"
  " parent= component parent for this watch [default: 0]\n"
  "\n"
  "Example with two watched events:\n\n"
  "counter_watch_events -d \\\n"
  "\t-w comp_count,scope_count,evt_ovf_udf \\\n"
  "\t-w comp_extension,scope_count,evt_capture,id=7,chan=3\n"
  );
}

static const struct option longopts[] = {
 { "debug",  no_argument,       0, 'd' },
 { "help",  no_argument,       0, 'h' },
 { "device-num",  required_argument, 0, 'n' },
 { "loop",  required_argument, 0, 'l' },
 { "watch",  required_argument, 0, 'w' },
 { },
};

/* counter watch subopts */
enum {
 WATCH_SCOPE_DEVICE,
 WATCH_SCOPE_SIGNAL,
 WATCH_SCOPE_COUNT,
 WATCH_COMPONENT_NONE,
 WATCH_COMPONENT_SIGNAL,
 WATCH_COMPONENT_COUNT,
 WATCH_COMPONENT_FUNCTION,
 WATCH_COMPONENT_SYNAPSE_ACTION,
 WATCH_COMPONENT_EXTENSION,
 WATCH_EVENT_OVERFLOW,
 WATCH_EVENT_UNDERFLOW,
 WATCH_EVENT_OVERFLOW_UNDERFLOW,
 WATCH_EVENT_THRESHOLD,
 WATCH_EVENT_INDEX,
 WATCH_EVENT_CHANGE_OF_STATE,
 WATCH_EVENT_CAPTURE,
 WATCH_EVENT_DIRECTION_CHANGE,
 WATCH_CHANNEL,
 WATCH_ID,
 WATCH_PARENT,
 WATCH_SUBOPTS_MAX,
};

static char * const counter_watch_subopts[WATCH_SUBOPTS_MAX + 1] = {
 /* component.scope */
 [WATCH_SCOPE_DEVICE] = "scope_device",
 [WATCH_SCOPE_SIGNAL] = "scope_signal",
 [WATCH_SCOPE_COUNT] = "scope_count",
 /* component.type */
 [WATCH_COMPONENT_NONE] = "comp_none",
 [WATCH_COMPONENT_SIGNAL] = "comp_signal",
 [WATCH_COMPONENT_COUNT] = "comp_count",
 [WATCH_COMPONENT_FUNCTION] = "comp_function",
 [WATCH_COMPONENT_SYNAPSE_ACTION] = "comp_synapse_action",
 [WATCH_COMPONENT_EXTENSION] = "comp_extension",
 /* event */
 [WATCH_EVENT_OVERFLOW] = "evt_ovf",
 [WATCH_EVENT_UNDERFLOW] = "evt_udf",
 [WATCH_EVENT_OVERFLOW_UNDERFLOW] = "evt_ovf_udf",
 [WATCH_EVENT_THRESHOLD] = "evt_threshold",
 [WATCH_EVENT_INDEX] = "evt_index",
 [WATCH_EVENT_CHANGE_OF_STATE] = "evt_change_of_state",
 [WATCH_EVENT_CAPTURE] = "evt_capture",
 [WATCH_EVENT_DIRECTION_CHANGE] = "evt_direction_change",
 /* channel, id, parent */
 [WATCH_CHANNEL] = "chan",
 [WATCH_ID] = "id",
 [WATCH_PARENT] = "parent",
 /* Empty entry ends the opts array */
 NULL
};

int main(int argc, char **argv)
{
 int c, fd, i, ret, rc = 0, debug = 0, loop = 0, dev_num = 0, nwatch = 0;
 struct counter_event event_data;
 char *device_name = NULL, *subopts, *value;
 struct counter_watch *watches;

 /*
 * 1st pass:
 * - list watch events number to allocate the watch array.
 * - parse normal options (other than watch options)
 */

 while ((c = getopt_long(argc, argv, "dhn:l:w:", longopts, NULL)) != -1) {
  switch (c) {
  case 'd':
   debug = 1;
   break;
  case 'h':
   print_usage();
   return EXIT_SUCCESS;
  case 'n':
   dev_num = strtoul(optarg, NULL, 10);
   if (errno) {
    perror("strtol failed: --device-num \n");
    return EXIT_FAILURE;
   }
   break;
  case 'l':
   loop = strtol(optarg, NULL, 10);
   if (errno) {
    perror("strtol failed: --loop \n");
    return EXIT_FAILURE;
   }
   break;
  case 'w':
   nwatch++;
   break;
  default:
   return EXIT_FAILURE;
  }
 }

 if (nwatch) {
  watches = calloc(nwatch, sizeof(*watches));
  if (!watches) {
   perror("Error allocating watches\n");
   return EXIT_FAILURE;
  }
 } else {
  /* default to simple watch example */
  watches = simple_watch;
  nwatch = ARRAY_SIZE(simple_watch);
 }

 /* 2nd pass: parse watch sub-options to fill in watch array */
 optind = 1;
 i = 0;
 while ((c = getopt_long(argc, argv, "dhn:l:w:", longopts, NULL)) != -1) {
  switch (c) {
  case 'w':
   subopts = optarg;
   while (*subopts != '\0') {
    ret = getsubopt(&subopts, counter_watch_subopts, &value);
    switch (ret) {
    case WATCH_SCOPE_DEVICE:
    case WATCH_SCOPE_SIGNAL:
    case WATCH_SCOPE_COUNT:
     /* match with counter_scope */
     watches[i].component.scope = ret;
     break;
    case WATCH_COMPONENT_NONE:
    case WATCH_COMPONENT_SIGNAL:
    case WATCH_COMPONENT_COUNT:
    case WATCH_COMPONENT_FUNCTION:
    case WATCH_COMPONENT_SYNAPSE_ACTION:
    case WATCH_COMPONENT_EXTENSION:
     /* match counter_component_type: subtract enum value */
     ret -= WATCH_COMPONENT_NONE;
     watches[i].component.type = ret;
     break;
    case WATCH_EVENT_OVERFLOW:
    case WATCH_EVENT_UNDERFLOW:
    case WATCH_EVENT_OVERFLOW_UNDERFLOW:
    case WATCH_EVENT_THRESHOLD:
    case WATCH_EVENT_INDEX:
    case WATCH_EVENT_CHANGE_OF_STATE:
    case WATCH_EVENT_CAPTURE:
    case WATCH_EVENT_DIRECTION_CHANGE:
     /* match counter_event_type: subtract enum value */
     ret -= WATCH_EVENT_OVERFLOW;
     watches[i].event = ret;
     break;
    case WATCH_CHANNEL:
     if (!value) {
      fprintf(stderr, "Invalid chan=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     watches[i].channel = strtoul(value, NULL, 10);
     if (errno) {
      perror("strtoul failed: chan=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     break;
    case WATCH_ID:
     if (!value) {
      fprintf(stderr, "Invalid id=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     watches[i].component.id = strtoul(value, NULL, 10);
     if (errno) {
      perror("strtoul failed: id=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     break;
    case WATCH_PARENT:
     if (!value) {
      fprintf(stderr, "Invalid parent=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     watches[i].component.parent = strtoul(value, NULL, 10);
     if (errno) {
      perror("strtoul failed: parent=\n");
      rc = EXIT_FAILURE;
      goto err_free_watches;
     }
     break;
    default:
     fprintf(stderr, "Unknown suboption '%s'\n", value);
     rc = EXIT_FAILURE;
     goto err_free_watches;
    }
   }
   i++;
   break;
  }
 }

 if (debug)
  print_watch(watches, nwatch);

 ret = asprintf(&device_name, "/dev/counter%d", dev_num);
 if (ret < 0) {
  fprintf(stderr, "asprintf failed\n");
  rc = EXIT_FAILURE;
  goto err_free_watches;
 }

 if (debug)
  printf("Opening %s\n", device_name);

 fd = open(device_name, O_RDWR);
 if (fd == -1) {
  fprintf(stderr, "Unable to open %s: %s\n", device_name, strerror(errno));
  free(device_name);
  rc = EXIT_FAILURE;
  goto err_free_watches;
 }
 free(device_name);

 for (i = 0; i < nwatch; i++) {
  ret = ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i);
  if (ret == -1) {
   fprintf(stderr, "Error adding watches[%d]: %s\n", i,
    strerror(errno));
   rc = EXIT_FAILURE;
   goto err_close;
  }
 }

 ret = ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL);
 if (ret == -1) {
  perror("Error enabling events");
  rc = EXIT_FAILURE;
  goto err_close;
 }

 for (i = 0; loop <= 0 || i < loop; i++) {
  ret = read(fd, &event_data, sizeof(event_data));
  if (ret == -1) {
   perror("Failed to read event data");
   rc = EXIT_FAILURE;
   goto err_close;
  }

  if (ret != sizeof(event_data)) {
   fprintf(stderr, "Failed to read event data (got: %d)\n", ret);
   rc = EXIT_FAILURE;
   goto err_close;
  }

  printf("Timestamp: %llu\tData: %llu\t event: %s\tch: %d\n",
         event_data.timestamp, event_data.value,
         counter_event_type_name[event_data.watch.event],
         event_data.watch.channel);

  if (event_data.status) {
   fprintf(stderr, "Error %d: %s\n", event_data.status,
    strerror(event_data.status));
  }
 }

err_close:
 close(fd);
err_free_watches:
 if (watches != simple_watch)
  free(watches);

 return rc;
}

Messung V0.5
C=96 H=71 G=84

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.