From 366ca4d70a2064364dbb76b9a2209cbae8953f67 Mon Sep 17 00:00:00 2001 From: Yogesh Tillu Date: Thu, 29 Jan 2015 10:12:36 +0100 Subject: initial commit Signed-off-by: Yogesh Tillu Signed-off-by: Anders Roxell --- perf_event_open.c | 99 +++++++++++++++++++++++++++++++++++ perf_readcounter_mmap.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 perf_event_open.c create mode 100644 perf_readcounter_mmap.c diff --git a/perf_event_open.c b/perf_event_open.c new file mode 100644 index 0000000..fb44469 --- /dev/null +++ b/perf_event_open.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +static int fddev = -1; +__attribute__((constructor)) static void +init(void) +{ + static struct perf_event_attr attr; + attr.type = PERF_TYPE_HARDWARE; + attr.config = PERF_COUNT_HW_CPU_CYCLES; + fddev = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0); +} + +__attribute__((destructor)) static void +fini(void) +{ + close(fddev); +} + + static inline long long +cpucycles(void) +{ + long long result = 0; + if (read(fddev, &result, sizeof(result)) < sizeof(result)) + return 0; + return result; +} + +/* Simple loop body to keep things interested. Make sure it gets inlined. */ + static inline int +loop(int* __restrict__ a, int* __restrict__ b, int n) +{ + unsigned sum = 0; + int i = 0; + for (i = 0; i < n; ++i) + if (a[i] > b[i]) + sum += a[i] + 5; + return sum; +} + + int +main(int ac, char **av) +{ + long long time_start = 0; + long long time_end = 0; + + int *a = NULL; + int *b = NULL; + int len = 0; + int i, sum = 0; + if (ac != 2) + return -1; + len = atoi(av[1]); + printf("%s: len = %d\n", av[0], len); + + a = malloc(len*sizeof(*a)); + b = malloc(len*sizeof(*b)); + + for (i = 0; i < len; ++i) { + a[i] = i+128; + b[i] = i+64; + } + printf("%s: beginning loop\n", av[0]); + time_start = time_end = 0; + /* --------------------Critical section-------------- */ + time_start = cpucycles(); + for (i = 0; i < 1000; i++) { + sum = loop(a, b, len); + cpucycles(); + } + time_end = cpucycles(); + /* ---------------------------------- */ + printf("sum = %d; Avg time delta[Loop + Read] = %llu\n", sum, + (time_end - time_start)/1000); + time_start = time_end = 0; + /* --------------------Critical section-------------- */ + time_start = cpucycles(); + for (i = 0; i < 1000; i++) + sum = loop(a, b, len); + time_end = cpucycles(); + /* ---------------------------------- */ + printf("sum = %d; Avg time delta[Loop]\t = %llu\n", sum, + (time_end - time_start)/1000); + free(a); + free(b); + return 0; +} diff --git a/perf_readcounter_mmap.c b/perf_readcounter_mmap.c new file mode 100644 index 0000000..38c1294 --- /dev/null +++ b/perf_readcounter_mmap.c @@ -0,0 +1,136 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Program to show read perf counter on ARMv8 from userspace using mmap way + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define barrier() asm volatile("" ::: "memory") +static int fddev = -1; + __attribute__((constructor)) static void +init(void) +{ + static struct perf_event_attr attr; + attr.type = PERF_TYPE_HARDWARE; + attr.config = PERF_COUNT_HW_CPU_CYCLES; + fddev = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0); +} + + __attribute__((destructor)) static void +fini(void) +{ + close(fddev); +} +#define ARMV8_PMCNTENSET_EL0_ENABLE (1<<31) /**< Enable Perf count reg */ + +static unsigned long rdpmc(unsigned int counter) +{ + unsigned long int ret; + asm volatile("mrs %0, pmccntr_el0" : "=r" (ret)); + return ret; +} +static unsigned long mmap_read_self(void *addr) +{ + struct perf_event_mmap_page *pc = addr; + unsigned int seq, idx; + unsigned long count; + signed long pmc = 0; + do { + count = 0; + seq = pc->lock; + barrier(); + idx = pc->index; + if (idx) + pmc = rdpmc(idx - 1); + barrier(); + } while (pc->lock != seq); + count = pmc; + return count; +} +/* Simple loop body to keep things interested. Make sure it gets inlined. */ + static inline int +loop(int* __restrict__ a, int* __restrict__ b, int n) +{ + unsigned sum = 0; + int i = 0; + for (i = 0; i < n; ++i) + if (a[i] > b[i]) + sum += a[i] + 5; + return sum; +} +static unsigned long page_size; + int +main(int ac, char **av) +{ + long long time_start = 0; + long long time_end = 0; + + int *a = NULL; + int *b = NULL; + int len = 0; + int i, sum = 0; + void *addr; /* mmaped address */ + unsigned long start_count, stop_count; + if (ac != 2) + return -1; + len = atoi(av[1]); + printf("%s: len = %d\n", av[0], len); + + a = malloc(len*sizeof(*a)); + b = malloc(len*sizeof(*b)); + + for (i = 0; i < len; ++i) { + a[i] = i+128; + b[i] = i+64; + } + + page_size = sysconf(_SC_PAGESIZE); + + /*Allocate memory for the page size */ + addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fddev, 0); + if (addr == (void *)(-1)) { + printf("Error: mmap() syscall returned with (%s)\n", + strerror(errno)); + return 0; + } + i = 0; + start_count = stop_count = 0; + /* --------------------Critical section-------------- */ + start_count = mmap_read_self(addr); + for (i = 0; i < 1000; i++) { + sum = loop(a, b, len); + mmap_read_self(addr); + } + stop_count = mmap_read_self(addr); + /* --------------------End Critical section-------------- */ + printf("sum=%d Avg count [ Loop + Read ] is = %ld\n", sum, + (stop_count-start_count)/1000); + start_count = stop_count = 0; + /* --------------------Critical section-------------- */ + start_count = mmap_read_self(addr); + for (i = 0; i < 1000; i++) + sum = loop(a, b, len); + stop_count = mmap_read_self(addr); + /* --------------------End Critical section-------------- */ + printf("sum=%d Avg count [ Loop ] \t is = %ld\n", sum, + (stop_count-start_count)/1000); + munmap(addr, page_size); + free(a); + free(b); + return 0; +} -- cgit v1.2.3