1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * Ones' complement checksum test & benchmark 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2016-2020, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#define _GNU_SOURCE 9bbbf1280Sopenharmony_ci#include <inttypes.h> 10bbbf1280Sopenharmony_ci#include <stdbool.h> 11bbbf1280Sopenharmony_ci#include <stdint.h> 12bbbf1280Sopenharmony_ci#include <stdio.h> 13bbbf1280Sopenharmony_ci#include <stdlib.h> 14bbbf1280Sopenharmony_ci#include <string.h> 15bbbf1280Sopenharmony_ci#include <sys/mman.h> 16bbbf1280Sopenharmony_ci#include <time.h> 17bbbf1280Sopenharmony_ci#include <unistd.h> 18bbbf1280Sopenharmony_ci#include "../include/networking.h" 19bbbf1280Sopenharmony_ci 20bbbf1280Sopenharmony_ci#if WANT_ASSERT 21bbbf1280Sopenharmony_ci#undef NDEBUG 22bbbf1280Sopenharmony_ci#include <assert.h> 23bbbf1280Sopenharmony_ci#define Assert(exp) assert(exp) 24bbbf1280Sopenharmony_ci#else 25bbbf1280Sopenharmony_ci#define Assert(exp) (void) (exp) 26bbbf1280Sopenharmony_ci#endif 27bbbf1280Sopenharmony_ci 28bbbf1280Sopenharmony_ci#ifdef __GNUC__ 29bbbf1280Sopenharmony_ci#define may_alias __attribute__((__may_alias__)) 30bbbf1280Sopenharmony_ci#else 31bbbf1280Sopenharmony_ci#define may_alias 32bbbf1280Sopenharmony_ci#endif 33bbbf1280Sopenharmony_ci 34bbbf1280Sopenharmony_ci#define CACHE_LINE 64 35bbbf1280Sopenharmony_ci#define ALIGN(x, y) (((x) + (y) - 1) & ~((y) - 1)) 36bbbf1280Sopenharmony_ci 37bbbf1280Sopenharmony_ci/* Reference implementation - do not modify! */ 38bbbf1280Sopenharmony_cistatic uint16_t 39bbbf1280Sopenharmony_cichecksum_simple(const void *ptr, uint32_t nbytes) 40bbbf1280Sopenharmony_ci{ 41bbbf1280Sopenharmony_ci const uint16_t *may_alias hptr = ptr; 42bbbf1280Sopenharmony_ci uint64_t sum = 0;/* Need 64-bit accumulator when nbytes > 64K */ 43bbbf1280Sopenharmony_ci 44bbbf1280Sopenharmony_ci /* Sum all halfwords, assume misaligned accesses are handled in HW */ 45bbbf1280Sopenharmony_ci for (uint32_t nhalfs = nbytes >> 1; nhalfs != 0; nhalfs--) 46bbbf1280Sopenharmony_ci { 47bbbf1280Sopenharmony_ci sum += *hptr++; 48bbbf1280Sopenharmony_ci } 49bbbf1280Sopenharmony_ci 50bbbf1280Sopenharmony_ci /* Add any trailing odd byte */ 51bbbf1280Sopenharmony_ci if ((nbytes & 0x01) != 0) 52bbbf1280Sopenharmony_ci { 53bbbf1280Sopenharmony_ci sum += *(uint8_t *) hptr; 54bbbf1280Sopenharmony_ci } 55bbbf1280Sopenharmony_ci 56bbbf1280Sopenharmony_ci /* Fold 64-bit sum to 32 bits */ 57bbbf1280Sopenharmony_ci sum = (sum & 0xffffffff) + (sum >> 32); 58bbbf1280Sopenharmony_ci sum = (sum & 0xffffffff) + (sum >> 32); 59bbbf1280Sopenharmony_ci Assert(sum == (uint32_t) sum); 60bbbf1280Sopenharmony_ci 61bbbf1280Sopenharmony_ci /* Fold 32-bit sum to 16 bits */ 62bbbf1280Sopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 63bbbf1280Sopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 64bbbf1280Sopenharmony_ci Assert(sum == (uint16_t) sum); 65bbbf1280Sopenharmony_ci 66bbbf1280Sopenharmony_ci return (uint16_t) sum; 67bbbf1280Sopenharmony_ci} 68bbbf1280Sopenharmony_ci 69bbbf1280Sopenharmony_cistatic struct 70bbbf1280Sopenharmony_ci{ 71bbbf1280Sopenharmony_ci uint16_t (*cksum_fp)(const void *, uint32_t); 72bbbf1280Sopenharmony_ci const char *name; 73bbbf1280Sopenharmony_ci} implementations[] = 74bbbf1280Sopenharmony_ci{ 75bbbf1280Sopenharmony_ci { checksum_simple, "simple"}, 76bbbf1280Sopenharmony_ci { __chksum, "scalar"}, 77bbbf1280Sopenharmony_ci#if __arm__ 78bbbf1280Sopenharmony_ci { __chksum_arm_simd, "simd" }, 79bbbf1280Sopenharmony_ci#elif __aarch64__ 80bbbf1280Sopenharmony_ci { __chksum_aarch64_simd, "simd" }, 81bbbf1280Sopenharmony_ci#endif 82bbbf1280Sopenharmony_ci { NULL, NULL} 83bbbf1280Sopenharmony_ci}; 84bbbf1280Sopenharmony_ci 85bbbf1280Sopenharmony_cistatic int 86bbbf1280Sopenharmony_cifind_impl(const char *name) 87bbbf1280Sopenharmony_ci{ 88bbbf1280Sopenharmony_ci for (int i = 0; implementations[i].name != NULL; i++) 89bbbf1280Sopenharmony_ci { 90bbbf1280Sopenharmony_ci if (strcmp(implementations[i].name, name) == 0) 91bbbf1280Sopenharmony_ci { 92bbbf1280Sopenharmony_ci return i; 93bbbf1280Sopenharmony_ci } 94bbbf1280Sopenharmony_ci } 95bbbf1280Sopenharmony_ci return -1; 96bbbf1280Sopenharmony_ci} 97bbbf1280Sopenharmony_ci 98bbbf1280Sopenharmony_cistatic uint16_t (*CKSUM_FP)(const void *, uint32_t); 99bbbf1280Sopenharmony_cistatic volatile uint16_t SINK; 100bbbf1280Sopenharmony_ci 101bbbf1280Sopenharmony_cistatic bool 102bbbf1280Sopenharmony_civerify(const void *data, uint32_t offset, uint32_t size) 103bbbf1280Sopenharmony_ci{ 104bbbf1280Sopenharmony_ci 105bbbf1280Sopenharmony_ci uint16_t csum_expected = checksum_simple(data, size); 106bbbf1280Sopenharmony_ci uint16_t csum_actual = CKSUM_FP(data, size); 107bbbf1280Sopenharmony_ci if (csum_actual != csum_expected) 108bbbf1280Sopenharmony_ci { 109bbbf1280Sopenharmony_ci fprintf(stderr, "\nInvalid checksum for offset %u size %u: " 110bbbf1280Sopenharmony_ci "actual %04x expected %04x (valid)", 111bbbf1280Sopenharmony_ci offset, size, csum_actual, csum_expected); 112bbbf1280Sopenharmony_ci if (size < 65536) 113bbbf1280Sopenharmony_ci { 114bbbf1280Sopenharmony_ci /* Fatal error */ 115bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 116bbbf1280Sopenharmony_ci } 117bbbf1280Sopenharmony_ci /* Else some implementations only support sizes up to 2^16 */ 118bbbf1280Sopenharmony_ci return false; 119bbbf1280Sopenharmony_ci } 120bbbf1280Sopenharmony_ci return true; 121bbbf1280Sopenharmony_ci} 122bbbf1280Sopenharmony_ci 123bbbf1280Sopenharmony_cistatic uint64_t 124bbbf1280Sopenharmony_ciclock_get_ns(void) 125bbbf1280Sopenharmony_ci{ 126bbbf1280Sopenharmony_ci struct timespec ts; 127bbbf1280Sopenharmony_ci clock_gettime(CLOCK_MONOTONIC, &ts); 128bbbf1280Sopenharmony_ci return ts.tv_sec * (uint64_t) 1000000000 + ts.tv_nsec; 129bbbf1280Sopenharmony_ci} 130bbbf1280Sopenharmony_ci 131bbbf1280Sopenharmony_cistatic void 132bbbf1280Sopenharmony_cibenchmark(const uint8_t *base, 133bbbf1280Sopenharmony_ci size_t poolsize, 134bbbf1280Sopenharmony_ci uint32_t blksize, 135bbbf1280Sopenharmony_ci uint32_t numops, 136bbbf1280Sopenharmony_ci uint64_t cpufreq) 137bbbf1280Sopenharmony_ci{ 138bbbf1280Sopenharmony_ci printf("%11u ", (unsigned int) blksize); fflush(stdout); 139bbbf1280Sopenharmony_ci 140bbbf1280Sopenharmony_ci uint64_t start = clock_get_ns(); 141bbbf1280Sopenharmony_ci for (uint32_t i = 0; i < numops; i ++) 142bbbf1280Sopenharmony_ci { 143bbbf1280Sopenharmony_ci /* Read a random value from the pool */ 144bbbf1280Sopenharmony_ci uint32_t random = ((uint32_t *) base)[i % (poolsize / 4)]; 145bbbf1280Sopenharmony_ci /* Generate a random starting address */ 146bbbf1280Sopenharmony_ci const void *data = &base[random % (poolsize - blksize)]; 147bbbf1280Sopenharmony_ci SINK = CKSUM_FP(data, blksize); 148bbbf1280Sopenharmony_ci } 149bbbf1280Sopenharmony_ci uint64_t end = clock_get_ns(); 150bbbf1280Sopenharmony_ci 151bbbf1280Sopenharmony_ci#define MEGABYTE 1000000 /* Decimal megabyte (MB) */ 152bbbf1280Sopenharmony_ci uint64_t elapsed_ns = end - start; 153bbbf1280Sopenharmony_ci uint64_t elapsed_ms = elapsed_ns / 1000000; 154bbbf1280Sopenharmony_ci uint32_t blks_per_s = (uint32_t) ((numops / elapsed_ms) * 1000); 155bbbf1280Sopenharmony_ci uint64_t accbytes = (uint64_t) numops * blksize; 156bbbf1280Sopenharmony_ci printf("%11ju ", (uintmax_t) ((accbytes / elapsed_ms) * 1000) / MEGABYTE); 157bbbf1280Sopenharmony_ci unsigned int cyc_per_blk = cpufreq / blks_per_s; 158bbbf1280Sopenharmony_ci printf("%11u ", cyc_per_blk); 159bbbf1280Sopenharmony_ci if (blksize != 0) 160bbbf1280Sopenharmony_ci { 161bbbf1280Sopenharmony_ci unsigned int cyc_per_byte = 1000 * cyc_per_blk / blksize; 162bbbf1280Sopenharmony_ci printf("%7u.%03u ", 163bbbf1280Sopenharmony_ci cyc_per_byte / 1000, cyc_per_byte % 1000); 164bbbf1280Sopenharmony_ci } 165bbbf1280Sopenharmony_ci printf("\n"); 166bbbf1280Sopenharmony_ci} 167bbbf1280Sopenharmony_ci 168bbbf1280Sopenharmony_ciint main(int argc, char *argv[]) 169bbbf1280Sopenharmony_ci{ 170bbbf1280Sopenharmony_ci int c; 171bbbf1280Sopenharmony_ci bool DUMP = false; 172bbbf1280Sopenharmony_ci uint32_t IMPL = 0;/* Simple implementation */ 173bbbf1280Sopenharmony_ci uint64_t CPUFREQ = 0; 174bbbf1280Sopenharmony_ci uint32_t BLKSIZE = 0; 175bbbf1280Sopenharmony_ci uint32_t NUMOPS = 1000000; 176bbbf1280Sopenharmony_ci uint32_t POOLSIZE = 512 * 1024;/* Typical ARM L2 cache size */ 177bbbf1280Sopenharmony_ci 178bbbf1280Sopenharmony_ci setvbuf(stdout, NULL, _IOLBF, 160); 179bbbf1280Sopenharmony_ci while ((c = getopt(argc, argv, "b:df:i:n:p:")) != -1) 180bbbf1280Sopenharmony_ci { 181bbbf1280Sopenharmony_ci switch (c) 182bbbf1280Sopenharmony_ci { 183bbbf1280Sopenharmony_ci case 'b' : 184bbbf1280Sopenharmony_ci { 185bbbf1280Sopenharmony_ci int blksize = atoi(optarg); 186bbbf1280Sopenharmony_ci if (blksize < 1 || blksize > POOLSIZE / 2) 187bbbf1280Sopenharmony_ci { 188bbbf1280Sopenharmony_ci fprintf(stderr, "Invalid block size %d\n", blksize); 189bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 190bbbf1280Sopenharmony_ci } 191bbbf1280Sopenharmony_ci BLKSIZE = (unsigned) blksize; 192bbbf1280Sopenharmony_ci break; 193bbbf1280Sopenharmony_ci } 194bbbf1280Sopenharmony_ci case 'd' : 195bbbf1280Sopenharmony_ci DUMP = true; 196bbbf1280Sopenharmony_ci break; 197bbbf1280Sopenharmony_ci case 'f' : 198bbbf1280Sopenharmony_ci { 199bbbf1280Sopenharmony_ci int64_t cpufreq = atoll(optarg); 200bbbf1280Sopenharmony_ci if (cpufreq < 1) 201bbbf1280Sopenharmony_ci { 202bbbf1280Sopenharmony_ci fprintf(stderr, "Invalid CPU frequency %"PRId64"\n", 203bbbf1280Sopenharmony_ci cpufreq); 204bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 205bbbf1280Sopenharmony_ci } 206bbbf1280Sopenharmony_ci CPUFREQ = cpufreq; 207bbbf1280Sopenharmony_ci break; 208bbbf1280Sopenharmony_ci } 209bbbf1280Sopenharmony_ci case 'i' : 210bbbf1280Sopenharmony_ci { 211bbbf1280Sopenharmony_ci int impl = find_impl(optarg); 212bbbf1280Sopenharmony_ci if (impl < 0) 213bbbf1280Sopenharmony_ci { 214bbbf1280Sopenharmony_ci fprintf(stderr, "Invalid implementation %s\n", optarg); 215bbbf1280Sopenharmony_ci goto usage; 216bbbf1280Sopenharmony_ci } 217bbbf1280Sopenharmony_ci IMPL = (unsigned) impl; 218bbbf1280Sopenharmony_ci break; 219bbbf1280Sopenharmony_ci } 220bbbf1280Sopenharmony_ci case 'n' : 221bbbf1280Sopenharmony_ci { 222bbbf1280Sopenharmony_ci int numops = atoi(optarg); 223bbbf1280Sopenharmony_ci if (numops < 1) 224bbbf1280Sopenharmony_ci { 225bbbf1280Sopenharmony_ci fprintf(stderr, "Invalid number of operations %d\n", numops); 226bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 227bbbf1280Sopenharmony_ci } 228bbbf1280Sopenharmony_ci NUMOPS = (unsigned) numops; 229bbbf1280Sopenharmony_ci break; 230bbbf1280Sopenharmony_ci } 231bbbf1280Sopenharmony_ci case 'p' : 232bbbf1280Sopenharmony_ci { 233bbbf1280Sopenharmony_ci int poolsize = atoi(optarg); 234bbbf1280Sopenharmony_ci if (poolsize < 4096) 235bbbf1280Sopenharmony_ci { 236bbbf1280Sopenharmony_ci fprintf(stderr, "Invalid pool size %d\n", poolsize); 237bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 238bbbf1280Sopenharmony_ci } 239bbbf1280Sopenharmony_ci char c = optarg[strlen(optarg) - 1]; 240bbbf1280Sopenharmony_ci if (c == 'M') 241bbbf1280Sopenharmony_ci { 242bbbf1280Sopenharmony_ci POOLSIZE = (unsigned) poolsize * 1024 * 1024; 243bbbf1280Sopenharmony_ci } 244bbbf1280Sopenharmony_ci else if (c == 'K') 245bbbf1280Sopenharmony_ci { 246bbbf1280Sopenharmony_ci POOLSIZE = (unsigned) poolsize * 1024; 247bbbf1280Sopenharmony_ci } 248bbbf1280Sopenharmony_ci else 249bbbf1280Sopenharmony_ci { 250bbbf1280Sopenharmony_ci POOLSIZE = (unsigned) poolsize; 251bbbf1280Sopenharmony_ci } 252bbbf1280Sopenharmony_ci break; 253bbbf1280Sopenharmony_ci } 254bbbf1280Sopenharmony_ci default : 255bbbf1280Sopenharmony_ciusage : 256bbbf1280Sopenharmony_ci fprintf(stderr, "Usage: checksum <options>\n" 257bbbf1280Sopenharmony_ci "-b <blksize> Block size\n" 258bbbf1280Sopenharmony_ci "-d Dump first 96 bytes of data\n" 259bbbf1280Sopenharmony_ci "-f <cpufreq> CPU frequency (Hz)\n" 260bbbf1280Sopenharmony_ci "-i <impl> Implementation\n" 261bbbf1280Sopenharmony_ci "-n <numops> Number of operations\n" 262bbbf1280Sopenharmony_ci "-p <poolsize> Pool size (K or M suffix)\n" 263bbbf1280Sopenharmony_ci ); 264bbbf1280Sopenharmony_ci printf("Implementations:"); 265bbbf1280Sopenharmony_ci for (int i = 0; implementations[i].name != NULL; i++) 266bbbf1280Sopenharmony_ci { 267bbbf1280Sopenharmony_ci printf(" %s", implementations[i].name); 268bbbf1280Sopenharmony_ci } 269bbbf1280Sopenharmony_ci printf("\n"); 270bbbf1280Sopenharmony_ci exit(EXIT_FAILURE); 271bbbf1280Sopenharmony_ci } 272bbbf1280Sopenharmony_ci } 273bbbf1280Sopenharmony_ci if (optind > argc) 274bbbf1280Sopenharmony_ci { 275bbbf1280Sopenharmony_ci goto usage; 276bbbf1280Sopenharmony_ci } 277bbbf1280Sopenharmony_ci 278bbbf1280Sopenharmony_ci CKSUM_FP = implementations[IMPL].cksum_fp; 279bbbf1280Sopenharmony_ci POOLSIZE = ALIGN(POOLSIZE, CACHE_LINE); 280bbbf1280Sopenharmony_ci uint8_t *base = mmap(0, POOLSIZE, PROT_READ|PROT_WRITE, 281bbbf1280Sopenharmony_ci MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 282bbbf1280Sopenharmony_ci if (base == MAP_FAILED) 283bbbf1280Sopenharmony_ci { 284bbbf1280Sopenharmony_ci perror("aligned_alloc"), exit(EXIT_FAILURE); 285bbbf1280Sopenharmony_ci } 286bbbf1280Sopenharmony_ci for (size_t i = 0; i < POOLSIZE / 4; i++) 287bbbf1280Sopenharmony_ci { 288bbbf1280Sopenharmony_ci ((uint32_t *) base)[i] = rand(); 289bbbf1280Sopenharmony_ci } 290bbbf1280Sopenharmony_ci 291bbbf1280Sopenharmony_ci printf("Implementation: %s\n", implementations[IMPL].name); 292bbbf1280Sopenharmony_ci printf("numops %u, poolsize ", NUMOPS); 293bbbf1280Sopenharmony_ci if (POOLSIZE % (1024 * 1024) == 0) 294bbbf1280Sopenharmony_ci { 295bbbf1280Sopenharmony_ci printf("%uMiB", POOLSIZE / (1024 * 1024)); 296bbbf1280Sopenharmony_ci } 297bbbf1280Sopenharmony_ci else if (POOLSIZE % 1024 == 0) 298bbbf1280Sopenharmony_ci { 299bbbf1280Sopenharmony_ci printf("%uKiB", POOLSIZE / 1024); 300bbbf1280Sopenharmony_ci } 301bbbf1280Sopenharmony_ci else 302bbbf1280Sopenharmony_ci { 303bbbf1280Sopenharmony_ci printf("%uB", POOLSIZE); 304bbbf1280Sopenharmony_ci } 305bbbf1280Sopenharmony_ci printf(", blocksize %u, CPU frequency %juMHz\n", 306bbbf1280Sopenharmony_ci BLKSIZE, (uintmax_t) (CPUFREQ / 1000000)); 307bbbf1280Sopenharmony_ci#if WANT_ASSERT 308bbbf1280Sopenharmony_ci printf("Warning: assertions are enabled\n"); 309bbbf1280Sopenharmony_ci#endif 310bbbf1280Sopenharmony_ci 311bbbf1280Sopenharmony_ci if (DUMP) 312bbbf1280Sopenharmony_ci { 313bbbf1280Sopenharmony_ci /* Print out first 96 bytes of data for human debugging */ 314bbbf1280Sopenharmony_ci for (int i = 0; i < 96; i++) 315bbbf1280Sopenharmony_ci { 316bbbf1280Sopenharmony_ci if (i % 8 == 0) 317bbbf1280Sopenharmony_ci printf("%2u:", i); 318bbbf1280Sopenharmony_ci printf(" %02x", base[i]); 319bbbf1280Sopenharmony_ci if (i % 8 == 7) 320bbbf1280Sopenharmony_ci printf("\n"); 321bbbf1280Sopenharmony_ci } 322bbbf1280Sopenharmony_ci } 323bbbf1280Sopenharmony_ci 324bbbf1280Sopenharmony_ci /* Verify that chosen algorithm handles all combinations of offsets and sizes */ 325bbbf1280Sopenharmony_ci printf("Verifying..."); fflush(stdout); 326bbbf1280Sopenharmony_ci bool success = true; 327bbbf1280Sopenharmony_ci /* Check all (relevant) combinations of size and offset */ 328bbbf1280Sopenharmony_ci for (int size = 0; size <= 256; size++) 329bbbf1280Sopenharmony_ci { 330bbbf1280Sopenharmony_ci for (int offset = 0; offset < 255; offset++) 331bbbf1280Sopenharmony_ci { 332bbbf1280Sopenharmony_ci /* Check at start of mapped memory */ 333bbbf1280Sopenharmony_ci success &= verify(&base[offset], offset, size); 334bbbf1280Sopenharmony_ci /* Check at end of mapped memory */ 335bbbf1280Sopenharmony_ci uint8_t *p = base + POOLSIZE - (size + offset); 336bbbf1280Sopenharmony_ci success &= verify(p, (uintptr_t) p % 64, size); 337bbbf1280Sopenharmony_ci } 338bbbf1280Sopenharmony_ci } 339bbbf1280Sopenharmony_ci /* Check increasingly larger sizes */ 340bbbf1280Sopenharmony_ci for (size_t size = 1; size < POOLSIZE; size *= 2) 341bbbf1280Sopenharmony_ci { 342bbbf1280Sopenharmony_ci success &= verify(base, 0, size); 343bbbf1280Sopenharmony_ci } 344bbbf1280Sopenharmony_ci /* Check the full size, this can detect accumulator overflows */ 345bbbf1280Sopenharmony_ci success &= verify(base, 0, POOLSIZE); 346bbbf1280Sopenharmony_ci printf("%s\n", success ? "OK" : "failure"); 347bbbf1280Sopenharmony_ci 348bbbf1280Sopenharmony_ci /* Print throughput in decimal megabyte (1000000B) per second */ 349bbbf1280Sopenharmony_ci if (CPUFREQ != 0) 350bbbf1280Sopenharmony_ci { 351bbbf1280Sopenharmony_ci printf("%11s %11s %11s %11s\n", 352bbbf1280Sopenharmony_ci "block size", "MB/s", "cycles/blk", "cycles/byte"); 353bbbf1280Sopenharmony_ci } 354bbbf1280Sopenharmony_ci else 355bbbf1280Sopenharmony_ci { 356bbbf1280Sopenharmony_ci printf("%11s %11s %11s %11s\n", 357bbbf1280Sopenharmony_ci "block size", "MB/s", "ns/blk", "ns/byte"); 358bbbf1280Sopenharmony_ci CPUFREQ = 1000000000; 359bbbf1280Sopenharmony_ci } 360bbbf1280Sopenharmony_ci if (BLKSIZE != 0) 361bbbf1280Sopenharmony_ci { 362bbbf1280Sopenharmony_ci benchmark(base, POOLSIZE, BLKSIZE, NUMOPS, CPUFREQ); 363bbbf1280Sopenharmony_ci } 364bbbf1280Sopenharmony_ci else 365bbbf1280Sopenharmony_ci { 366bbbf1280Sopenharmony_ci static const uint16_t sizes[] = 367bbbf1280Sopenharmony_ci { 20, 42, 102, 250, 612, 1500, 3674, 9000, 0 }; 368bbbf1280Sopenharmony_ci for (int i = 0; sizes[i] != 0; i++) 369bbbf1280Sopenharmony_ci { 370bbbf1280Sopenharmony_ci uint32_t numops = NUMOPS * 10000 / (40 + sizes[i]); 371bbbf1280Sopenharmony_ci benchmark(base, POOLSIZE, sizes[i], numops, CPUFREQ); 372bbbf1280Sopenharmony_ci } 373bbbf1280Sopenharmony_ci } 374bbbf1280Sopenharmony_ci 375bbbf1280Sopenharmony_ci if (munmap(base, POOLSIZE) != 0) 376bbbf1280Sopenharmony_ci { 377bbbf1280Sopenharmony_ci perror("munmap"), exit(EXIT_FAILURE); 378bbbf1280Sopenharmony_ci } 379bbbf1280Sopenharmony_ci 380bbbf1280Sopenharmony_ci return success ? EXIT_SUCCESS : EXIT_FAILURE; 381bbbf1280Sopenharmony_ci} 382