source: mainline/uspace/app/tmon/burst_tests.c@ f4b83cc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f4b83cc was f4b83cc, checked in by Petr Manek <petr.manek@…>, 8 years ago

tmon: change format string

  • Property mode set to 100644
File size: 12.4 KB
RevLine 
[dd36558]1/*
2 * Copyright (c) 2017 Petr Manek
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup tmon
30 * @{
31 */
32/**
33 * @file
[2986763]34 * USB burst tests.
[dd36558]35 */
36
37#include <stdio.h>
38#include <errno.h>
39#include <str_error.h>
[119a794]40#include <getopt.h>
[dd36558]41#include <usbdiag_iface.h>
[59958992]42#include <macros.h>
[dd36558]43#include "commands.h"
[2986763]44#include "tf.h"
[dd36558]45
[b10a434]46#define NAME "tmon"
47#define INDENT " "
[dd36558]48
[8e16454]49/** Generic burst test parameters. */
[2986763]50typedef struct tmon_burst_test_params {
[8e16454]51 /** Inherited base. */
52 tmon_test_params_t base;
53 /** The count of reads/writes to perform. */
[119a794]54 uint32_t cycles;
[8e16454]55 /** Size of single read/write. */
[dd36558]56 size_t size;
[2986763]57} tmon_burst_test_params_t;
[dd36558]58
[8e16454]59/** Static array of long options, from which test parameters are parsed. */
[119a794]60static struct option long_options[] = {
61 {"cycles", required_argument, NULL, 'n'},
62 {"size", required_argument, NULL, 's'},
63 {0, 0, NULL, 0}
64};
65
[8e16454]66/** String of short options, from which test parameters are parsed. */
[119a794]67static const char *short_options = "n:s:";
68
[8e16454]69/** Common option parser for all burst tests.
70 * @param[in] argc Number of arguments.
71 * @param[in] argv Argument values. Must point to exactly `argc` strings.
72 * @param[out] params Parsed test parameters (if successful).
73 *
74 * @return EOK if successful (in such case caller becomes the owner of `params`).
75 */
[dd36558]76static int read_params(int argc, char *argv[], tmon_test_params_t **params)
77{
[119a794]78 int rc;
[2986763]79 tmon_burst_test_params_t *p = (tmon_burst_test_params_t *) malloc(sizeof(tmon_burst_test_params_t));
[dd36558]80 if (!p)
81 return ENOMEM;
82
83 // Default values.
[119a794]84 p->cycles = 256;
85 p->size = 1024;
86
87 // Parse other than default values.
88 int c;
89 for (c = 0, optreset = 1, optind = 0; c != -1;) {
90 c = getopt_long(argc, argv, short_options, long_options, NULL);
91 switch (c) {
92 case -1:
93 break;
94 case 'n':
95 if (!optarg || str_uint32_t(optarg, NULL, 10, false, &p->cycles) != EOK) {
96 puts(NAME ": Invalid number of cycles.\n");
97 rc = EINVAL;
98 goto err_malloc;
99 }
100 break;
101 case 's':
102 if (!optarg || str_size_t(optarg, NULL, 10, false, &p->size) != EOK) {
103 puts(NAME ": Invalid data size.\n");
104 rc = EINVAL;
105 goto err_malloc;
106 }
107 break;
108 }
109 }
[dd36558]110
111 *params = (tmon_test_params_t *) p;
112 return EOK;
[119a794]113
114err_malloc:
115 free(p);
116 *params = NULL;
117 return rc;
[dd36558]118}
119
[8e16454]120/** Unit of quantity used for pretty formatting. */
[acb9aa7]121typedef struct tmon_unit {
[8e16454]122 /** Prefix letter, which is printed before the actual unit. */
[acb9aa7]123 char prefix;
[8e16454]124 /** Factor of the unit. */
[acb9aa7]125 uint64_t factor;
126} tmon_unit_t;
127
[8e16454]128/** Static array of units with decreasing factors. */
[acb9aa7]129static const tmon_unit_t units[] = {
130 { .prefix = 'E', .factor = 1ul << 60 },
131 { .prefix = 'P', .factor = 1ul << 50 },
132 { .prefix = 'T', .factor = 1ul << 40 },
133 { .prefix = 'G', .factor = 1ul << 30 },
134 { .prefix = 'M', .factor = 1ul << 20 },
[59958992]135 { .prefix = 'k', .factor = 1ul << 10 }
[acb9aa7]136};
137
[8e16454]138/** Format size in bytes for human reading.
139 * @param[in] size The size to format.
140 * @param[in] fmt Format string. Must include one double and char.
141 *
142 * @return Heap-allocated string if successful (caller becomes its owner), NULL otherwise.
143 */
[acb9aa7]144static char * format_size(double size, const char *fmt)
145{
[8e16454]146 // Figure out the "tightest" unit.
[59958992]147 unsigned i;
148 for (i = 0; i < ARRAY_SIZE(units); ++i) {
[acb9aa7]149 if (units[i].factor <= size)
150 break;
151 }
152
[59958992]153 char prefix[] = { '\0', '\0' };
[acb9aa7]154 double factor = 1;
155
[59958992]156 if (i < ARRAY_SIZE(units)) {
[acb9aa7]157 prefix[0] = units[i].prefix;
158 factor = units[i].factor;
159 }
160
[8e16454]161 // Format the size.
[acb9aa7]162 const double div_size = size / factor;
[f4b83cc]163
[acb9aa7]164 char *out = NULL;
165 asprintf(&out, fmt, div_size, prefix);
166
167 return out;
168}
169
[8e16454]170/** Print burst test parameters.
171 * @param[in] params Test parameters to print.
172 */
[b10a434]173static void print_params(const tmon_burst_test_params_t *params)
174{
175 printf(INDENT "Number of cycles: %d\n", params->cycles);
[acb9aa7]176
[f4b83cc]177 char *str_size = format_size(params->size, "%.3f %sB");
[acb9aa7]178 printf(INDENT "Data size: %s\n", str_size);
179 free(str_size);
[b10a434]180}
181
[8e16454]182/** Print burst test results.
183 * @param[in] params Test parameters.
184 * @param[in] duration Duration of the burst test.
185 */
[b10a434]186static void print_results(const tmon_burst_test_params_t *params, usbdiag_dur_t duration)
187{
188 printf(INDENT "Total duration: %ld ms\n", duration);
189
190 const double dur_per_cycle = (double) duration / (double) params->cycles;
[f4b83cc]191 printf(INDENT "Duration per cycle: %.3f ms\n", dur_per_cycle);
[b10a434]192
[e23b87b]193 const size_t total_size = params->size * params->cycles;
[f4b83cc]194 char *str_total_size = format_size(total_size, "%.3f %sB");
[acb9aa7]195 printf(INDENT "Total size: %s\n", str_total_size);
196 free(str_total_size);
[e23b87b]197
198 const double speed = 1000.0 * (double) total_size / (double) duration;
[f4b83cc]199 char *str_speed = format_size(speed, "%.3f %sB/s");
[acb9aa7]200 printf(INDENT "Average speed: %s\n", str_speed);
201 free(str_speed);
[b10a434]202}
203
[8e16454]204/** Run "interrupt in" burst test.
205 * @param[in] exch Open async exchange with the diagnostic device.
206 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
207 *
208 * @return Exit code
209 */
[dd36558]210static int run_intr_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
211{
[2986763]212 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]213 puts("Reading data from interrupt endpoint.\n");
214 print_params(params);
[dd36558]215
[b10a434]216 usbdiag_dur_t duration;
217 int rc = usbdiag_burst_intr_in(exch, params->cycles, params->size, &duration);
[dd36558]218 if (rc) {
[b10a434]219 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[dd36558]220 return 1;
221 }
222
[b10a434]223 puts("Test succeeded.\n");
224 print_results(params, duration);
[dd36558]225 return 0;
226}
227
[8e16454]228/** Run "interrupt out" burst test.
229 * @param[in] exch Open async exchange with the diagnostic device.
230 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
231 *
232 * @return Exit code
233 */
[dd36558]234static int run_intr_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
235{
[2986763]236 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]237 puts("Writing data to interrupt endpoint.\n");
238 print_params(params);
[dd36558]239
[b10a434]240 usbdiag_dur_t duration;
241 int rc = usbdiag_burst_intr_out(exch, params->cycles, params->size, &duration);
[dd36558]242 if (rc) {
[b10a434]243 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[dd36558]244 return 1;
245 }
246
[b10a434]247 puts("Test succeeded.\n");
248 print_results(params, duration);
[dd36558]249 return 0;
250}
251
[8e16454]252/** Run "bulk in" burst test.
253 * @param[in] exch Open async exchange with the diagnostic device.
254 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
255 *
256 * @return Exit code
257 */
[dd36558]258static int run_bulk_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
259{
[2986763]260 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]261 puts("Reading data from bulk endpoint.\n");
262 print_params(params);
[dd36558]263
[b10a434]264 usbdiag_dur_t duration;
265 int rc = usbdiag_burst_bulk_in(exch, params->cycles, params->size, &duration);
[dd36558]266 if (rc) {
[b10a434]267 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[dd36558]268 return 1;
269 }
270
[b10a434]271 puts("Test succeeded.\n");
272 print_results(params, duration);
[dd36558]273 return 0;
274}
275
[8e16454]276/** Run "bulk out" burst test.
277 * @param[in] exch Open async exchange with the diagnostic device.
278 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
279 *
280 * @return Exit code
281 */
[dd36558]282static int run_bulk_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
283{
[2986763]284 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]285 puts("Writing data to bulk endpoint.\n");
286 print_params(params);
[dd36558]287
[b10a434]288 usbdiag_dur_t duration;
289 int rc = usbdiag_burst_bulk_out(exch, params->cycles, params->size, &duration);
[dd36558]290 if (rc) {
[b10a434]291 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[dd36558]292 return 1;
293 }
294
[b10a434]295 puts("Test succeeded.\n");
296 print_results(params, duration);
[dd36558]297 return 0;
298}
299
[8e16454]300/** Run "isochronous in" burst test.
301 * @param[in] exch Open async exchange with the diagnostic device.
302 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
303 *
304 * @return Exit code
305 */
[ff16da5f]306static int run_isoch_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
307{
[2986763]308 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]309 puts("Reading data from isochronous endpoint.\n");
310 print_params(params);
[ff16da5f]311
[b10a434]312 usbdiag_dur_t duration;
313 int rc = usbdiag_burst_isoch_in(exch, params->cycles, params->size, &duration);
[ff16da5f]314 if (rc) {
[b10a434]315 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[ff16da5f]316 return 1;
317 }
318
[b10a434]319 puts("Test succeeded.\n");
320 print_results(params, duration);
[ff16da5f]321 return 0;
322}
323
[8e16454]324/** Run "isochronous out" burst test.
325 * @param[in] exch Open async exchange with the diagnostic device.
326 * @param[in] generic_params Test parameters. Must point to 'tmon_burst_test_params_t'.
327 *
328 * @return Exit code
329 */
[ff16da5f]330static int run_isoch_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
331{
[2986763]332 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
[b10a434]333 puts("Writing data to isochronous endpoint.\n");
334 print_params(params);
[ff16da5f]335
[b10a434]336 usbdiag_dur_t duration;
337 int rc = usbdiag_burst_isoch_out(exch, params->cycles, params->size, &duration);
[ff16da5f]338 if (rc) {
[b10a434]339 printf(NAME ": Test failed with error: %s\n", str_error(rc));
[ff16da5f]340 return 1;
341 }
342
[b10a434]343 puts("Test succeeded.\n");
344 print_results(params, duration);
[ff16da5f]345 return 0;
346}
347
[8e16454]348/** Interrupt in burst test command handler.
349 * @param[in] argc Number of arguments.
350 * @param[in] argv Argument values. Must point to exactly `argc` strings.
351 *
352 * @return Exit code
353 */
[2986763]354int tmon_burst_intr_in(int argc, char *argv[])
[dd36558]355{
356 static const tmon_test_ops_t ops = {
357 .run = run_intr_in,
358 .read_params = read_params
359 };
360
361 return tmon_test_main(argc, argv, &ops);
362}
363
[8e16454]364/** Interrupt out burst test command handler.
365 * @param[in] argc Number of arguments.
366 * @param[in] argv Argument values. Must point to exactly `argc` strings.
367 *
368 * @return Exit code
369 */
[2986763]370int tmon_burst_intr_out(int argc, char *argv[])
[dd36558]371{
372 static const tmon_test_ops_t ops = {
373 .run = run_intr_out,
374 .read_params = read_params
375 };
376
377 return tmon_test_main(argc, argv, &ops);
378}
379
[8e16454]380/** Interrupt bulk burst test command handler.
381 * @param[in] argc Number of arguments.
382 * @param[in] argv Argument values. Must point to exactly `argc` strings.
383 *
384 * @return Exit code
385 */
[2986763]386int tmon_burst_bulk_in(int argc, char *argv[])
[dd36558]387{
388 static const tmon_test_ops_t ops = {
389 .run = run_bulk_in,
390 .read_params = read_params
391 };
392
393 return tmon_test_main(argc, argv, &ops);
394}
395
[8e16454]396/** Bulk out burst test command handler.
397 * @param[in] argc Number of arguments.
398 * @param[in] argv Argument values. Must point to exactly `argc` strings.
399 *
400 * @return Exit code
401 */
[2986763]402int tmon_burst_bulk_out(int argc, char *argv[])
[dd36558]403{
404 static const tmon_test_ops_t ops = {
405 .run = run_bulk_out,
406 .read_params = read_params
407 };
408
409 return tmon_test_main(argc, argv, &ops);
410}
411
[8e16454]412/** Isochronous in burst test command handler.
413 * @param[in] argc Number of arguments.
414 * @param[in] argv Argument values. Must point to exactly `argc` strings.
415 *
416 * @return Exit code
417 */
[2986763]418int tmon_burst_isoch_in(int argc, char *argv[])
[ff16da5f]419{
420 static const tmon_test_ops_t ops = {
421 .run = run_isoch_in,
422 .read_params = read_params
423 };
424
425 return tmon_test_main(argc, argv, &ops);
426}
427
[8e16454]428/** Isochronous out burst test command handler.
429 * @param[in] argc Number of arguments.
430 * @param[in] argv Argument values. Must point to exactly `argc` strings.
431 *
432 * @return Exit code
433 */
[2986763]434int tmon_burst_isoch_out(int argc, char *argv[])
[ff16da5f]435{
436 static const tmon_test_ops_t ops = {
437 .run = run_isoch_out,
438 .read_params = read_params
439 };
440
441 return tmon_test_main(argc, argv, &ops);
442}
443
[dd36558]444/** @}
445 */
Note: See TracBrowser for help on using the repository browser.