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