1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * builtin-bench.c
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * General benchmarking subsystem provided by perf
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Copyright (C) 2009, Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/*
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Available subsystem list:
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *  sched ... scheduler and IPC mechanism
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *  mem   ... memory access performance
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "perf.h"
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/util.h"
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/parse-options.h"
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "builtin.h"
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "bench/bench.h"
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h>
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct bench_suite {
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *name;
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *summary;
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int (*fn)(int, const char **, const char *);
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						\
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* sentinel: easy for help */
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define suite_all { "all", "Test all benchmark suites", NULL }
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#ifdef LIBNUMA_SUPPORT
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct bench_suite numa_suites[] = {
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "mem",
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "Benchmark for NUMA workloads",
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  bench_numa },
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	suite_all,
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ NULL,
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL,
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL                  }
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct bench_suite sched_suites[] = {
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "messaging",
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "Benchmark for scheduler and IPC mechanisms",
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  bench_sched_messaging },
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "pipe",
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "Flood of communication over pipe() between two processes",
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  bench_sched_pipe      },
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	suite_all,
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ NULL,
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL,
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL                  }
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct bench_suite mem_suites[] = {
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "memcpy",
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "Simple memory copy in various ways",
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  bench_mem_memcpy },
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "memset",
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "Simple memory set in various ways",
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  bench_mem_memset },
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	suite_all,
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ NULL,
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL,
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL             }
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct bench_subsys {
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *name;
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *summary;
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct bench_suite *suites;
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct bench_subsys subsystems[] = {
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#ifdef LIBNUMA_SUPPORT
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "numa",
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "NUMA scheduling and MM behavior",
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  numa_suites },
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "sched",
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "scheduler and IPC mechanism",
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  sched_suites },
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "mem",
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "memory access performance",
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  mem_suites },
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ "all",		/* sentinel: easy for help */
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  "all benchmark subsystem",
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL },
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	{ NULL,
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL,
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	  NULL       }
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void dump_suites(int subsys_index)
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("# List of available suites for %s...\n\n",
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	       subsystems[subsys_index].name);
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; subsystems[subsys_index].suites[i].name; i++)
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("%14s: %s\n",
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       subsystems[subsys_index].suites[i].name,
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       subsystems[subsys_index].suites[i].summary);
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("\n");
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return;
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const char *bench_format_str;
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint bench_format = BENCH_FORMAT_DEFAULT;
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const struct option bench_options[] = {
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_STRING('f', "format", &bench_format_str, "default",
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    "Specify format style"),
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	OPT_END()
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const char * const bench_usage[] = {
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	"perf bench [<common options>] <subsystem> <suite> [<options>]",
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	NULL
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void print_usage(void)
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("Usage: \n");
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; bench_usage[i]; i++)
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("\t%s\n", bench_usage[i]);
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("\n");
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("# List of available subsystems...\n\n");
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; subsystems[i].name; i++)
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("%14s: %s\n",
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       subsystems[i].name, subsystems[i].summary);
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("\n");
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int bench_str2int(const char *str)
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!str)
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return BENCH_FORMAT_DEFAULT;
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!strcmp(str, BENCH_FORMAT_DEFAULT_STR))
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return BENCH_FORMAT_DEFAULT;
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else if (!strcmp(str, BENCH_FORMAT_SIMPLE_STR))
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return BENCH_FORMAT_SIMPLE;
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return BENCH_FORMAT_UNKNOWN;
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void all_suite(struct bench_subsys *subsys)	  /* FROM HERE */
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *argv[2];
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct bench_suite *suites = subsys->suites;
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	argv[1] = NULL;
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * TODO:
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * preparing preset parameters for
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * embedded, ordinary PC, HPC, etc...
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * will be helpful
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; suites[i].fn; i++) {
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("# Running %s/%s benchmark...\n",
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       subsys->name,
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       suites[i].name);
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fflush(stdout);
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		argv[1] = suites[i].name;
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		suites[i].fn(1, argv, NULL);
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("\n");
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void all_subsystem(void)
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; subsystems[i].suites; i++)
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		all_suite(&subsystems[i]);
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint cmd_bench(int argc, const char **argv, const char *prefix __maybe_unused)
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i, j, status = 0;
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (argc < 2) {
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* No subsystem specified. */
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		print_usage();
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto end;
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	argc = parse_options(argc, argv, bench_options, bench_usage,
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			     PARSE_OPT_STOP_AT_NON_OPTION);
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bench_format = bench_str2int(bench_format_str);
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (bench_format == BENCH_FORMAT_UNKNOWN) {
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("Unknown format descriptor:%s\n", bench_format_str);
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto end;
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (argc < 1) {
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		print_usage();
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto end;
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!strcmp(argv[0], "all")) {
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		all_subsystem();
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto end;
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; subsystems[i].name; i++) {
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (strcmp(subsystems[i].name, argv[0]))
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			continue;
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (argc < 2) {
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			/* No suite specified. */
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dump_suites(i);
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto end;
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!strcmp(argv[1], "all")) {
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			all_suite(&subsystems[i]);
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto end;
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (j = 0; subsystems[i].suites[j].name; j++) {
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (strcmp(subsystems[i].suites[j].name, argv[1]))
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (bench_format == BENCH_FORMAT_DEFAULT)
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				printf("# Running %s/%s benchmark...\n",
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       subsystems[i].name,
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				       subsystems[i].suites[j].name);
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fflush(stdout);
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			status = subsystems[i].suites[j].fn(argc - 1,
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng							    argv + 1, prefix);
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto end;
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			dump_suites(i);
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto end;
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		printf("Unknown suite:%s for %s\n", argv[1], argv[0]);
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		status = 1;
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto end;
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	printf("Unknown subsystem:%s\n", argv[0]);
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	status = 1;
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengend:
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return status;
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
268