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
Line 
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
34 * USB burst tests.
35 */
36
37#include <stdio.h>
38#include <errno.h>
39#include <str.h>
40#include <str_error.h>
41#include <getopt.h>
42#include <usbdiag_iface.h>
43#include <macros.h>
44#include "commands.h"
45#include "tf.h"
46
47#define NAME "tmon"
48#define INDENT " "
49
50/** Generic burst test parameters. */
51typedef struct tmon_burst_test_params {
52 /** Inherited base. */
53 tmon_test_params_t base;
54 /** The count of reads/writes to perform. */
55 uint32_t cycles;
56 /** Size of single read/write. */
57 size_t size;
58} tmon_burst_test_params_t;
59
60/** Static array of long options, from which test parameters are parsed. */
61static struct option long_options[] = {
62 {"cycles", required_argument, NULL, 'n'},
63 {"size", required_argument, NULL, 's'},
64 {0, 0, NULL, 0}
65};
66
67/** String of short options, from which test parameters are parsed. */
68static const char *short_options = "n:s:";
69
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 */
77static int read_params(int argc, char *argv[], tmon_test_params_t **params)
78{
79 int rc;
80 tmon_burst_test_params_t *p = (tmon_burst_test_params_t *) malloc(sizeof(tmon_burst_test_params_t));
81 if (!p)
82 return ENOMEM;
83
84 // Default values.
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 }
111
112 *params = (tmon_test_params_t *) p;
113 return EOK;
114
115err_malloc:
116 free(p);
117 *params = NULL;
118 return rc;
119}
120
121/** Unit of quantity used for pretty formatting. */
122typedef struct tmon_unit {
123 /** Prefix letter, which is printed before the actual unit. */
124 char prefix;
125 /** Factor of the unit. */
126 uint64_t factor;
127} tmon_unit_t;
128
129/** Static array of units with decreasing factors. */
130static const tmon_unit_t units[] = {
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 }
137};
138
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 */
145static char * format_size(double size, const char *fmt)
146{
147 // Figure out the "tightest" unit.
148 unsigned i;
149 for (i = 0; i < ARRAY_SIZE(units); ++i) {
150 if (units[i].factor <= size)
151 break;
152 }
153
154 char prefix[] = { '\0', '\0' };
155 double factor = 1;
156
157 if (i < ARRAY_SIZE(units)) {
158 prefix[0] = units[i].prefix;
159 factor = units[i].factor;
160 }
161
162 // Format the size.
163 const double div_size = size / factor;
164
165 char *out = NULL;
166 asprintf(&out, fmt, div_size, prefix);
167
168 return out;
169}
170
171/** Print burst test parameters.
172 * @param[in] params Test parameters to print.
173 */
174static void print_params(const tmon_burst_test_params_t *params)
175{
176 printf(INDENT "Number of cycles: %d\n", params->cycles);
177
178 char *str_size = format_size(params->size, "%.3f %sB");
179 printf(INDENT "Data size: %s\n", str_size);
180 free(str_size);
181}
182
183/** Print burst test results.
184 * @param[in] params Test parameters.
185 * @param[in] duration Duration of the burst test.
186 */
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;
192 printf(INDENT "Duration per cycle: %.3f ms\n", dur_per_cycle);
193
194 const size_t total_size = params->size * params->cycles;
195 char *str_total_size = format_size(total_size, "%.3f %sB");
196 printf(INDENT "Total size: %s\n", str_total_size);
197 free(str_total_size);
198
199 const double speed = 1000.0 * (double) total_size / (double) duration;
200 char *str_speed = format_size(speed, "%.3f %sB/s");
201 printf(INDENT "Average speed: %s\n", str_speed);
202 free(str_speed);
203}
204
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 */
211static int run_intr_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
212{
213 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
214 puts("Reading data from interrupt endpoint.\n");
215 print_params(params);
216
217 usbdiag_dur_t duration;
218 int rc = usbdiag_burst_intr_in(exch, params->cycles, params->size, &duration);
219 if (rc) {
220 printf(NAME ": Test failed with error: %s\n", str_error(rc));
221 return 1;
222 }
223
224 puts("Test succeeded.\n");
225 print_results(params, duration);
226 return 0;
227}
228
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 */
235static int run_intr_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
236{
237 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
238 puts("Writing data to interrupt endpoint.\n");
239 print_params(params);
240
241 usbdiag_dur_t duration;
242 int rc = usbdiag_burst_intr_out(exch, params->cycles, params->size, &duration);
243 if (rc) {
244 printf(NAME ": Test failed with error: %s\n", str_error(rc));
245 return 1;
246 }
247
248 puts("Test succeeded.\n");
249 print_results(params, duration);
250 return 0;
251}
252
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 */
259static int run_bulk_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
260{
261 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
262 puts("Reading data from bulk endpoint.\n");
263 print_params(params);
264
265 usbdiag_dur_t duration;
266 int rc = usbdiag_burst_bulk_in(exch, params->cycles, params->size, &duration);
267 if (rc) {
268 printf(NAME ": Test failed with error: %s\n", str_error(rc));
269 return 1;
270 }
271
272 puts("Test succeeded.\n");
273 print_results(params, duration);
274 return 0;
275}
276
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 */
283static int run_bulk_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
284{
285 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
286 puts("Writing data to bulk endpoint.\n");
287 print_params(params);
288
289 usbdiag_dur_t duration;
290 int rc = usbdiag_burst_bulk_out(exch, params->cycles, params->size, &duration);
291 if (rc) {
292 printf(NAME ": Test failed with error: %s\n", str_error(rc));
293 return 1;
294 }
295
296 puts("Test succeeded.\n");
297 print_results(params, duration);
298 return 0;
299}
300
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 */
307static int run_isoch_in(async_exch_t *exch, const tmon_test_params_t *generic_params)
308{
309 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
310 puts("Reading data from isochronous endpoint.\n");
311 print_params(params);
312
313 usbdiag_dur_t duration;
314 int rc = usbdiag_burst_isoch_in(exch, params->cycles, params->size, &duration);
315 if (rc) {
316 printf(NAME ": Test failed with error: %s\n", str_error(rc));
317 return 1;
318 }
319
320 puts("Test succeeded.\n");
321 print_results(params, duration);
322 return 0;
323}
324
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 */
331static int run_isoch_out(async_exch_t *exch, const tmon_test_params_t *generic_params)
332{
333 const tmon_burst_test_params_t *params = (tmon_burst_test_params_t *) generic_params;
334 puts("Writing data to isochronous endpoint.\n");
335 print_params(params);
336
337 usbdiag_dur_t duration;
338 int rc = usbdiag_burst_isoch_out(exch, params->cycles, params->size, &duration);
339 if (rc) {
340 printf(NAME ": Test failed with error: %s\n", str_error(rc));
341 return 1;
342 }
343
344 puts("Test succeeded.\n");
345 print_results(params, duration);
346 return 0;
347}
348
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 */
355int tmon_burst_intr_in(int argc, char *argv[])
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
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 */
371int tmon_burst_intr_out(int argc, char *argv[])
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
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 */
387int tmon_burst_bulk_in(int argc, char *argv[])
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
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 */
403int tmon_burst_bulk_out(int argc, char *argv[])
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
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 */
419int tmon_burst_isoch_in(int argc, char *argv[])
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
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 */
435int tmon_burst_isoch_out(int argc, char *argv[])
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
445/** @}
446 */
Note: See TracBrowser for help on using the repository browser.