source: mainline/uspace/app/tmon/burst_tests.c@ 2b3dd78

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2b3dd78 was 2b3dd78, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge remote-tracking branch 'upstream/master' into forwardport

change tmon includes because of new stdlib

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