-/*----- Benchmarking ------------------------------------------------------*/
-
-struct bench_state *tvec_benchstate;
-
-struct benchrun {
- unsigned long *n;
- tvec_testfn *fn;
- const struct tvec_reg *in; struct tvec_reg *out;
- void *ctx;
-};
-
-static void benchloop_outer(unsigned long n, void *p)
- { struct benchrun *r = p; while (n--) r->fn(r->in, r->out, r->ctx); }
-
-static void benchloop_inner(unsigned long n, void *p)
- { struct benchrun *r = p; *r->n = n; r->fn(r->in, r->out, r->ctx); }
-
-int tvec_ensurebench(struct tvec_state *tv, struct bench_state **b_out)
-{
- const struct tvec_bench *tvb = tv->test->arg.p;
- struct bench_state **bb;
- struct bench_timer *bt;
-
- if (tvb->b) bb = tvb->b;
- else bb = &tvec_benchstate;
-
- if (!*bb) {
- bt = bench_createtimer();
- if (!bt) { tvec_skip(tv, "failed to create timer"); return (-1); }
- *bb = xmalloc(sizeof(**bb)); bench_init(*bb, bt);
- } else if (!(*bb)->tm)
- { tvec_skip(tv, "failed to create timer"); return (-1); }
-
- *b_out = *bb;
- return (0);
-}
-
-int tvec_bench(struct tvec_state *tv)
-{
- const struct tvec_bench *tvb = tv->test->arg.p;
- struct bench_state *b;
- struct bench_timing tm;
- struct benchrun r;
- bench_fn *loopfn;
-
- if (tvec_ensurebench(tv, &b)) goto end_0;
-
- r.in = tv->in; r.out = tv->out; r.fn = tv->test->fn;
- if (tvb->ctxsz) r.ctx = xmalloc(tvb->ctxsz);
- else r.ctx = 0;
- if (tvb->setup && tvb->setup(tv->in, tv->out, &tvb->arg, r.ctx))
- { tvec_skip(tv, "benchmark setup failed"); goto end_1; }
-
- if (tvb->riter < 0)
- { r.n = 0; loopfn = benchloop_outer; }
- else
- { r.n = &TVEC_REG(tv, in, tvb->riter)->v.u; loopfn = benchloop_inner; }
-
- tv->output->ops->bbench(tv->output);
- if (bench_measure(&tm, b, loopfn, &r))
- { tv->output->ops->ebench(tv->output, 0); goto end_2; }
- tv->output->ops->ebench(tv->output, &tm);
-
-end_2:
- if (tvb->teardown) tvb->teardown(r.ctx);
-end_1:
- if (r.ctx) xfree(r.ctx);
-end_0:
- return (0);
-}
-