Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/counter: Create Counter tools

This creates an example Counter program under tools/counter/*
to exemplify the Counter character device interface.

Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Link: https://lore.kernel.org/r/7c0f975ba098952122302d258ec9ffdef04befaf.1632884256.git.vilhelm.gray@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

William Breathitt Gray and committed by
Jonathan Cameron
08609989 a8a28737

+154 -6
+1
MAINTAINERS
··· 4805 4805 F: drivers/counter/ 4806 4806 F: include/linux/counter.h 4807 4807 F: include/uapi/linux/counter.h 4808 + F: tools/counter/ 4808 4809 4809 4810 CP2615 I2C DRIVER 4810 4811 M: Bence Csókás <bence98@sch.bme.hu>
+7 -6
tools/Makefile
··· 12 12 @echo ' acpi - ACPI tools' 13 13 @echo ' bpf - misc BPF tools' 14 14 @echo ' cgroup - cgroup tools' 15 + @echo ' counter - counter tools' 15 16 @echo ' cpupower - a tool for all things x86 CPU power' 16 17 @echo ' debugging - tools for debugging' 17 18 @echo ' firewire - the userspace part of nosy, an IEEE-1394 traffic sniffer' ··· 66 65 cpupower: FORCE 67 66 $(call descend,power/$@) 68 67 69 - cgroup firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 68 + cgroup counter firewire hv guest bootconfig spi usb virtio vm bpf iio gpio objtool leds wmi pci firmware debugging tracing: FORCE 70 69 $(call descend,$@) 71 70 72 71 bpf/%: FORCE ··· 101 100 kvm_stat: FORCE 102 101 $(call descend,kvm/$@) 103 102 104 - all: acpi cgroup cpupower gpio hv firewire liblockdep \ 103 + all: acpi cgroup counter cpupower gpio hv firewire liblockdep \ 105 104 perf selftests bootconfig spi turbostat usb \ 106 105 virtio vm bpf x86_energy_perf_policy \ 107 106 tmon freefall iio objtool kvm_stat wmi \ ··· 113 112 cpupower_install: 114 113 $(call descend,power/$(@:_install=),install) 115 114 116 - cgroup_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 115 + cgroup_install counter_install firewire_install gpio_install hv_install iio_install perf_install bootconfig_install spi_install usb_install virtio_install vm_install bpf_install objtool_install wmi_install pci_install debugging_install tracing_install: 117 116 $(call descend,$(@:_install=),install) 118 117 119 118 liblockdep_install: ··· 134 133 kvm_stat_install: 135 134 $(call descend,kvm/$(@:_install=),install) 136 135 137 - install: acpi_install cgroup_install cpupower_install gpio_install \ 136 + install: acpi_install cgroup_install counter_install cpupower_install gpio_install \ 138 137 hv_install firewire_install iio_install liblockdep_install \ 139 138 perf_install selftests_install turbostat_install usb_install \ 140 139 virtio_install vm_install bpf_install x86_energy_perf_policy_install \ ··· 148 147 cpupower_clean: 149 148 $(call descend,power/cpupower,clean) 150 149 151 - cgroup_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 150 + cgroup_clean counter_clean hv_clean firewire_clean bootconfig_clean spi_clean usb_clean virtio_clean vm_clean wmi_clean bpf_clean iio_clean gpio_clean objtool_clean leds_clean pci_clean firmware_clean debugging_clean tracing_clean: 152 151 $(call descend,$(@:_clean=),clean) 153 152 154 153 liblockdep_clean: ··· 182 181 build_clean: 183 182 $(call descend,build,clean) 184 183 185 - clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ 184 + clean: acpi_clean cgroup_clean counter_clean cpupower_clean hv_clean firewire_clean \ 186 185 perf_clean selftests_clean turbostat_clean bootconfig_clean spi_clean usb_clean virtio_clean \ 187 186 vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ 188 187 freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
+1
tools/counter/Build
··· 1 + counter_example-y += counter_example.o
+53
tools/counter/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + include ../scripts/Makefile.include 3 + 4 + bindir ?= /usr/bin 5 + 6 + ifeq ($(srctree),) 7 + srctree := $(patsubst %/,%,$(dir $(CURDIR))) 8 + srctree := $(patsubst %/,%,$(dir $(srctree))) 9 + endif 10 + 11 + # Do not use make's built-in rules 12 + # (this improves performance and avoids hard-to-debug behaviour); 13 + MAKEFLAGS += -r 14 + 15 + override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include 16 + 17 + ALL_TARGETS := counter_example 18 + ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS)) 19 + 20 + all: $(ALL_PROGRAMS) 21 + 22 + export srctree OUTPUT CC LD CFLAGS 23 + include $(srctree)/tools/build/Makefile.include 24 + 25 + # 26 + # We need the following to be outside of kernel tree 27 + # 28 + $(OUTPUT)include/linux/counter.h: ../../include/uapi/linux/counter.h 29 + mkdir -p $(OUTPUT)include/linux 2>&1 || true 30 + ln -sf $(CURDIR)/../../include/uapi/linux/counter.h $@ 31 + 32 + prepare: $(OUTPUT)include/linux/counter.h 33 + 34 + COUNTER_EXAMPLE := $(OUTPUT)counter_example.o 35 + $(COUNTER_EXAMPLE): prepare FORCE 36 + $(Q)$(MAKE) $(build)=counter_example 37 + $(OUTPUT)counter_example: $(COUNTER_EXAMPLE) 38 + $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ 39 + 40 + clean: 41 + rm -f $(ALL_PROGRAMS) 42 + rm -rf $(OUTPUT)include/linux/counter.h 43 + find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete 44 + 45 + install: $(ALL_PROGRAMS) 46 + install -d -m 755 $(DESTDIR)$(bindir); \ 47 + for program in $(ALL_PROGRAMS); do \ 48 + install $$program $(DESTDIR)$(bindir); \ 49 + done 50 + 51 + FORCE: 52 + 53 + .PHONY: all install clean FORCE prepare
+92
tools/counter/counter_example.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Counter - example userspace application 3 + * 4 + * The userspace application opens /dev/counter0, configures the 5 + * COUNTER_EVENT_INDEX event channel 0 to gather Count 0 count and Count 6 + * 1 count, and prints out the data as it becomes available on the 7 + * character device node. 8 + * 9 + * Copyright (C) 2021 William Breathitt Gray 10 + */ 11 + #include <errno.h> 12 + #include <fcntl.h> 13 + #include <linux/counter.h> 14 + #include <stdio.h> 15 + #include <string.h> 16 + #include <sys/ioctl.h> 17 + #include <unistd.h> 18 + 19 + static struct counter_watch watches[2] = { 20 + { 21 + /* Component data: Count 0 count */ 22 + .component.type = COUNTER_COMPONENT_COUNT, 23 + .component.scope = COUNTER_SCOPE_COUNT, 24 + .component.parent = 0, 25 + /* Event type: Index */ 26 + .event = COUNTER_EVENT_INDEX, 27 + /* Device event channel 0 */ 28 + .channel = 0, 29 + }, 30 + { 31 + /* Component data: Count 1 count */ 32 + .component.type = COUNTER_COMPONENT_COUNT, 33 + .component.scope = COUNTER_SCOPE_COUNT, 34 + .component.parent = 1, 35 + /* Event type: Index */ 36 + .event = COUNTER_EVENT_INDEX, 37 + /* Device event channel 0 */ 38 + .channel = 0, 39 + }, 40 + }; 41 + 42 + int main(void) 43 + { 44 + int fd; 45 + int ret; 46 + int i; 47 + struct counter_event event_data[2]; 48 + 49 + fd = open("/dev/counter0", O_RDWR); 50 + if (fd == -1) { 51 + perror("Unable to open /dev/counter0"); 52 + return 1; 53 + } 54 + 55 + for (i = 0; i < 2; i++) { 56 + ret = ioctl(fd, COUNTER_ADD_WATCH_IOCTL, watches + i); 57 + if (ret == -1) { 58 + fprintf(stderr, "Error adding watches[%d]: %s\n", i, 59 + strerror(errno)); 60 + return 1; 61 + } 62 + } 63 + ret = ioctl(fd, COUNTER_ENABLE_EVENTS_IOCTL); 64 + if (ret == -1) { 65 + perror("Error enabling events"); 66 + return 1; 67 + } 68 + 69 + for (;;) { 70 + ret = read(fd, event_data, sizeof(event_data)); 71 + if (ret == -1) { 72 + perror("Failed to read event data"); 73 + return 1; 74 + } 75 + 76 + if (ret != sizeof(event_data)) { 77 + fprintf(stderr, "Failed to read event data\n"); 78 + return -EIO; 79 + } 80 + 81 + printf("Timestamp 0: %llu\tCount 0: %llu\n" 82 + "Error Message 0: %s\n" 83 + "Timestamp 1: %llu\tCount 1: %llu\n" 84 + "Error Message 1: %s\n", 85 + event_data[0].timestamp, event_data[0].value, 86 + strerror(event_data[0].status), 87 + event_data[1].timestamp, event_data[1].value, 88 + strerror(event_data[1].status)); 89 + } 90 + 91 + return 0; 92 + }