* [PATCH rt-tests v5 00/13] Generate machine-readable output
@ 2021-02-10 17:51 Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param Daniel Wagner
` (12 more replies)
0 siblings, 13 replies; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
v5:
- add 'realtime' to common header
- add timestamp to common header
- oslat add quiet option
- oslat fix JSON formatting
- rt-migrate fix JSON formatting
v4:
- rebased on top of '[rt-tests v3 00/16] rt-numa.h cleanups' series
- dropped applied patches
- dropped RFC label
v3:
- A number of bug fixes added at the beginning of
the series.
- Add --output option to all tests which have a
numeric results, not just failed/passed
v2:
- Moved the common JSON parts into rt-util.[ch]
- Add --output option to signaltest
The current output of cyclictest is optimized for humans to read. This
is all good when working directly with the tools. But for CI
integration it's a bit of pain. Furthermore, not all rt-tests use the
same output format.
By using some easy to parse existing machine-readable format we can use
standard libraries to parse the data. For example in jitterdebug there
is a short Python program[1] to visualize either the histogram[2] or
all samples[3].
The implementation for JSON output for this is very simple. The last
patch adds a version of jitterdebugs's JSON output, which looks like
{
"file_version": 1,
"version:": "cyclictest V 1.90",
"num_threads": 2,
"resolution_in_ns": 0,
"cmdline:": "./cyclictest --affinity=1-2 --duration=1s --output=dump.json -h 1000 -p 80",
"sysinfo": {
"sysname": "Linux",
"nodename": "beryllium",
"release": "5.9.14-1-default",
"version": "#1 SMP Sat Dec 12 06:57:32 UTC 2020 (c648a46)",
"machine": "x86_64"
},
"thread": {
"0": {
"histogram": {
"0": 16,
"1": 853,
"2": 80,
"3": 50,
"4": 1
},
"cycles": 1000,
"min": 0,
"max": 4,
"avg": 1.17,
"cpu": 1,
"node": 0
},
"1": {
"histogram": {
"0": 14,
"1": 833,
"2": 93,
"3": 56,
"4": 4
},
"cycles": 1000,
"min": 0,
"max": 4,
"avg": 1.20,
"cpu": 2,
"node": 0
}
}
}
It's just a rough version. I didn't try to make it generic for the
other rt-tests or make it as plugin as John was suggesting. I'd think
we could make this feature as compile option, if you want to keep the
program small. Obviously, we could also make the terminal output a
compile option, to keep it small.
Anyway, what do you think about it?
Thanks,
Daniel
Daniel Wagner (13):
cyclictest: Move thread data to struct thread_param
signaltest: Move thread data to struct thread_param
rt-utils: Add JSON common header output helper
cyclictest: Add JSON output feature
signaltest: Add JSON output feature
cyclicdeadline: Add JSON output feature
pmqtest: Add JSON output feature
ptsematest: Add JSON output feature
sigwaittest: Add JSON output feature
svsematest: Add JSON output feature
oslat: Add JSON output feature
rt-migrate-test: Add JSON output feature
oslat: Add quiet command line option
src/cyclictest/cyclictest.c | 80 ++++++++++---
src/include/rt-utils.h | 4 +
src/lib/rt-utils.c | 96 ++++++++++++++++
src/oslat/oslat.c | 118 ++++++++++++++++----
src/pmqtest/pmqtest.c | 137 +++++++++++++++++++----
src/ptsematest/ptsematest.c | 120 ++++++++++++++++----
src/rt-migrate-test/rt-migrate-test.c | 120 ++++++++++++++++----
src/sched_deadline/cyclicdeadline.c | 72 +++++++++---
src/signaltest/signaltest.c | 154 +++++++++++++++++++-------
src/sigwaittest/sigwaittest.c | 117 ++++++++++++++++---
src/svsematest/svsematest.c | 124 +++++++++++++++++----
11 files changed, 946 insertions(+), 196 deletions(-)
--
2.30.0
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 02/13] signaltest: " Daniel Wagner
` (11 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Group thread realated data such as thread ID to struct thread_param.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/cyclictest/cyclictest.c | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index c4b2369bee6b..7c45732c1553 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -113,6 +113,9 @@ static char *policyname(int policy);
/* Struct to transfer parameters to the thread */
struct thread_param {
+ pthread_t thread;
+ int threadstarted;
+ int tid;
int prio;
int policy;
int mode;
@@ -141,9 +144,6 @@ struct thread_stat {
long *smis;
long *hist_array;
long *outliers;
- pthread_t thread;
- int threadstarted;
- int tid;
long reduce;
long redmax;
long cycleofmax;
@@ -530,7 +530,7 @@ static void *timerthread(void *param)
interval.tv_sec = par->interval / USEC_PER_SEC;
interval.tv_nsec = (par->interval % USEC_PER_SEC) * 1000;
- stat->tid = gettid();
+ par->tid = gettid();
sigemptyset(&sigset);
sigaddset(&sigset, par->signal);
@@ -539,7 +539,7 @@ static void *timerthread(void *param)
if (par->mode == MODE_CYCLIC) {
sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
sigev.sigev_signo = par->signal;
- sigev.sigev_notify_thread_id = stat->tid;
+ sigev.sigev_notify_thread_id = par->tid;
timer_create(par->clock, &sigev, &timer);
tspec.it_interval = interval;
}
@@ -613,7 +613,7 @@ static void *timerthread(void *param)
setitimer(ITIMER_REAL, &itimer, NULL);
}
- stat->threadstarted++;
+ par->threadstarted++;
while (!shutdown) {
@@ -719,7 +719,7 @@ static void *timerthread(void *param)
shutdown++;
pthread_mutex_lock(&break_thread_id_lock);
if (break_thread_id == 0) {
- break_thread_id = stat->tid;
+ break_thread_id = par->tid;
tracemark("hit latency threshold (%llu > %d)",
(unsigned long long) diff, tracelimit);
break_thread_value = diff;
@@ -795,7 +795,7 @@ static void *timerthread(void *param)
/* switch to normal */
schedp.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schedp);
- stat->threadstarted = -1;
+ par->threadstarted = -1;
return NULL;
}
@@ -1293,7 +1293,7 @@ static void print_tids(struct thread_param *par[], int nthreads)
printf("# Thread Ids:");
for (i = 0; i < nthreads; i++)
- printf(" %05d", par[i]->stats->tid);
+ printf(" %05d", par[i]->tid);
printf("\n");
}
@@ -1407,7 +1407,7 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
"Min:%7ld Act:%5ld Avg:%5ld Max:%8ld";
- fprintf(fp, fmt, index, stat->tid, par->prio,
+ fprintf(fp, fmt, index, par->tid, par->prio,
par->interval, stat->cycles, stat->min,
stat->act, stat->cycles ?
(long)(stat->avg/stat->cycles) : 0, stat->max);
@@ -1463,7 +1463,7 @@ static void rstat_print_stat(struct thread_param *par, int index, int verbose, i
fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
"Min:%7ld Act:%5ld Avg:%5ld Max:%8ld";
- dprintf(fd, fmt, index, stat->tid, par->prio,
+ dprintf(fd, fmt, index, par->tid, par->prio,
par->interval, stat->cycles, stat->min,
stat->act, stat->cycles ?
(long)(stat->avg/stat->cycles) : 0, stat->max);
@@ -1966,9 +1966,9 @@ int main(int argc, char **argv)
stat->min = 1000000;
stat->max = 0;
stat->avg = 0.0;
- stat->threadstarted = 1;
stat->smi_count = 0;
- status = pthread_create(&stat->thread, &attr, timerthread, par);
+ par->threadstarted = 1;
+ status = pthread_create(&par->thread, &attr, timerthread, par);
if (status)
fatal("failed to create thread %d: %s\n", i, strerror(status));
@@ -2038,10 +2038,10 @@ int main(int argc, char **argv)
if (quiet)
quiet = 2;
for (i = 0; i < num_threads; i++) {
- if (statistics[i]->threadstarted > 0)
- pthread_kill(statistics[i]->thread, SIGTERM);
- if (statistics[i]->threadstarted) {
- pthread_join(statistics[i]->thread, NULL);
+ if (parameters[i]->threadstarted > 0)
+ pthread_kill(parameters[i]->thread, SIGTERM);
+ if (parameters[i]->threadstarted) {
+ pthread_join(parameters[i]->thread, NULL);
if (quiet && !histogram)
print_stat(stdout, parameters[i], i, 0, 0);
}
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 02/13] signaltest: Move thread data to struct thread_param
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper Daniel Wagner
` (10 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Group thread realated data such as thread ID to struct thread_param.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/signaltest/signaltest.c | 44 ++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
index c34bc994d886..dd5633d5fc51 100644
--- a/src/signaltest/signaltest.c
+++ b/src/signaltest/signaltest.c
@@ -40,6 +40,10 @@
/* Struct to transfer parameters to the thread */
struct thread_param {
+ pthread_t thread;
+ pthread_t tothread;
+ int threadstarted;
+ int tid;
int id;
int prio;
int signal;
@@ -47,6 +51,7 @@ struct thread_param {
struct thread_stat *stats;
int bufmsk;
int cpu;
+ int interrupted;
};
/* Struct for statistics */
@@ -58,11 +63,6 @@ struct thread_stat {
long act;
double avg;
long *values;
- pthread_t thread;
- pthread_t tothread;
- int threadstarted;
- int tid;
- int interrupted;
};
static int shutdown;
@@ -86,7 +86,7 @@ void *signalthread(void *param)
pthread_t thread;
cpu_set_t mask;
- stat->tid = gettid();
+ par->tid = gettid();
if (par->cpu != -1) {
CPU_ZERO(&mask);
@@ -105,7 +105,7 @@ void *signalthread(void *param)
schedp.sched_priority = par->prio;
sched_setscheduler(0, policy, &schedp);
- stat->threadstarted++;
+ par->threadstarted++;
clock_gettime(CLOCK_MONOTONIC, &before);
@@ -128,7 +128,7 @@ void *signalthread(void *param)
/* Get current time */
clock_gettime(CLOCK_MONOTONIC, &now);
- pthread_kill(stat->tothread, SIGUSR1);
+ pthread_kill(par->tothread, SIGUSR1);
/* Skip the first cycle */
if (first) {
@@ -148,7 +148,7 @@ void *signalthread(void *param)
if (!stopped && tracelimit && !par->id && (diff > tracelimit)) {
stat->act = diff;
- stat->interrupted = 1;
+ par->interrupted = 1;
stopped++;
shutdown++;
}
@@ -167,7 +167,7 @@ void *signalthread(void *param)
schedp.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schedp);
- stat->threadstarted = -1;
+ par->threadstarted = -1;
return NULL;
}
@@ -298,7 +298,7 @@ static void print_stat(struct thread_param *par, int index, int verbose)
if (quiet != 1) {
printf("T:%2d (%5d) P:%2d C:%7lu "
"Min:%7ld Act:%5ld Avg:%5ld Max:%8ld\n",
- index, stat->tid, par->prio,
+ index, par->tid, par->prio,
stat->cycles, stat->min, stat->act,
stat->cycles ?
(long)(stat->avg/stat->cycles) : 0, stat->max);
@@ -389,8 +389,8 @@ int main(int argc, char **argv)
stat[i].min = 1000000;
stat[i].max = -1000000;
stat[i].avg = 0.0;
- stat[i].threadstarted = 1;
- status = pthread_create(&stat[i].thread, NULL, signalthread,
+ par[i].threadstarted = 1;
+ status = pthread_create(&par[i].thread, NULL, signalthread,
&par[i]);
if (status)
fatal("failed to create thread %d: %s\n", i,
@@ -401,18 +401,18 @@ int main(int argc, char **argv)
int allstarted = 1;
for (i = 0; i < num_threads; i++) {
- if (stat[i].threadstarted != 2)
+ if (par[i].threadstarted != 2)
allstarted = 0;
}
if (!allstarted)
continue;
for (i = 0; i < num_threads - 1; i++)
- stat[i].tothread = stat[i+1].thread;
- stat[i].tothread = stat[0].thread;
+ par[i].tothread = par[i+1].thread;
+ par[i].tothread = par[0].thread;
break;
}
- pthread_kill(stat[0].thread, signum);
+ pthread_kill(par[0].thread, signum);
while (!shutdown) {
char lavg[256];
@@ -443,12 +443,12 @@ int main(int argc, char **argv)
if (quiet)
quiet = 2;
for (i = 0; i < num_threads; i++) {
- if (stat[i].threadstarted > 0)
- pthread_kill(stat[i].thread, SIGUSR1);
- if (stat[i].interrupted)
+ if (par[i].threadstarted > 0)
+ pthread_kill(par[i].thread, SIGUSR1);
+ if (par[i].interrupted)
printf("Thread %d exceeded trace limit.\n", i);
- if (stat[i].threadstarted) {
- pthread_join(stat[i].thread, NULL);
+ if (par[i].threadstarted) {
+ pthread_join(par[i].thread, NULL);
print_stat(&par[i], i, 0);
}
if (stat[i].values)
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 02/13] signaltest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature Daniel Wagner
` (9 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
rt_write_json writes the common system information header of the
rt-test currently executed.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/include/rt-utils.h | 4 ++
src/lib/rt-utils.c | 96 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+)
diff --git a/src/include/rt-utils.h b/src/include/rt-utils.h
index 39ddbd9eae29..36af92b170df 100644
--- a/src/include/rt-utils.h
+++ b/src/include/rt-utils.h
@@ -80,4 +80,8 @@ static inline int64_t calctime(struct timespec t)
return time;
}
+void rt_write_json(const char *filename, int argc, char *argv[],
+ void (*cb)(FILE *, void *),
+ void *data);
+
#endif /* __RT_UTILS.H */
diff --git a/src/lib/rt-utils.c b/src/lib/rt-utils.c
index 321a11b1172d..00907c573d6a 100644
--- a/src/lib/rt-utils.c
+++ b/src/lib/rt-utils.c
@@ -20,6 +20,9 @@
#include <sys/stat.h>
#include <unistd.h>
#include <sys/syscall.h> /* For SYS_gettid definitions */
+#include <sys/utsname.h>
+#include <time.h>
+#include <sys/time.h>
#include "rt-utils.h"
#include "rt-sched.h"
@@ -482,3 +485,96 @@ void disable_trace_mark(void)
{
close_tracemark_fd();
}
+
+static char *get_cmdline(int argc, char *argv[])
+{
+ char *cmdline;
+ int len, i;
+
+ len = 0;
+ for (i = 0; i < argc; i++)
+ len += strlen(argv[i]) + 1;
+
+ cmdline = malloc(len);
+ if (!cmdline)
+ err_exit(ENOMEM, "Could not copy cmdline");
+
+ memset(cmdline, 0, len);
+ for (i = 0; i < argc;) {
+ cmdline = strcat(cmdline, argv[i]);
+ i++;
+ if (i < argc)
+ cmdline = strcat(cmdline, " ");
+ }
+
+ return cmdline;
+}
+
+void rt_write_json(const char *filename, int argc, char *argv[],
+ void (*cb)(FILE *, void *),
+ void *data)
+{
+ unsigned char buf[1];
+ struct utsname uts;
+ struct timeval tv;
+ char tsbuf[64];
+ struct tm *tm;
+ char *cmdline;
+ FILE *f, *s;
+ time_t t;
+ size_t n;
+ int rt = 0;
+
+ if (!filename || !strcmp("-", filename)) {
+ f = stdout;
+ } else {
+ f = fopen(filename, "w");
+ if (!f)
+ err_exit(errno, "Failed to open '%s'\n", filename);
+ }
+
+ cmdline = get_cmdline(argc, argv);
+ if (!cmdline)
+ err_exit(ENOMEM, "get_cmdline()");
+
+
+ gettimeofday(&tv, NULL);
+ t = tv.tv_sec;
+ tm = localtime(&t);
+ /* RFC 2822-compliant date format */
+ strftime(tsbuf, sizeof(tsbuf), "%a, %d %b %Y %T %z", tm);
+
+ s = fopen("/sys/kernel/realtime", "r");
+ if (s) {
+ n = fread(buf, 1, 1, s);
+ if (n == 1 && buf[0] == '1')
+ rt = 1;
+ fclose(s);
+ }
+
+ if (uname(&uts))
+ err_exit(errno, "Could not retrieve system information");
+
+ fprintf(f, "{\n");
+ fprintf(f, " \"file_version\": 1,\n");
+ fprintf(f, " \"cmdline:\": \"%s\",\n", cmdline);
+ fprintf(f, " \"rt_test_version:\": \"%1.2f\",\n", VERSION);
+ fprintf(f, " \"finished\": \"%s\",\n", tsbuf);
+ fprintf(f, " \"sysinfo\": {\n");
+ fprintf(f, " \"sysname\": \"%s\",\n", uts.sysname);
+ fprintf(f, " \"nodename\": \"%s\",\n", uts.nodename);
+ fprintf(f, " \"release\": \"%s\",\n", uts.release);
+ fprintf(f, " \"version\": \"%s\",\n", uts.version);
+ fprintf(f, " \"machine\": \"%s\",\n", uts.machine);
+ fprintf(f, " \"realtime\": %d\n", rt);
+ fprintf(f, " },\n");
+
+ (cb)(f, data);
+
+ fprintf(f, "}\n");
+
+ free(cmdline);
+
+ if (!filename || strcmp("-", filename))
+ fclose(f);
+}
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (2 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 05/13] signaltest: " Daniel Wagner
` (8 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/cyclictest/cyclictest.c | 46 ++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 7c45732c1553..3d0cf3f84b69 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <inttypes.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
@@ -217,6 +218,7 @@ static struct timespec globalt;
static char fifopath[MAX_PATH];
static char histfile[MAX_PATH];
+static char outfile[MAX_PATH];
static struct thread_param **parameters;
static struct thread_stat **statistics;
@@ -838,6 +840,7 @@ static void display_help(int error)
" latency is hit. Useful for low bandwidth.\n"
"-N --nsecs print results in ns instead of us (default us)\n"
"-o RED --oscope=RED oscilloscope mode, reduce verbose output by RED\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --priority=PRIO priority of highest prio thread\n"
" --policy=NAME policy of measurement thread, where NAME may be one\n"
" of: other, normal, batch, idle, fifo or rr.\n"
@@ -945,7 +948,7 @@ enum option_values {
OPT_TRIGGER_NODES, OPT_UNBUFFERED, OPT_NUMA, OPT_VERBOSE,
OPT_DBGCYCLIC, OPT_POLICY, OPT_HELP, OPT_NUMOPTS,
OPT_ALIGNED, OPT_SECALIGNED, OPT_LAPTOP, OPT_SMI,
- OPT_TRACEMARK, OPT_POSIX_TIMERS,
+ OPT_TRACEMARK, OPT_POSIX_TIMERS, OPT_OUTPUT
};
/* Process commandline options */
@@ -979,6 +982,7 @@ static void process_options(int argc, char *argv[])
{"refresh_on_max", no_argument, NULL, OPT_REFRESH },
{"nsecs", no_argument, NULL, OPT_NSECS },
{"oscope", required_argument, NULL, OPT_OSCOPE },
+ {"output", required_argument, NULL, OPT_OUTPUT },
{"priority", required_argument, NULL, OPT_PRIORITY },
{"quiet", no_argument, NULL, OPT_QUIET },
{"priospread", no_argument, NULL, OPT_PRIOSPREAD },
@@ -1073,6 +1077,9 @@ static void process_options(int argc, char *argv[])
case 'o':
case OPT_OSCOPE:
oscope_reduction = atoi(optarg); break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
case 'p':
case OPT_PRIORITY:
priority = atoi(optarg);
@@ -1690,6 +1697,40 @@ static void rstat_setup(void)
return;
}
+static void write_stats(FILE *f, void *data)
+{
+ struct thread_param **par = parameters;
+ unsigned int i, j, comma;
+ struct thread_stat *s;
+
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
+ fprintf(f, " \"resolution_in_ns\": %u,\n", use_nsecs);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ fprintf(f, " \"%u\": {\n", i);
+
+ fprintf(f, " \"histogram\": {");
+ s = par[i]->stats;
+ for (j = 0, comma = 0; j < histogram; j++) {
+ if (s->hist_array[j] == 0)
+ continue;
+ fprintf(f, "%s", comma ? ",\n" : "\n");
+ fprintf(f, " \"%u\": %" PRIu64,j, s->hist_array[j]);
+ comma = 1;
+ }
+ if (comma)
+ fprintf(f, "\n");
+ fprintf(f, " },\n");
+ fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
+ fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
+ fprintf(f, " \"avg\": %.2f,\n", s->avg/s->cycles);
+ fprintf(f, " \"cpu\": %d,\n", par[i]->cpu);
+ fprintf(f, " \"node\": %d\n", par[i]->node);
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
int main(int argc, char **argv)
{
@@ -2035,6 +2076,9 @@ int main(int argc, char **argv)
if (!verbose && !quiet && refresh_on_max)
printf("\033[%dB", num_threads + 2);
+ if (strlen(outfile) != 0)
+ rt_write_json(outfile, argc, argv, write_stats, NULL);
+
if (quiet)
quiet = 2;
for (i = 0; i < num_threads; i++) {
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 05/13] signaltest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (3 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 06/13] cyclicdeadline: " Daniel Wagner
` (7 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/signaltest/signaltest.c | 109 +++++++++++++++++++++++++++++-------
1 file changed, 88 insertions(+), 21 deletions(-)
diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
index dd5633d5fc51..09039b299367 100644
--- a/src/signaltest/signaltest.c
+++ b/src/signaltest/signaltest.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <errno.h>
#include <sched.h>
+#include <inttypes.h>
#include <linux/unistd.h>
@@ -205,6 +206,14 @@ static int verbose;
static int quiet;
static int lockall;
static struct bitmask *affinity_mask = NULL;
+static char outfile[MAX_PATH];
+
+enum option_values {
+ OPT_AFFINITY=1, OPT_BREAKTRACE,
+ OPT_DURATION, OPT_HELP, OPT_LOOPS,
+ OPT_MLOCKALL, OPT_OUTPUT, OPT_PRIORITY,
+ OPT_QUIET, OPT_SMP, OPT_THREADS, OPT_VERBOSE
+};
/* Process commandline options */
static void process_options(int argc, char *argv[])
@@ -216,17 +225,18 @@ static void process_options(int argc, char *argv[])
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"duration", required_argument, NULL, 'D'},
- {"help", no_argument, NULL, 'h'},
- {"loops", required_argument, NULL, 'l'},
- {"mlockall", no_argument, NULL, 'm'},
- {"priority", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'q'},
- {"smp", no_argument, NULL, 'S'},
- {"threads", required_argument, NULL, 't'},
- {"verbose", no_argument, NULL, 'v'},
+ {"affinity", optional_argument, NULL, OPT_AFFINITY},
+ {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"mlockall", no_argument, NULL, OPT_MLOCKALL},
+ {"output", required_argument, NULL, OPT_OUTPUT},
+ {"priority", required_argument, NULL, OPT_PRIORITY},
+ {"quiet", no_argument, NULL, OPT_QUIET},
+ {"smp", no_argument, NULL, OPT_SMP},
+ {"threads", required_argument, NULL, OPT_THREADS},
+ {"verbose", no_argument, NULL, OPT_VERBOSE},
{NULL, 0, NULL, 0}
};
int c = getopt_long(argc, argv, "a::b:D:hl:mp:qSt:v",
@@ -234,6 +244,7 @@ static void process_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
if (optarg) {
parse_cpumask(optarg, &affinity_mask);
@@ -248,17 +259,49 @@ static void process_options(int argc, char *argv[])
printf("Using %u cpus.\n",
numa_bitmask_weight(affinity_mask));
break;
- case 'b': tracelimit = atoi(optarg); break;
- case 'D': duration = parse_time_string(optarg); break;
+ case OPT_BREAKTRACE:
+ case 'b':
+ tracelimit = atoi(optarg);
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_HELP:
case '?':
- case 'h': display_help(0); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'm': lockall = 1; break;
- case 'p': priority = atoi(optarg); break;
- case 'q': quiet = 1; break;
- case 'S': smp = 1; break;
- case 't': num_threads = atoi(optarg); break;
- case 'v': verbose = 1; break;
+ case 'h':
+ display_help(0);
+ break;
+ case OPT_LOOPS:
+ case 'l':
+ max_cycles = atoi(optarg);
+ break;
+ case OPT_MLOCKALL:
+ case 'm':
+ lockall = 1;
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIORITY:
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_SMP:
+ case 'S':
+ smp = 1;
+ break;
+ case OPT_THREADS:
+ case 't':
+ num_threads = atoi(optarg);
+ break;
+ case OPT_VERBOSE:
+ case 'v': verbose = 1;
+ break;
}
}
@@ -312,6 +355,27 @@ static void print_stat(struct thread_param *par, int index, int verbose)
}
}
+static void write_stats(FILE *f, void *data)
+{
+ struct thread_param *par = data;
+ struct thread_stat *s;
+ unsigned int i;
+
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ fprintf(f, " \"%u\": {\n", i);
+ s = &par->stats[i];
+ fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
+ fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
+ fprintf(f, " \"avg\": %.2f,\n", s->avg/s->cycles);
+ fprintf(f, " \"cpu\": %d\n", par->cpu);
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+
+ }
+ fprintf(f, " }\n");
+}
+
int main(int argc, char **argv)
{
sigset_t sigset;
@@ -454,6 +518,9 @@ int main(int argc, char **argv)
if (stat[i].values)
free(stat[i].values);
}
+ if (strlen(outfile) != 0)
+ rt_write_json(outfile, argc, argv, write_stats, par);
+
free(stat);
outpar:
free(par);
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 06/13] cyclicdeadline: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (4 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 05/13] signaltest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 07/13] pmqtest: " Daniel Wagner
` (6 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/sched_deadline/cyclicdeadline.c | 72 ++++++++++++++++++++++-------
1 file changed, 56 insertions(+), 16 deletions(-)
diff --git a/src/sched_deadline/cyclicdeadline.c b/src/sched_deadline/cyclicdeadline.c
index 71cde5781499..ed3c960d9916 100644
--- a/src/sched_deadline/cyclicdeadline.c
+++ b/src/sched_deadline/cyclicdeadline.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <signal.h>
#include <getopt.h>
+#include <inttypes.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -85,13 +86,11 @@ static pthread_barrier_t barrier;
static int cpu_count;
static int all_cpus;
-
static int nr_threads;
static int use_nsecs;
-
static int mark_fd;
-
static int quiet;
+static char outfile[MAX_PATH];
static int find_mount(const char *mount, char *debugfs)
{
@@ -603,16 +602,17 @@ static void usage(int error)
" tasks on. An empty CPUSET runs on all CPUs a deadline\n"
" task.\n"
" on CPU 4, and thread #5 on CPU 5.\n"
- "-D TIME --duration Specify a length for the test run.\n"
+ "-D TIME --duration Specify a length for the test run.\n"
" Append 'm', 'h', or 'd' to specify minutes, hours or\n"
" days\n"
- "-h --help Show this help menu.\n"
- "-i INTV --interval The shortest deadline for the tasks in us\n"
+ "-h --help Show this help menu.\n"
+ "-i INTV --interval The shortest deadline for the tasks in us\n"
" (default 1000us).\n"
- "-s STEP --step The amount to increase the deadline for each task in us\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
+ "-s STEP --step The amount to increase the deadline for each task in us\n"
" (default 500us).\n"
- "-t NUM --threads The number of threads to run as deadline (default 1).\n"
- "-q --quiet print a summary only on exit\n"
+ "-t NUM --threads The number of threads to run as deadline (default 1).\n"
+ "-q --quiet print a summary only on exit\n"
);
exit(error);
}
@@ -966,6 +966,32 @@ static void loop(struct sched_data *sched_data, int nr_threads)
}
}
+static void write_stats(FILE *f, void *data)
+{
+ struct sched_data *sd = data;
+ struct thread_stat *s;
+ unsigned int i;
+
+ fprintf(f, " \"num_threads\": %d,\n", nr_threads);
+ fprintf(f, " \"resolution_in_ns\": %u,\n", use_nsecs);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < nr_threads; i++) {
+ s = &sd[i].stat;
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
+ fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
+ fprintf(f, " \"avg\": %.2f\n", s->avg/s->cycles);
+ fprintf(f, " }%s\n", i == nr_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
+enum options_valud {
+ OPT_AFFINITY=1, OPT_DURATION, OPT_HELP, OPT_INTERVAL,
+ OPT_OUTPUT, OPT_STEP, OPT_THREADS, OPT_QUIET
+};
+
int main(int argc, char **argv)
{
struct sched_data *sched_data;
@@ -992,19 +1018,21 @@ int main(int argc, char **argv)
for (;;) {
static struct option options[] = {
- { "affinity", optional_argument, NULL, 'a' },
- { "duration", required_argument, NULL, 'D' },
- { "help", no_argument, NULL, 'h' },
- { "interval", required_argument, NULL, 'i' },
- { "step", required_argument, NULL, 's' },
- { "threads", required_argument, NULL, 't' },
- { "quiet", no_argument, NULL, 'q' },
+ { "affinity", optional_argument, NULL, OPT_AFFINITY },
+ { "duration", required_argument, NULL, OPT_DURATION },
+ { "help", no_argument, NULL, OPT_HELP },
+ { "interval", required_argument, NULL, OPT_INTERVAL },
+ { "output", required_argument, NULL, OPT_OUTPUT },
+ { "step", required_argument, NULL, OPT_STEP },
+ { "threads", required_argument, NULL, OPT_THREADS },
+ { "quiet", no_argument, NULL, OPT_QUIET },
{ NULL, 0, NULL, 0 },
};
c = getopt_long(argc, argv, "a::c:D:hi:s:t:q", options, NULL);
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
case 'c':
if (!nr_threads)
@@ -1016,21 +1044,30 @@ int main(int argc, char **argv)
else
all_cpus = 1;
break;
+ case OPT_INTERVAL:
case 'i':
interval = atoi(optarg);
break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_STEP:
case 's':
step = atoi(optarg);
break;
+ case OPT_THREADS:
case 't':
nr_threads = atoi(optarg);
break;
+ case OPT_DURATION:
case 'D':
duration = parse_time_string(optarg);
break;
+ case OPT_QUIET:
case 'q':
quiet = 1;
break;
+ case OPT_HELP:
case 'h':
usage(0);
break;
@@ -1190,6 +1227,9 @@ int main(int argc, char **argv)
}
}
+ if (strlen(outfile) != 0)
+ rt_write_json(outfile, argc, argv, write_stats, sched_data);
+
if (setcpu_buf)
free(setcpu_buf);
free(thread);
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 07/13] pmqtest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (5 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 06/13] cyclicdeadline: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 08/13] ptsematest: " Daniel Wagner
` (5 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/pmqtest/pmqtest.c | 137 +++++++++++++++++++++++++++++++++++-------
1 file changed, 114 insertions(+), 23 deletions(-)
diff --git a/src/pmqtest/pmqtest.c b/src/pmqtest/pmqtest.c
index 349b47741003..e1f59836ea07 100644
--- a/src/pmqtest/pmqtest.c
+++ b/src/pmqtest/pmqtest.c
@@ -22,6 +22,7 @@
#include <utmpx.h>
#include <mqueue.h>
#include <pthread.h>
+#include <inttypes.h>
#include "rt-utils.h"
#include "rt-get_cpu.h"
@@ -231,6 +232,7 @@ static void display_help(int error)
"-h --help print this help message\n"
"-i INTV --interval=INTV base interval of thread in us default=1000\n"
"-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --prio=PRIO priority\n"
"-q --quiet print a summary only on exit\n"
"-S --smp SMP testing: options -a -t and same priority\n"
@@ -258,6 +260,14 @@ static int sameprio;
static int timeout;
static int forcetimeout;
static int quiet;
+static char outfile[MAX_PATH];
+
+enum option_value {
+ OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
+ OPT_FORCETIMEOUT, OPT_HELP, OPT_INTERVAL, OPT_LOOPS,
+ OPT_OUTPUT, OPT_PRIORITY, OPT_QUIET, OPT_SMP, OPT_THREADS,
+ OPT_TIMEOUT
+};
static void process_options(int argc, char *argv[])
{
@@ -268,19 +278,20 @@ static void process_options(int argc, char *argv[])
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"duration", required_argument, NULL, 'D'},
- {"forcetimeout", required_argument, NULL, 'f'},
- {"help", no_argument, NULL, 'h'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'q'},
- {"smp", no_argument, NULL, 'S'},
- {"threads", optional_argument, NULL, 't'},
- {"timeout", required_argument, NULL, 'T'},
+ {"affinity", optional_argument, NULL, OPT_AFFINITY},
+ {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
+ {"distance", required_argument, NULL, OPT_DISTANCE},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"forcetimeout",required_argument, NULL, OPT_FORCETIMEOUT},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"interval", required_argument, NULL, OPT_INTERVAL},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"output", required_argument, NULL, OPT_OUTPUT },
+ {"priority", required_argument, NULL, OPT_PRIORITY},
+ {"quiet", no_argument, NULL, OPT_QUIET},
+ {"smp", no_argument, NULL, OPT_SMP},
+ {"threads", optional_argument, NULL, OPT_THREADS},
+ {"timeout", required_argument, NULL, OPT_TIMEOUT},
{NULL, 0, NULL, 0}
};
int c = getopt_long (argc, argv, "a::b:d:D:f:i:l:p:qSt::T:",
@@ -288,6 +299,7 @@ static void process_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
if (smp) {
warn("-a ignored due to --smp\n");
@@ -303,21 +315,53 @@ static void process_options(int argc, char *argv[])
setaffinity = AFFINITY_USEALL;
}
break;
- case 'b': tracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'D': duration = parse_time_string(optarg); break;
- case 'f': forcetimeout = atoi(optarg); break;
+ case OPT_BREAKTRACE:
+ case 'b':
+ tracelimit = atoi(optarg);
+ break;
+ case OPT_DISTANCE:
+ case 'd':
+ distance = atoi(optarg);
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_FORCETIMEOUT:
+ case 'f':
+ forcetimeout = atoi(optarg);
+ break;
+ case OPT_HELP:
case '?':
- case 'h': display_help(0); break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 'q': quiet = 1; break;
+ case 'h':
+ display_help(0);
+ break;
+ case OPT_INTERVAL:
+ case 'i':
+ interval = atoi(optarg);
+ break;
+ case OPT_LOOPS:
+ case 'l':
+ max_cycles = atoi(optarg);
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIORITY:
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_SMP:
case 'S':
smp = 1;
num_threads = max_cpus;
setaffinity = AFFINITY_USEALL;
break;
+ case OPT_THREADS:
case 't':
if (smp) {
warn("-t ignored due to --smp\n");
@@ -330,7 +374,10 @@ static void process_options(int argc, char *argv[])
else
num_threads = max_cpus;
break;
- case 'T': timeout = atoi(optarg); break;
+ case OPT_TIMEOUT:
+ case 'T':
+ timeout = atoi(optarg);
+ break;
default:
display_help(1);
break;
@@ -401,6 +448,42 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
}
}
+struct params_stats {
+ struct params *receiver;
+ struct params *sender;
+};
+
+static void write_stats(FILE *f, void *data)
+{
+ struct params_stats *ps = data;
+ struct params *s, *r;
+ unsigned int i;
+
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ s = &ps->sender[i];
+ r = &ps->receiver[i];
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"sender\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", s->cpu);
+ fprintf(f, " \"priority\": %d,\n", s->priority);
+ fprintf(f, " \"samples\": %d,\n", s->samples);
+ fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
+ fprintf(f, " },\n");
+ fprintf(f, " \"receiver\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", r->cpu);
+ fprintf(f, " \"priority\": %d,\n", r->priority);
+ fprintf(f, " \"timeoutcount\": %d,\n", r->timeoutcount);
+ fprintf(f, " \"min\": %d,\n", r->mindiff);
+ fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
+ fprintf(f, " \"max\": %d\n", r->maxdiff);
+ fprintf(f, " }\n");
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
int main(int argc, char *argv[])
{
int i;
@@ -562,6 +645,14 @@ int main(int argc, char *argv[])
mq_unlink(mqname);
}
+ if (strlen(outfile) != 0) {
+ struct params_stats ps = {
+ .receiver = receiver,
+ .sender = sender,
+ };
+ rt_write_json(outfile, argc, argv, write_stats, &ps);
+ }
+
nomem:
return 0;
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 08/13] ptsematest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (6 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 07/13] pmqtest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 09/13] sigwaittest: " Daniel Wagner
` (4 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/ptsematest/ptsematest.c | 120 ++++++++++++++++++++++++++++++------
1 file changed, 101 insertions(+), 19 deletions(-)
diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c
index 7d4ca97773d6..2755bfde5210 100644
--- a/src/ptsematest/ptsematest.c
+++ b/src/ptsematest/ptsematest.c
@@ -20,6 +20,7 @@
#include <linux/unistd.h>
#include <utmpx.h>
#include <pthread.h>
+#include <inttypes.h>
#include "rt-utils.h"
#include "rt-get_cpu.h"
@@ -155,6 +156,7 @@ static void display_help(int error)
" days.\n"
"-i INTV --interval=INTV base interval of thread in us default=1000\n"
"-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --prio=PRIO priority\n"
"-q --quiet print a summary only on exit\n"
"-S --smp SMP testing: options -a -t and same priority\n"
@@ -180,6 +182,13 @@ static int distance = 500;
static int smp;
static int sameprio;
static int quiet;
+static char outfile[MAX_PATH];
+
+enum option_value {
+ OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
+ OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT, OPT_PRIORITY,
+ OPT_QUIET, OPT_SMP, OPT_THREADS
+};
static void process_options(int argc, char *argv[])
{
@@ -190,17 +199,18 @@ static void process_options(int argc, char *argv[])
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"duration", required_argument, NULL, 'D'},
- {"help", no_argument, NULL, 'h'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"quiet", no_argument , NULL, 'q'},
- {"smp", no_argument, NULL, 'S'},
- {"threads", optional_argument, NULL, 't'},
+ {"affinity", optional_argument, NULL, OPT_AFFINITY},
+ {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
+ {"distance", required_argument, NULL, OPT_DISTANCE},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"interval", required_argument, NULL, OPT_INTERVAL},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"output", required_argument, NULL, OPT_OUTPUT },
+ {"priority", required_argument, NULL, OPT_PRIORITY},
+ {"quiet", no_argument , NULL, OPT_QUIET},
+ {"smp", no_argument, NULL, OPT_SMP},
+ {"threads", optional_argument, NULL, OPT_THREADS},
{NULL, 0, NULL, 0}
};
int c = getopt_long (argc, argv, "a::b:d:i:l:D:p:qSt::h",
@@ -208,6 +218,7 @@ static void process_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
if (smp) {
warn("-a ignored due to --smp\n");
@@ -223,20 +234,49 @@ static void process_options(int argc, char *argv[])
setaffinity = AFFINITY_USEALL;
}
break;
- case 'b': tracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'D': duration = parse_time_string(optarg); break;
- case 'i': interval = atoi(optarg); break;
+ case OPT_BREAKTRACE:
+ case 'b':
+ tracelimit = atoi(optarg);
+ break;
+ case OPT_DISTANCE:
+ case 'd':
+ distance = atoi(optarg);
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_INTERVAL:
+ case 'i':
+ interval = atoi(optarg);
+ break;
+ case OPT_HELP:
case '?':
- case 'h': display_help(0); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 'q': quiet = 1; break;
+ case 'h':
+ display_help(0);
+ break;
+ case OPT_LOOPS:
+ case 'l':
+ max_cycles = atoi(optarg);
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIORITY:
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_SMP:
case 'S':
smp = 1;
num_threads = max_cpus;
setaffinity = AFFINITY_USEALL;
break;
+ case OPT_THREADS:
case 't':
if (smp) {
warn("-t ignored due to --smp\n");
@@ -316,6 +356,40 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
}
}
+struct params_stats {
+ struct params *receiver;
+ struct params *sender;
+};
+
+static void write_stats(FILE *f, void *data)
+{
+ struct params_stats *ps = data;
+ struct params *s, *r;
+ unsigned int i;
+
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ s = &ps->sender[i];
+ r = &ps->receiver[i];
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"sender\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", s->cpu);
+ fprintf(f, " \"priority\": %d,\n", s->priority);
+ fprintf(f, " \"samples\": %d,\n", s->samples);
+ fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
+ fprintf(f, " },\n");
+ fprintf(f, " \"receiver\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", r->cpu);
+ fprintf(f, " \"priority\": %d,\n", r->priority);
+ fprintf(f, " \"min\": %d,\n", r->mindiff);
+ fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
+ fprintf(f, " \"max\": %d\n", r->maxdiff);
+ fprintf(f, " }\n");
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
int main(int argc, char *argv[])
{
@@ -439,6 +513,14 @@ int main(int argc, char *argv[])
pthread_mutex_destroy(&syncmutex[i]);
}
+ if (strlen(outfile) != 0) {
+ struct params_stats ps = {
+ .receiver = receiver,
+ .sender = sender,
+ };
+ rt_write_json(outfile, argc, argv, write_stats, &ps);
+ }
+
nomem:
return 0;
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 09/13] sigwaittest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (7 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 08/13] ptsematest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 10/13] svsematest: " Daniel Wagner
` (3 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/signaltest/signaltest.c | 1 +
src/sigwaittest/sigwaittest.c | 117 ++++++++++++++++++++++++++++------
2 files changed, 100 insertions(+), 18 deletions(-)
diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
index 09039b299367..b1a71efdf42f 100644
--- a/src/signaltest/signaltest.c
+++ b/src/signaltest/signaltest.c
@@ -361,6 +361,7 @@ static void write_stats(FILE *f, void *data)
struct thread_stat *s;
unsigned int i;
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
fprintf(f, " \"thread\": {\n");
for (i = 0; i < num_threads; i++) {
fprintf(f, " \"%u\": {\n", i);
diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c
index f10c24914d4a..0cdf30a6a769 100644
--- a/src/sigwaittest/sigwaittest.c
+++ b/src/sigwaittest/sigwaittest.c
@@ -39,6 +39,7 @@
#include <linux/unistd.h>
#include <utmpx.h>
#include <pthread.h>
+#include <inttypes.h>
#include "rt-utils.h"
#include "rt-get_cpu.h"
@@ -220,6 +221,7 @@ static void display_help(int error)
"-f [OPT] --fork[=OPT] fork new processes instead of creating threads\n"
"-i INTV --interval=INTV base interval of thread in us default=1000\n"
"-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --prio=PRIO priority\n"
"-q --quiet print a summary only on exit\n"
"-t --threads one thread per available processor\n"
@@ -240,6 +242,13 @@ static int duration;
static int interval = 1000;
static int distance = 500;
static int quiet;
+static char outfile[MAX_PATH];
+
+enum option_value {
+ OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
+ OPT_FORK, OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT,
+ OPT_PRIORITY, OPT_QUIET, OPT_THREADS
+};
static void process_options(int argc, char *argv[])
{
@@ -251,17 +260,18 @@ static void process_options(int argc, char *argv[])
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"duration", required_argument, NULL, 'D'},
- {"fork", optional_argument, NULL, 'f'},
- {"help", no_argument, NULL, 'h'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'q'},
- {"threads", optional_argument, NULL, 't'},
+ {"affinity", optional_argument, NULL, OPT_AFFINITY},
+ {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
+ {"distance", required_argument, NULL, OPT_DISTANCE},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"fork", optional_argument, NULL, OPT_FORK},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"interval", required_argument, NULL, OPT_INTERVAL},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"output", required_argument, NULL, OPT_OUTPUT },
+ {"priority", required_argument, NULL, OPT_PRIORITY},
+ {"quiet", no_argument, NULL, OPT_QUIET},
+ {"threads", optional_argument, NULL, OPT_THREADS},
{NULL, 0, NULL, 0}
};
int c = getopt_long (argc, argv, "a::b:d:D:f::hi:l:p:qt::",
@@ -269,6 +279,7 @@ static void process_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
if (optarg != NULL) {
affinity = atoi(optarg);
@@ -280,9 +291,19 @@ static void process_options(int argc, char *argv[])
setaffinity = AFFINITY_USEALL;
}
break;
- case 'b': thistracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'D': duration = parse_time_string(optarg); break;
+ case OPT_BREAKTRACE:
+ case 'b':
+ thistracelimit = atoi(optarg);
+ break;
+ case OPT_DISTANCE:
+ case 'd':
+ distance = atoi(optarg);
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_FORK:
case 'f':
if (optarg != NULL) {
wasforked = 1;
@@ -294,14 +315,31 @@ static void process_options(int argc, char *argv[])
} else
mustfork = 1;
break;
+ case OPT_HELP:
case '?':
case 'h':
display_help(0);
break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 'q': quiet = 1; break;
+ case OPT_INTERVAL:
+ case 'i':
+ interval = atoi(optarg);
+ break;
+ case OPT_LOOPS:
+ case 'l':
+ max_cycles = atoi(optarg);
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIORITY:
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_THREADS:
case 't':
if (optarg != NULL)
num_threads = atoi(optarg);
@@ -388,6 +426,41 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
}
}
+struct params_stats {
+ struct params *receiver;
+ struct params *sender;
+};
+
+static void write_stats(FILE *f, void *data)
+{
+ struct params_stats *ps = data;
+ struct params *s, *r;
+ unsigned int i;
+
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ s = &ps->sender[i];
+ r = &ps->receiver[i];
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"sender\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", s->cpu);
+ fprintf(f, " \"priority\": %d,\n", s->priority);
+ fprintf(f, " \"samples\": %d,\n", s->samples);
+ fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
+ fprintf(f, " },\n");
+ fprintf(f, " \"receiver\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", r->cpu);
+ fprintf(f, " \"priority\": %d,\n", r->priority);
+ fprintf(f, " \"min\": %d,\n", r->mindiff);
+ fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
+ fprintf(f, " \"max\": %d\n", r->maxdiff);
+ fprintf(f, " }\n");
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
int main(int argc, char *argv[])
{
int i, totalsize = 0;
@@ -627,6 +700,14 @@ int main(int argc, char *argv[])
}
}
+ if (strlen(outfile) != 0) {
+ struct params_stats ps = {
+ .receiver = receiver,
+ .sender = sender,
+ };
+ rt_write_json(outfile, argc, argv, write_stats, &ps);
+ }
+
nomem:
if (mustfork) {
munmap(param, totalsize);
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 10/13] svsematest: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (8 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 09/13] sigwaittest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 11/13] oslat: " Daniel Wagner
` (2 subsequent siblings)
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/svsematest/svsematest.c | 124 ++++++++++++++++++++++++++++++------
1 file changed, 104 insertions(+), 20 deletions(-)
diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c
index 7a298e0dea8c..23f84bcbd3dc 100644
--- a/src/svsematest/svsematest.c
+++ b/src/svsematest/svsematest.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <time.h>
#include <utmpx.h>
+#include <inttypes.h>
#include <linux/unistd.h>
@@ -233,6 +234,7 @@ static void display_help(int error)
"-f [OPT] --fork[=OPT] fork new processes instead of creating threads\n"
"-i INTV --interval=INTV base interval of thread in us default=1000\n"
"-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --prio=PRIO priority\n"
"-S --smp SMP testing: options -a -t and same priority\n"
" of all threads\n"
@@ -255,6 +257,13 @@ static int distance = 500;
static int smp;
static int sameprio;
static int quiet;
+static char outfile[MAX_PATH];
+
+enum option_value {
+ OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
+ OPT_FORK, OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT,
+ OPT_PRIORITY, OPT_QUIET, OPT_SMP, OPT_THREADS
+};
static void process_options(int argc, char *argv[])
{
@@ -266,18 +275,19 @@ static void process_options(int argc, char *argv[])
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"affinity", optional_argument, NULL, 'a'},
- {"breaktrace", required_argument, NULL, 'b'},
- {"distance", required_argument, NULL, 'd'},
- {"duration", required_argument, NULL, 'D'},
- {"fork", optional_argument, NULL, 'f'},
- {"help", no_argument, NULL, 'h'},
- {"interval", required_argument, NULL, 'i'},
- {"loops", required_argument, NULL, 'l'},
- {"priority", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'q'},
- {"smp", no_argument, NULL, 'S'},
- {"threads", optional_argument, NULL, 't'},
+ {"affinity", optional_argument, NULL, OPT_AFFINITY},
+ {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
+ {"distance", required_argument, NULL, OPT_DISTANCE},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"fork", optional_argument, NULL, OPT_FORK},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"interval", required_argument, NULL, OPT_INTERVAL},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"output", required_argument, NULL, OPT_OUTPUT},
+ {"priority", required_argument, NULL, OPT_PRIORITY},
+ {"quiet", no_argument, NULL, OPT_QUIET},
+ {"smp", no_argument, NULL, OPT_SMP},
+ {"threads", optional_argument, NULL, OPT_THREADS},
{NULL, 0, NULL, 0}
};
int c = getopt_long (argc, argv, "a::b:d:D:f::hi:l:p:qSt::",
@@ -285,6 +295,7 @@ static void process_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
+ case OPT_AFFINITY:
case 'a':
if (smp) {
warn("-a ignored due to --smp\n");
@@ -300,9 +311,19 @@ static void process_options(int argc, char *argv[])
setaffinity = AFFINITY_USEALL;
}
break;
- case 'b': thistracelimit = atoi(optarg); break;
- case 'd': distance = atoi(optarg); break;
- case 'D': duration = parse_time_string(optarg); break;
+ case OPT_BREAKTRACE:
+ case 'b':
+ thistracelimit = atoi(optarg);
+ break;
+ case OPT_DISTANCE:
+ case 'd':
+ distance = atoi(optarg);
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_FORK:
case 'f':
if (optarg != NULL) {
wasforked = 1;
@@ -314,16 +335,36 @@ static void process_options(int argc, char *argv[])
} else
mustfork = 1;
break;
- case 'h': display_help(0); break;
- case 'i': interval = atoi(optarg); break;
- case 'l': max_cycles = atoi(optarg); break;
- case 'p': priority = atoi(optarg); break;
- case 'q': quiet = 1; break;
+ case OPT_HELP:
+ case 'h':
+ display_help(0);
+ break;
+ case OPT_INTERVAL:
+ case 'i':
+ interval = atoi(optarg);
+ break;
+ case OPT_LOOPS:
+ case 'l':
+ max_cycles = atoi(optarg);
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIORITY:
+ case 'p':
+ priority = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_SMP:
case 'S':
smp = 1;
num_threads = max_cpus;
setaffinity = AFFINITY_USEALL;
break;
+ case OPT_THREADS:
case 't':
if (smp) {
warn("-t ignored due to --smp\n");
@@ -380,6 +421,41 @@ static void sighand(int sig)
mustshutdown = 1;
}
+struct params_stats {
+ struct params *receiver;
+ struct params *sender;
+};
+
+static void write_stats(FILE *f, void *data)
+{
+ struct params_stats *ps = data;
+ struct params *s, *r;
+ unsigned int i;
+
+ fprintf(f, " \"num_threads\": %d,\n", num_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < num_threads; i++) {
+ s = &ps->sender[i];
+ r = &ps->receiver[i];
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"sender\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", s->cpu);
+ fprintf(f, " \"priority\": %d,\n", s->priority);
+ fprintf(f, " \"samples\": %d,\n", s->samples);
+ fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
+ fprintf(f, " },\n");
+ fprintf(f, " \"receiver\": {\n");
+ fprintf(f, " \"cpu\": %d,\n", r->cpu);
+ fprintf(f, " \"priority\": %d,\n", r->priority);
+ fprintf(f, " \"min\": %d,\n", r->mindiff);
+ fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
+ fprintf(f, " \"max\": %d\n", r->maxdiff);
+ fprintf(f, " }\n");
+ fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
int verbose, int quiet)
{
@@ -696,6 +772,14 @@ int main(int argc, char *argv[])
}
}
+ if (strlen(outfile) != 0) {
+ struct params_stats ps = {
+ .receiver = receiver,
+ .sender = sender,
+ };
+ rt_write_json(outfile, argc, argv, write_stats, &ps);
+ }
+
nosem:
for (i = 0; i < num_threads; i++)
semctl(receiver[i].semid, -1, IPC_RMID);
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 11/13] oslat: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (9 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 10/13] svsematest: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 12/13] rt-migrate-test: " Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 13/13] oslat: Add quiet command line option Daniel Wagner
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/oslat/oslat.c | 97 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 82 insertions(+), 15 deletions(-)
diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
index 9e6f70600830..987f2002985d 100644
--- a/src/oslat/oslat.c
+++ b/src/oslat/oslat.c
@@ -29,7 +29,7 @@
#include <numa.h>
#include <math.h>
#include <limits.h>
-#include <linux/unistd.h>
+#include <inttypes.h>
#include <sys/prctl.h>
#include <sys/stat.h>
@@ -41,6 +41,8 @@
#include <sys/mman.h>
#include <sys/syscall.h>
+#include <linux/unistd.h>
+
#include "rt-utils.h"
#include "rt-numa.h"
#include "rt-error.h"
@@ -171,6 +173,7 @@ struct global {
uint64_t bias;
int single_preheat_thread;
int output_omit_zero_buckets;
+ char outfile[MAX_PATH];
/* Mutable state. */
volatile enum command cmd;
@@ -479,6 +482,39 @@ static void write_summary(struct thread *t)
printf("\n");
}
+static void write_summary_json(FILE *f, void *data)
+{
+ struct thread *t = data;
+ int i, j, comma;
+
+ fprintf(f, " \"num_threads\": %d,\n", g.n_threads);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < g.n_threads; ++i) {
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"cpu\": %d,\n", t[i].core_i);
+ fprintf(f, " \"freq\": %d,\n", t[i].cpu_mhz);
+ fprintf(f, " \"min\": %" PRIu64 ",\n", t[i].minlat);
+ fprintf(f, " \"avg\": %3lf,\n", t[i].average);
+ fprintf(f, " \"max\": %" PRIu64 ",\n", t[i].maxlat);
+ fprintf(f, " \"duration\": %.3f,\n",
+ cycles_to_sec(&(t[i]), t[i].runtime));
+ fprintf(f, " \"histogram\": {");
+ for (j = 0, comma = 0; j < g.bucket_size; j++) {
+ if (t[i].buckets[j] == 0)
+ continue;
+ fprintf(f, "%s", comma ? ",\n" : "\n");
+ fprintf(f, " \"%" PRIu64 "\": %" PRIu64,
+ g.bias+j+1, t[i].buckets[j]);
+ comma = 1;
+ }
+ if (comma)
+ fprintf(f, "\n");
+ fprintf(f, " }\n");
+ fprintf(f, " }%s\n", i == g.n_threads - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
static void run_expt(struct thread *threads, int runtime_secs)
{
int i;
@@ -533,6 +569,7 @@ static void usage(int error)
" NOTE: please make sure the CPU frequency on all testing cores\n"
" are locked before using this parmater. If you don't know how\n"
" to lock the freq then please don't use this parameter.\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-T, --trace-threshold Stop the test when threshold triggered (in us),\n"
" print a marker in ftrace and stop ftrace too.\n"
"-v, --version Display the version of the software.\n"
@@ -557,34 +594,45 @@ static int workload_select(char *name)
return -1;
}
+enum option_value {
+ OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
+ OPT_DURATION, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH,
+ OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, OPT_OUTPUT,
+ OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, OPT_VERSION
+
+};
+
/* Process commandline options */
static void parse_options(int argc, char *argv[])
{
while (1) {
+ int option_index = 0;
static struct option options[] = {
- { "bucket-size", required_argument, NULL, 'b' },
- { "cpu-list", required_argument, NULL, 'c' },
- { "cpu-main-thread", required_argument, NULL, 'C'},
- { "duration", required_argument, NULL, 'D' },
- { "rtprio", required_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { "trace-threshold", required_argument, NULL, 'T' },
- { "workload", required_argument, NULL, 'w'},
- { "workload-mem", required_argument, NULL, 'm'},
- { "bias", no_argument, NULL, 'B'},
- { "single-preheat", no_argument, NULL, 's'},
- { "zero-omit", no_argument, NULL, 'u'},
- { "version", no_argument, NULL, 'v'},
+ { "bucket-size",required_argument, NULL, OPT_BUCKETSIZE },
+ { "cpu-list", required_argument, NULL, OPT_CPU_LIST },
+ { "cpu-main-thread", required_argument, NULL, OPT_CPU_MAIN_THREAD},
+ { "duration", required_argument, NULL, OPT_DURATION },
+ { "rtprio", required_argument, NULL, OPT_RT_PRIO },
+ { "help", no_argument, NULL, OPT_HELP },
+ { "trace-threshold", required_argument, NULL, OPT_TRACE_TH },
+ { "workload", required_argument, NULL, OPT_WORKLOAD },
+ { "workload-mem", required_argument, NULL, OPT_WORKLOAD_MEM },
+ { "bias", no_argument, NULL, OPT_BIAS },
+ { "single-preheat", no_argument, NULL, OPT_SINGLE_PREHEAT },
+ { "output", required_argument, NULL, OPT_OUTPUT },
+ { "zero-omit", no_argument, NULL, OPT_ZERO_OMIT },
+ { "version", no_argument, NULL, OPT_VERSION },
{ NULL, 0, NULL, 0 },
};
int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:sw:T:vz",
- options, NULL);
+ options, &option_index);
long ncores;
if (c == -1)
break;
switch (c) {
+ case OPT_BUCKETSIZE:
case 'b':
g.bucket_size = strtol(optarg, NULL, 10);
if (g.bucket_size > 1024 || g.bucket_size <= 4) {
@@ -593,12 +641,15 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_BIAS:
case 'B':
g.enable_bias = 1;
break;
+ case OPT_CPU_LIST:
case 'c':
g.cpu_list = strdup(optarg);
break;
+ case OPT_CPU_MAIN_THREAD:
case 'C':
ncores = sysconf(_SC_NPROCESSORS_CONF);
g.cpu_main_thread = strtol(optarg, NULL, 10);
@@ -608,6 +659,7 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_DURATION:
case 'D':
g.runtime = parse_time_string(optarg);
if (!g.runtime) {
@@ -615,6 +667,7 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_RT_PRIO:
case 'f':
g.rtprio = strtol(optarg, NULL, 10);
if (g.rtprio < 1 || g.rtprio > 99) {
@@ -622,6 +675,10 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_OUTPUT:
+ strncpy(g.outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_TRACE_TH:
case 'T':
g.trace_threshold = strtol(optarg, NULL, 10);
if (g.trace_threshold <= 0) {
@@ -630,6 +687,7 @@ static void parse_options(int argc, char *argv[])
}
enable_trace_mark();
break;
+ case OPT_WORKLOAD:
case 'w':
if (workload_select(optarg)) {
printf("Unknown workload '%s'. Please choose from: ", optarg);
@@ -642,12 +700,14 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_WORKLOAD_MEM:
case 'm':
if (parse_mem_string(optarg, &g.workload_mem_size)) {
printf("Unknown workload memory size '%s'.\n\n", optarg);
exit(1);
}
break;
+ case OPT_SINGLE_PREHEAT:
case 's':
/*
* Only use one core for pre-heat. Then if --bias is used, the
@@ -655,6 +715,7 @@ static void parse_options(int argc, char *argv[])
*/
g.single_preheat_thread = true;
break;
+ case OPT_VERSION:
case 'v':
/*
* Because we always dump the version even before parsing options,
@@ -662,9 +723,11 @@ static void parse_options(int argc, char *argv[])
*/
exit(0);
break;
+ case OPT_ZERO_OMIT:
case 'z':
g.output_omit_zero_buckets = 1;
break;
+ case OPT_HELP:
case 'h':
usage(0);
break;
@@ -781,6 +844,10 @@ int main(int argc, char *argv[])
write_summary(threads);
+ if (strlen(g.outfile) != 0)
+ rt_write_json(g.outfile, argc, argv,
+ write_summary_json, threads);
+
if (g.cpu_list) {
free(g.cpu_list);
g.cpu_list = NULL;
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 12/13] rt-migrate-test: Add JSON output feature
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (10 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 11/13] oslat: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 13/13] oslat: Add quiet command line option Daniel Wagner
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
Write the test results as JSON output to a file. This allows to
simplifies any parsing later on.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/rt-migrate-test/rt-migrate-test.c | 120 ++++++++++++++++++++++----
1 file changed, 101 insertions(+), 19 deletions(-)
diff --git a/src/rt-migrate-test/rt-migrate-test.c b/src/rt-migrate-test/rt-migrate-test.c
index 9bf716c9178c..56b7b66ccdf4 100644
--- a/src/rt-migrate-test/rt-migrate-test.c
+++ b/src/rt-migrate-test/rt-migrate-test.c
@@ -19,11 +19,14 @@
#include <fcntl.h>
#include <signal.h>
#include <sys/time.h>
-#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
+#include <inttypes.h>
+
+#include <linux/unistd.h>
+
#include "rt-utils.h"
int nr_tasks;
@@ -99,6 +102,7 @@ static int done;
static int loop;
static int duration;
static int quiet;
+static char outfile[MAX_PATH];
static pthread_barrier_t start_barrier;
static pthread_barrier_t end_barrier;
@@ -160,6 +164,7 @@ static void usage(int error)
"-h --help Print this help message\n"
"-l LOOPS --loops=LOOPS Number of iterations to run (50)\n"
"-m TIME --maxerr=TIME Max allowed error (microsecs)\n"
+ " --output=FILENAME write final results into FILENAME, JSON formatted\n"
"-p PRIO --prio=PRIO base priority to start RT tasks with (2)\n"
"-q --quiet print a summary only on exit\n"
"-r TIME --run-time=TIME Run time (ms) to busy loop the threads (20)\n"
@@ -169,22 +174,29 @@ static void usage(int error)
exit(error);
}
+enum option_value {
+ OPT_CHECK=1, OPT_DURATION, OPT_EQUAL, OPT_HELP, OPT_LOOPS,
+ OPT_MAXERR, OPT_OUTPUT, OPT_PRIO, OPT_QUIET, OPT_RUN_TIME,
+ OPT_SLEEP_TIME
+};
+
static void parse_options(int argc, char *argv[])
{
for (;;) {
int option_index = 0;
/** Options for getopt */
static struct option long_options[] = {
- {"check", no_argument, NULL, 'c'},
- {"duration", required_argument, NULL, 'D'},
- {"equal", no_argument, NULL, 'e'},
- {"help", no_argument, NULL, 'h'},
- {"loops", required_argument, NULL, 'l'},
- {"maxerr", required_argument, NULL, 'm'},
- {"prio", required_argument, NULL, 'p'},
- {"quiet", no_argument, NULL, 'q'},
- {"run-time", required_argument, NULL, 'r'},
- {"sleep-time", required_argument, NULL, 's'},
+ {"check", no_argument, NULL, OPT_CHECK},
+ {"duration", required_argument, NULL, OPT_DURATION},
+ {"equal", no_argument, NULL, OPT_EQUAL},
+ {"help", no_argument, NULL, OPT_HELP},
+ {"loops", required_argument, NULL, OPT_LOOPS},
+ {"maxerr", required_argument, NULL, OPT_MAXERR},
+ {"output", required_argument, NULL, OPT_OUTPUT },
+ {"prio", required_argument, NULL, OPT_PRIO},
+ {"quiet", no_argument, NULL, OPT_QUIET},
+ {"run-time", required_argument, NULL, OPT_RUN_TIME},
+ {"sleep-time", required_argument, NULL, OPT_SLEEP_TIME},
{NULL, 0, NULL, 0}
};
int c = getopt_long(argc, argv, "cD:ehl:m:p:qr:s:",
@@ -192,21 +204,50 @@ static void parse_options(int argc, char *argv[])
if (c == -1)
break;
switch (c) {
- case 'c': check = 1; break;
- case 'D': duration = parse_time_string(optarg); break;
- case 'e': equal = 1; break;
+ case OPT_CHECK:
+ case 'c':
+ check = 1;
+ break;
+ case OPT_DURATION:
+ case 'D':
+ duration = parse_time_string(optarg);
+ break;
+ case OPT_EQUAL:
+ case 'e':
+ equal = 1;
+ break;
+ case OPT_HELP:
case '?':
case 'h':
usage(0);
break;
- case 'l': nr_runs = atoi(optarg); break;
- case 'm': max_err = usec2nano(atoi(optarg)); break;
- case 'p': prio_start = atoi(optarg); break;
- case 'q': quiet = 1; break;
+ case OPT_LOOPS:
+ case 'l':
+ nr_runs = atoi(optarg);
+ break;
+ case OPT_MAXERR:
+ case 'm':
+ max_err = usec2nano(atoi(optarg));
+ break;
+ case OPT_OUTPUT:
+ strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
+ break;
+ case OPT_PRIO:
+ case 'p':
+ prio_start = atoi(optarg);
+ break;
+ case OPT_QUIET:
+ case 'q':
+ quiet = 1;
+ break;
+ case OPT_RUN_TIME:
case 'r':
run_interval = atoi(optarg);
break;
- case 's': interval = atoi(optarg); break;
+ case OPT_SLEEP_TIME:
+ case 's':
+ interval = atoi(optarg);
+ break;
default:
usage(1);
}
@@ -313,6 +354,44 @@ static void print_results(void)
}
}
+static void write_stats(FILE *f, void *data)
+{
+ int i;
+ int t;
+ unsigned long long tasks_max[nr_tasks];
+ unsigned long long tasks_min[nr_tasks];
+ unsigned long long tasks_avg[nr_tasks];
+
+ memset(tasks_max, 0, sizeof(tasks_max[0])*nr_tasks);
+ memset(tasks_min, 0xff, sizeof(tasks_min[0])*nr_tasks);
+ memset(tasks_avg, 0, sizeof(tasks_avg[0])*nr_tasks);
+
+ for (i=0; i < nr_runs; i++) {
+ for (t=0; t < nr_tasks; t++) {
+ unsigned long long itv = intervals[i][t];
+
+ if (tasks_max[t] < itv)
+ tasks_max[t] = itv;
+ if (tasks_min[t] > itv)
+ tasks_min[t] = itv;
+ tasks_avg[t] += itv;
+ }
+ }
+
+ fprintf(f, " \"num_threads\": %d,\n", nr_tasks);
+ fprintf(f, " \"thread\": {\n");
+ for (i = 0; i < nr_tasks; i++) {
+ fprintf(f, " \"%u\": {\n", i);
+ fprintf(f, " \"prio\": %d,\n", calc_prio(i));
+ fprintf(f, " \"min\": %lld,\n", nano2usec(tasks_min[i]));
+ fprintf(f, " \"avg\": %lld,\n", nano2usec(tasks_avg[i]) / nr_runs);
+ fprintf(f, " \"max\": %lld,\n", nano2usec(tasks_max[i]));
+ fprintf(f, " \"total\": %lld\n", nano2usec(tasks_avg[i]));
+ fprintf(f, " }%s\n", i == nr_tasks - 1 ? "" : ",");
+ }
+ fprintf(f, " }\n");
+}
+
static unsigned long busy_loop(unsigned long long start_time)
{
unsigned long long time;
@@ -582,6 +661,9 @@ int main (int argc, char **argv)
print_results();
+ if (strlen(outfile) != 0)
+ rt_write_json(outfile, argc, argv, write_stats, NULL);
+
if (stop) {
/*
* We use this test in bash while loops
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH rt-tests v5 13/13] oslat: Add quiet command line option
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
` (11 preceding siblings ...)
2021-02-10 17:51 ` [PATCH rt-tests v5 12/13] rt-migrate-test: " Daniel Wagner
@ 2021-02-10 17:51 ` Daniel Wagner
2021-02-17 3:52 ` John Kacur
12 siblings, 1 reply; 27+ messages in thread
From: Daniel Wagner @ 2021-02-10 17:51 UTC (permalink / raw
To: Clark Williams, John Kacur; +Cc: linux-rt-users, Daniel Wagner
The quiet option is useful for automated test setups where
only the final result of the run is interesting.
Furthermore, this makes oslat accept rt-tests standard options.
Signed-off-by: Daniel Wagner <dwagner@suse.de>
---
src/oslat/oslat.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
index 987f2002985d..0d9afedbdc82 100644
--- a/src/oslat/oslat.c
+++ b/src/oslat/oslat.c
@@ -171,6 +171,7 @@ struct global {
uint64_t workload_mem_size;
int enable_bias;
uint64_t bias;
+ int quiet;
int single_preheat_thread;
int output_omit_zero_buckets;
char outfile[MAX_PATH];
@@ -565,6 +566,7 @@ static void usage(int error)
" Total memory usage will be this value multiplies 2*N,\n"
" because there will be src/dst buffers for each thread, and\n"
" N is the number of processors for testing.\n"
+ "-q --quiet print a summary only on exit\n"
"-s, --single-preheat Use a single thread when measuring latency at preheat stage\n"
" NOTE: please make sure the CPU frequency on all testing cores\n"
" are locked before using this parmater. If you don't know how\n"
@@ -598,8 +600,8 @@ enum option_value {
OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
OPT_DURATION, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH,
OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, OPT_OUTPUT,
- OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, OPT_VERSION
-
+ OPT_QUIET, OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT,
+ OPT_VERSION
};
/* Process commandline options */
@@ -618,13 +620,14 @@ static void parse_options(int argc, char *argv[])
{ "workload", required_argument, NULL, OPT_WORKLOAD },
{ "workload-mem", required_argument, NULL, OPT_WORKLOAD_MEM },
{ "bias", no_argument, NULL, OPT_BIAS },
+ { "quiet", no_argument, NULL, OPT_QUIET },
{ "single-preheat", no_argument, NULL, OPT_SINGLE_PREHEAT },
{ "output", required_argument, NULL, OPT_OUTPUT },
{ "zero-omit", no_argument, NULL, OPT_ZERO_OMIT },
{ "version", no_argument, NULL, OPT_VERSION },
{ NULL, 0, NULL, 0 },
};
- int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:sw:T:vz",
+ int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:qsw:T:vz",
options, &option_index);
long ncores;
@@ -707,6 +710,10 @@ static void parse_options(int argc, char *argv[])
exit(1);
}
break;
+ case OPT_QUIET:
+ case 'q':
+ g.quiet = 1;
+ break;
case OPT_SINGLE_PREHEAT:
case 's':
/*
@@ -825,9 +832,11 @@ int main(int argc, char *argv[])
signal(SIGINT, handle_alarm);
signal(SIGTERM, handle_alarm);
- dump_globals();
+ if (!g.quiet)
+ dump_globals();
- printf("Pre-heat for 1 seconds...\n");
+ if (!g.quiet)
+ printf("Pre-heat for 1 seconds...\n");
if (g.single_preheat_thread)
g.n_threads = 1;
else
@@ -835,12 +844,14 @@ int main(int argc, char *argv[])
run_expt(threads, 1);
record_bias(threads);
- printf("Test starts...\n");
+ if (!g.quiet)
+ printf("Test starts...\n");
/* Reset n_threads to always run on all the cores */
g.n_threads = g.n_threads_total;
run_expt(threads, g.runtime);
- printf("Test completed.\n\n");
+ if (!g.quiet)
+ printf("Test completed.\n\n");
write_summary(threads);
--
2.30.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper
2021-02-10 17:51 ` [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper Daniel Wagner
@ 2021-02-17 3:50 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:50 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> rt_write_json writes the common system information header of the
> rt-test currently executed.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/include/rt-utils.h | 4 ++
> src/lib/rt-utils.c | 96 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 100 insertions(+)
>
> diff --git a/src/include/rt-utils.h b/src/include/rt-utils.h
> index 39ddbd9eae29..36af92b170df 100644
> --- a/src/include/rt-utils.h
> +++ b/src/include/rt-utils.h
> @@ -80,4 +80,8 @@ static inline int64_t calctime(struct timespec t)
> return time;
> }
>
> +void rt_write_json(const char *filename, int argc, char *argv[],
> + void (*cb)(FILE *, void *),
> + void *data);
> +
> #endif /* __RT_UTILS.H */
> diff --git a/src/lib/rt-utils.c b/src/lib/rt-utils.c
> index 321a11b1172d..00907c573d6a 100644
> --- a/src/lib/rt-utils.c
> +++ b/src/lib/rt-utils.c
> @@ -20,6 +20,9 @@
> #include <sys/stat.h>
> #include <unistd.h>
> #include <sys/syscall.h> /* For SYS_gettid definitions */
> +#include <sys/utsname.h>
> +#include <time.h>
> +#include <sys/time.h>
>
> #include "rt-utils.h"
> #include "rt-sched.h"
> @@ -482,3 +485,96 @@ void disable_trace_mark(void)
> {
> close_tracemark_fd();
> }
> +
> +static char *get_cmdline(int argc, char *argv[])
> +{
> + char *cmdline;
> + int len, i;
> +
> + len = 0;
> + for (i = 0; i < argc; i++)
> + len += strlen(argv[i]) + 1;
> +
> + cmdline = malloc(len);
> + if (!cmdline)
> + err_exit(ENOMEM, "Could not copy cmdline");
> +
> + memset(cmdline, 0, len);
> + for (i = 0; i < argc;) {
> + cmdline = strcat(cmdline, argv[i]);
> + i++;
> + if (i < argc)
> + cmdline = strcat(cmdline, " ");
> + }
> +
> + return cmdline;
> +}
> +
> +void rt_write_json(const char *filename, int argc, char *argv[],
> + void (*cb)(FILE *, void *),
> + void *data)
> +{
> + unsigned char buf[1];
> + struct utsname uts;
> + struct timeval tv;
> + char tsbuf[64];
> + struct tm *tm;
> + char *cmdline;
> + FILE *f, *s;
> + time_t t;
> + size_t n;
> + int rt = 0;
> +
> + if (!filename || !strcmp("-", filename)) {
> + f = stdout;
> + } else {
> + f = fopen(filename, "w");
> + if (!f)
> + err_exit(errno, "Failed to open '%s'\n", filename);
> + }
> +
> + cmdline = get_cmdline(argc, argv);
> + if (!cmdline)
> + err_exit(ENOMEM, "get_cmdline()");
> +
> +
> + gettimeofday(&tv, NULL);
> + t = tv.tv_sec;
> + tm = localtime(&t);
> + /* RFC 2822-compliant date format */
> + strftime(tsbuf, sizeof(tsbuf), "%a, %d %b %Y %T %z", tm);
> +
> + s = fopen("/sys/kernel/realtime", "r");
> + if (s) {
> + n = fread(buf, 1, 1, s);
> + if (n == 1 && buf[0] == '1')
> + rt = 1;
> + fclose(s);
> + }
> +
> + if (uname(&uts))
> + err_exit(errno, "Could not retrieve system information");
> +
> + fprintf(f, "{\n");
> + fprintf(f, " \"file_version\": 1,\n");
> + fprintf(f, " \"cmdline:\": \"%s\",\n", cmdline);
> + fprintf(f, " \"rt_test_version:\": \"%1.2f\",\n", VERSION);
> + fprintf(f, " \"finished\": \"%s\",\n", tsbuf);
> + fprintf(f, " \"sysinfo\": {\n");
> + fprintf(f, " \"sysname\": \"%s\",\n", uts.sysname);
> + fprintf(f, " \"nodename\": \"%s\",\n", uts.nodename);
> + fprintf(f, " \"release\": \"%s\",\n", uts.release);
> + fprintf(f, " \"version\": \"%s\",\n", uts.version);
> + fprintf(f, " \"machine\": \"%s\",\n", uts.machine);
> + fprintf(f, " \"realtime\": %d\n", rt);
> + fprintf(f, " },\n");
> +
> + (cb)(f, data);
> +
> + fprintf(f, "}\n");
> +
> + free(cmdline);
> +
> + if (!filename || strcmp("-", filename))
> + fclose(f);
> +}
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature Daniel Wagner
@ 2021-02-17 3:50 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:50 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/cyclictest/cyclictest.c | 46 ++++++++++++++++++++++++++++++++++++-
> 1 file changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
> index 7c45732c1553..3d0cf3f84b69 100644
> --- a/src/cyclictest/cyclictest.c
> +++ b/src/cyclictest/cyclictest.c
> @@ -11,6 +11,7 @@
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdint.h>
> +#include <inttypes.h>
> #include <stdarg.h>
> #include <unistd.h>
> #include <fcntl.h>
> @@ -217,6 +218,7 @@ static struct timespec globalt;
>
> static char fifopath[MAX_PATH];
> static char histfile[MAX_PATH];
> +static char outfile[MAX_PATH];
>
> static struct thread_param **parameters;
> static struct thread_stat **statistics;
> @@ -838,6 +840,7 @@ static void display_help(int error)
> " latency is hit. Useful for low bandwidth.\n"
> "-N --nsecs print results in ns instead of us (default us)\n"
> "-o RED --oscope=RED oscilloscope mode, reduce verbose output by RED\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --priority=PRIO priority of highest prio thread\n"
> " --policy=NAME policy of measurement thread, where NAME may be one\n"
> " of: other, normal, batch, idle, fifo or rr.\n"
> @@ -945,7 +948,7 @@ enum option_values {
> OPT_TRIGGER_NODES, OPT_UNBUFFERED, OPT_NUMA, OPT_VERBOSE,
> OPT_DBGCYCLIC, OPT_POLICY, OPT_HELP, OPT_NUMOPTS,
> OPT_ALIGNED, OPT_SECALIGNED, OPT_LAPTOP, OPT_SMI,
> - OPT_TRACEMARK, OPT_POSIX_TIMERS,
> + OPT_TRACEMARK, OPT_POSIX_TIMERS, OPT_OUTPUT
> };
>
> /* Process commandline options */
> @@ -979,6 +982,7 @@ static void process_options(int argc, char *argv[])
> {"refresh_on_max", no_argument, NULL, OPT_REFRESH },
> {"nsecs", no_argument, NULL, OPT_NSECS },
> {"oscope", required_argument, NULL, OPT_OSCOPE },
> + {"output", required_argument, NULL, OPT_OUTPUT },
> {"priority", required_argument, NULL, OPT_PRIORITY },
> {"quiet", no_argument, NULL, OPT_QUIET },
> {"priospread", no_argument, NULL, OPT_PRIOSPREAD },
> @@ -1073,6 +1077,9 @@ static void process_options(int argc, char *argv[])
> case 'o':
> case OPT_OSCOPE:
> oscope_reduction = atoi(optarg); break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> case 'p':
> case OPT_PRIORITY:
> priority = atoi(optarg);
> @@ -1690,6 +1697,40 @@ static void rstat_setup(void)
> return;
> }
>
> +static void write_stats(FILE *f, void *data)
> +{
> + struct thread_param **par = parameters;
> + unsigned int i, j, comma;
> + struct thread_stat *s;
> +
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> + fprintf(f, " \"resolution_in_ns\": %u,\n", use_nsecs);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + fprintf(f, " \"%u\": {\n", i);
> +
> + fprintf(f, " \"histogram\": {");
> + s = par[i]->stats;
> + for (j = 0, comma = 0; j < histogram; j++) {
> + if (s->hist_array[j] == 0)
> + continue;
> + fprintf(f, "%s", comma ? ",\n" : "\n");
> + fprintf(f, " \"%u\": %" PRIu64,j, s->hist_array[j]);
> + comma = 1;
> + }
> + if (comma)
> + fprintf(f, "\n");
> + fprintf(f, " },\n");
> + fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
> + fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
> + fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
> + fprintf(f, " \"avg\": %.2f,\n", s->avg/s->cycles);
> + fprintf(f, " \"cpu\": %d,\n", par[i]->cpu);
> + fprintf(f, " \"node\": %d\n", par[i]->node);
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
>
> int main(int argc, char **argv)
> {
> @@ -2035,6 +2076,9 @@ int main(int argc, char **argv)
> if (!verbose && !quiet && refresh_on_max)
> printf("\033[%dB", num_threads + 2);
>
> + if (strlen(outfile) != 0)
> + rt_write_json(outfile, argc, argv, write_stats, NULL);
> +
> if (quiet)
> quiet = 2;
> for (i = 0; i < num_threads; i++) {
> --
> 2.30.0
>
>
- Added a space after a comma in fprintf
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 05/13] signaltest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 05/13] signaltest: " Daniel Wagner
@ 2021-02-17 3:50 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:50 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/signaltest/signaltest.c | 109 +++++++++++++++++++++++++++++-------
> 1 file changed, 88 insertions(+), 21 deletions(-)
>
> diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
> index dd5633d5fc51..09039b299367 100644
> --- a/src/signaltest/signaltest.c
> +++ b/src/signaltest/signaltest.c
> @@ -22,6 +22,7 @@
> #include <unistd.h>
> #include <errno.h>
> #include <sched.h>
> +#include <inttypes.h>
>
> #include <linux/unistd.h>
>
> @@ -205,6 +206,14 @@ static int verbose;
> static int quiet;
> static int lockall;
> static struct bitmask *affinity_mask = NULL;
> +static char outfile[MAX_PATH];
> +
> +enum option_values {
> + OPT_AFFINITY=1, OPT_BREAKTRACE,
> + OPT_DURATION, OPT_HELP, OPT_LOOPS,
> + OPT_MLOCKALL, OPT_OUTPUT, OPT_PRIORITY,
> + OPT_QUIET, OPT_SMP, OPT_THREADS, OPT_VERBOSE
> +};
>
> /* Process commandline options */
> static void process_options(int argc, char *argv[])
> @@ -216,17 +225,18 @@ static void process_options(int argc, char *argv[])
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"affinity", optional_argument, NULL, 'a'},
> - {"breaktrace", required_argument, NULL, 'b'},
> - {"duration", required_argument, NULL, 'D'},
> - {"help", no_argument, NULL, 'h'},
> - {"loops", required_argument, NULL, 'l'},
> - {"mlockall", no_argument, NULL, 'm'},
> - {"priority", required_argument, NULL, 'p'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"smp", no_argument, NULL, 'S'},
> - {"threads", required_argument, NULL, 't'},
> - {"verbose", no_argument, NULL, 'v'},
> + {"affinity", optional_argument, NULL, OPT_AFFINITY},
> + {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"mlockall", no_argument, NULL, OPT_MLOCKALL},
> + {"output", required_argument, NULL, OPT_OUTPUT},
> + {"priority", required_argument, NULL, OPT_PRIORITY},
> + {"quiet", no_argument, NULL, OPT_QUIET},
> + {"smp", no_argument, NULL, OPT_SMP},
> + {"threads", required_argument, NULL, OPT_THREADS},
> + {"verbose", no_argument, NULL, OPT_VERBOSE},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long(argc, argv, "a::b:D:hl:mp:qSt:v",
> @@ -234,6 +244,7 @@ static void process_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> if (optarg) {
> parse_cpumask(optarg, &affinity_mask);
> @@ -248,17 +259,49 @@ static void process_options(int argc, char *argv[])
> printf("Using %u cpus.\n",
> numa_bitmask_weight(affinity_mask));
> break;
> - case 'b': tracelimit = atoi(optarg); break;
> - case 'D': duration = parse_time_string(optarg); break;
> + case OPT_BREAKTRACE:
> + case 'b':
> + tracelimit = atoi(optarg);
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_HELP:
> case '?':
> - case 'h': display_help(0); break;
> - case 'l': max_cycles = atoi(optarg); break;
> - case 'm': lockall = 1; break;
> - case 'p': priority = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> - case 'S': smp = 1; break;
> - case 't': num_threads = atoi(optarg); break;
> - case 'v': verbose = 1; break;
> + case 'h':
> + display_help(0);
> + break;
> + case OPT_LOOPS:
> + case 'l':
> + max_cycles = atoi(optarg);
> + break;
> + case OPT_MLOCKALL:
> + case 'm':
> + lockall = 1;
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIORITY:
> + case 'p':
> + priority = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_SMP:
> + case 'S':
> + smp = 1;
> + break;
> + case OPT_THREADS:
> + case 't':
> + num_threads = atoi(optarg);
> + break;
> + case OPT_VERBOSE:
> + case 'v': verbose = 1;
> + break;
> }
> }
>
> @@ -312,6 +355,27 @@ static void print_stat(struct thread_param *par, int index, int verbose)
> }
> }
>
> +static void write_stats(FILE *f, void *data)
> +{
> + struct thread_param *par = data;
> + struct thread_stat *s;
> + unsigned int i;
> +
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + fprintf(f, " \"%u\": {\n", i);
> + s = &par->stats[i];
> + fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
> + fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
> + fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
> + fprintf(f, " \"avg\": %.2f,\n", s->avg/s->cycles);
> + fprintf(f, " \"cpu\": %d\n", par->cpu);
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> +
> + }
> + fprintf(f, " }\n");
> +}
> +
> int main(int argc, char **argv)
> {
> sigset_t sigset;
> @@ -454,6 +518,9 @@ int main(int argc, char **argv)
> if (stat[i].values)
> free(stat[i].values);
> }
> + if (strlen(outfile) != 0)
> + rt_write_json(outfile, argc, argv, write_stats, par);
> +
> free(stat);
> outpar:
> free(par);
> --
> 2.30.0
>
>
This has a number of conflicts due to me
not applying all of the changes to smp / numa
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 06/13] cyclicdeadline: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 06/13] cyclicdeadline: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/sched_deadline/cyclicdeadline.c | 72 ++++++++++++++++++++++-------
> 1 file changed, 56 insertions(+), 16 deletions(-)
>
> diff --git a/src/sched_deadline/cyclicdeadline.c b/src/sched_deadline/cyclicdeadline.c
> index 71cde5781499..ed3c960d9916 100644
> --- a/src/sched_deadline/cyclicdeadline.c
> +++ b/src/sched_deadline/cyclicdeadline.c
> @@ -18,6 +18,7 @@
> #include <errno.h>
> #include <signal.h>
> #include <getopt.h>
> +#include <inttypes.h>
>
> #include <sys/syscall.h>
> #include <sys/types.h>
> @@ -85,13 +86,11 @@ static pthread_barrier_t barrier;
>
> static int cpu_count;
> static int all_cpus;
> -
> static int nr_threads;
> static int use_nsecs;
> -
> static int mark_fd;
> -
> static int quiet;
> +static char outfile[MAX_PATH];
>
> static int find_mount(const char *mount, char *debugfs)
> {
> @@ -603,16 +602,17 @@ static void usage(int error)
> " tasks on. An empty CPUSET runs on all CPUs a deadline\n"
> " task.\n"
> " on CPU 4, and thread #5 on CPU 5.\n"
> - "-D TIME --duration Specify a length for the test run.\n"
> + "-D TIME --duration Specify a length for the test run.\n"
> " Append 'm', 'h', or 'd' to specify minutes, hours or\n"
> " days\n"
> - "-h --help Show this help menu.\n"
> - "-i INTV --interval The shortest deadline for the tasks in us\n"
> + "-h --help Show this help menu.\n"
> + "-i INTV --interval The shortest deadline for the tasks in us\n"
> " (default 1000us).\n"
> - "-s STEP --step The amount to increase the deadline for each task in us\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> + "-s STEP --step The amount to increase the deadline for each task in us\n"
> " (default 500us).\n"
> - "-t NUM --threads The number of threads to run as deadline (default 1).\n"
> - "-q --quiet print a summary only on exit\n"
> + "-t NUM --threads The number of threads to run as deadline (default 1).\n"
> + "-q --quiet print a summary only on exit\n"
> );
> exit(error);
> }
> @@ -966,6 +966,32 @@ static void loop(struct sched_data *sched_data, int nr_threads)
> }
> }
>
> +static void write_stats(FILE *f, void *data)
> +{
> + struct sched_data *sd = data;
> + struct thread_stat *s;
> + unsigned int i;
> +
> + fprintf(f, " \"num_threads\": %d,\n", nr_threads);
> + fprintf(f, " \"resolution_in_ns\": %u,\n", use_nsecs);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < nr_threads; i++) {
> + s = &sd[i].stat;
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"cycles\": %" PRIu64 ",\n", s->cycles);
> + fprintf(f, " \"min\": %" PRIu64 ",\n", s->min);
> + fprintf(f, " \"max\": %" PRIu64 ",\n", s->max);
> + fprintf(f, " \"avg\": %.2f\n", s->avg/s->cycles);
> + fprintf(f, " }%s\n", i == nr_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> +enum options_valud {
> + OPT_AFFINITY=1, OPT_DURATION, OPT_HELP, OPT_INTERVAL,
> + OPT_OUTPUT, OPT_STEP, OPT_THREADS, OPT_QUIET
> +};
> +
> int main(int argc, char **argv)
> {
> struct sched_data *sched_data;
> @@ -992,19 +1018,21 @@ int main(int argc, char **argv)
>
> for (;;) {
> static struct option options[] = {
> - { "affinity", optional_argument, NULL, 'a' },
> - { "duration", required_argument, NULL, 'D' },
> - { "help", no_argument, NULL, 'h' },
> - { "interval", required_argument, NULL, 'i' },
> - { "step", required_argument, NULL, 's' },
> - { "threads", required_argument, NULL, 't' },
> - { "quiet", no_argument, NULL, 'q' },
> + { "affinity", optional_argument, NULL, OPT_AFFINITY },
> + { "duration", required_argument, NULL, OPT_DURATION },
> + { "help", no_argument, NULL, OPT_HELP },
> + { "interval", required_argument, NULL, OPT_INTERVAL },
> + { "output", required_argument, NULL, OPT_OUTPUT },
> + { "step", required_argument, NULL, OPT_STEP },
> + { "threads", required_argument, NULL, OPT_THREADS },
> + { "quiet", no_argument, NULL, OPT_QUIET },
> { NULL, 0, NULL, 0 },
> };
> c = getopt_long(argc, argv, "a::c:D:hi:s:t:q", options, NULL);
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> case 'c':
> if (!nr_threads)
> @@ -1016,21 +1044,30 @@ int main(int argc, char **argv)
> else
> all_cpus = 1;
> break;
> + case OPT_INTERVAL:
> case 'i':
> interval = atoi(optarg);
> break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_STEP:
> case 's':
> step = atoi(optarg);
> break;
> + case OPT_THREADS:
> case 't':
> nr_threads = atoi(optarg);
> break;
> + case OPT_DURATION:
> case 'D':
> duration = parse_time_string(optarg);
> break;
> + case OPT_QUIET:
> case 'q':
> quiet = 1;
> break;
> + case OPT_HELP:
> case 'h':
> usage(0);
> break;
> @@ -1190,6 +1227,9 @@ int main(int argc, char **argv)
> }
> }
>
> + if (strlen(outfile) != 0)
> + rt_write_json(outfile, argc, argv, write_stats, sched_data);
> +
> if (setcpu_buf)
> free(setcpu_buf);
> free(thread);
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 07/13] pmqtest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 07/13] pmqtest: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/pmqtest/pmqtest.c | 137 +++++++++++++++++++++++++++++++++++-------
> 1 file changed, 114 insertions(+), 23 deletions(-)
>
> diff --git a/src/pmqtest/pmqtest.c b/src/pmqtest/pmqtest.c
> index 349b47741003..e1f59836ea07 100644
> --- a/src/pmqtest/pmqtest.c
> +++ b/src/pmqtest/pmqtest.c
> @@ -22,6 +22,7 @@
> #include <utmpx.h>
> #include <mqueue.h>
> #include <pthread.h>
> +#include <inttypes.h>
>
> #include "rt-utils.h"
> #include "rt-get_cpu.h"
> @@ -231,6 +232,7 @@ static void display_help(int error)
> "-h --help print this help message\n"
> "-i INTV --interval=INTV base interval of thread in us default=1000\n"
> "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --prio=PRIO priority\n"
> "-q --quiet print a summary only on exit\n"
> "-S --smp SMP testing: options -a -t and same priority\n"
> @@ -258,6 +260,14 @@ static int sameprio;
> static int timeout;
> static int forcetimeout;
> static int quiet;
> +static char outfile[MAX_PATH];
> +
> +enum option_value {
> + OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
> + OPT_FORCETIMEOUT, OPT_HELP, OPT_INTERVAL, OPT_LOOPS,
> + OPT_OUTPUT, OPT_PRIORITY, OPT_QUIET, OPT_SMP, OPT_THREADS,
> + OPT_TIMEOUT
> +};
>
> static void process_options(int argc, char *argv[])
> {
> @@ -268,19 +278,20 @@ static void process_options(int argc, char *argv[])
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"affinity", optional_argument, NULL, 'a'},
> - {"breaktrace", required_argument, NULL, 'b'},
> - {"distance", required_argument, NULL, 'd'},
> - {"duration", required_argument, NULL, 'D'},
> - {"forcetimeout", required_argument, NULL, 'f'},
> - {"help", no_argument, NULL, 'h'},
> - {"interval", required_argument, NULL, 'i'},
> - {"loops", required_argument, NULL, 'l'},
> - {"priority", required_argument, NULL, 'p'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"smp", no_argument, NULL, 'S'},
> - {"threads", optional_argument, NULL, 't'},
> - {"timeout", required_argument, NULL, 'T'},
> + {"affinity", optional_argument, NULL, OPT_AFFINITY},
> + {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
> + {"distance", required_argument, NULL, OPT_DISTANCE},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"forcetimeout",required_argument, NULL, OPT_FORCETIMEOUT},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"interval", required_argument, NULL, OPT_INTERVAL},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"output", required_argument, NULL, OPT_OUTPUT },
> + {"priority", required_argument, NULL, OPT_PRIORITY},
> + {"quiet", no_argument, NULL, OPT_QUIET},
> + {"smp", no_argument, NULL, OPT_SMP},
> + {"threads", optional_argument, NULL, OPT_THREADS},
> + {"timeout", required_argument, NULL, OPT_TIMEOUT},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long (argc, argv, "a::b:d:D:f:i:l:p:qSt::T:",
> @@ -288,6 +299,7 @@ static void process_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> if (smp) {
> warn("-a ignored due to --smp\n");
> @@ -303,21 +315,53 @@ static void process_options(int argc, char *argv[])
> setaffinity = AFFINITY_USEALL;
> }
> break;
> - case 'b': tracelimit = atoi(optarg); break;
> - case 'd': distance = atoi(optarg); break;
> - case 'D': duration = parse_time_string(optarg); break;
> - case 'f': forcetimeout = atoi(optarg); break;
> + case OPT_BREAKTRACE:
> + case 'b':
> + tracelimit = atoi(optarg);
> + break;
> + case OPT_DISTANCE:
> + case 'd':
> + distance = atoi(optarg);
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_FORCETIMEOUT:
> + case 'f':
> + forcetimeout = atoi(optarg);
> + break;
> + case OPT_HELP:
> case '?':
> - case 'h': display_help(0); break;
> - case 'i': interval = atoi(optarg); break;
> - case 'l': max_cycles = atoi(optarg); break;
> - case 'p': priority = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> + case 'h':
> + display_help(0);
> + break;
> + case OPT_INTERVAL:
> + case 'i':
> + interval = atoi(optarg);
> + break;
> + case OPT_LOOPS:
> + case 'l':
> + max_cycles = atoi(optarg);
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIORITY:
> + case 'p':
> + priority = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_SMP:
> case 'S':
> smp = 1;
> num_threads = max_cpus;
> setaffinity = AFFINITY_USEALL;
> break;
> + case OPT_THREADS:
> case 't':
> if (smp) {
> warn("-t ignored due to --smp\n");
> @@ -330,7 +374,10 @@ static void process_options(int argc, char *argv[])
> else
> num_threads = max_cpus;
> break;
> - case 'T': timeout = atoi(optarg); break;
> + case OPT_TIMEOUT:
> + case 'T':
> + timeout = atoi(optarg);
> + break;
> default:
> display_help(1);
> break;
> @@ -401,6 +448,42 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
> }
> }
>
> +struct params_stats {
> + struct params *receiver;
> + struct params *sender;
> +};
> +
> +static void write_stats(FILE *f, void *data)
> +{
> + struct params_stats *ps = data;
> + struct params *s, *r;
> + unsigned int i;
> +
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + s = &ps->sender[i];
> + r = &ps->receiver[i];
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"sender\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", s->cpu);
> + fprintf(f, " \"priority\": %d,\n", s->priority);
> + fprintf(f, " \"samples\": %d,\n", s->samples);
> + fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
> + fprintf(f, " },\n");
> + fprintf(f, " \"receiver\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", r->cpu);
> + fprintf(f, " \"priority\": %d,\n", r->priority);
> + fprintf(f, " \"timeoutcount\": %d,\n", r->timeoutcount);
> + fprintf(f, " \"min\": %d,\n", r->mindiff);
> + fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
> + fprintf(f, " \"max\": %d\n", r->maxdiff);
> + fprintf(f, " }\n");
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> int main(int argc, char *argv[])
> {
> int i;
> @@ -562,6 +645,14 @@ int main(int argc, char *argv[])
> mq_unlink(mqname);
> }
>
> + if (strlen(outfile) != 0) {
> + struct params_stats ps = {
> + .receiver = receiver,
> + .sender = sender,
> + };
> + rt_write_json(outfile, argc, argv, write_stats, &ps);
> + }
> +
> nomem:
>
> return 0;
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 08/13] ptsematest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 08/13] ptsematest: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/ptsematest/ptsematest.c | 120 ++++++++++++++++++++++++++++++------
> 1 file changed, 101 insertions(+), 19 deletions(-)
>
> diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c
> index 7d4ca97773d6..2755bfde5210 100644
> --- a/src/ptsematest/ptsematest.c
> +++ b/src/ptsematest/ptsematest.c
> @@ -20,6 +20,7 @@
> #include <linux/unistd.h>
> #include <utmpx.h>
> #include <pthread.h>
> +#include <inttypes.h>
>
> #include "rt-utils.h"
> #include "rt-get_cpu.h"
> @@ -155,6 +156,7 @@ static void display_help(int error)
> " days.\n"
> "-i INTV --interval=INTV base interval of thread in us default=1000\n"
> "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --prio=PRIO priority\n"
> "-q --quiet print a summary only on exit\n"
> "-S --smp SMP testing: options -a -t and same priority\n"
> @@ -180,6 +182,13 @@ static int distance = 500;
> static int smp;
> static int sameprio;
> static int quiet;
> +static char outfile[MAX_PATH];
> +
> +enum option_value {
> + OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
> + OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT, OPT_PRIORITY,
> + OPT_QUIET, OPT_SMP, OPT_THREADS
> +};
>
> static void process_options(int argc, char *argv[])
> {
> @@ -190,17 +199,18 @@ static void process_options(int argc, char *argv[])
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"affinity", optional_argument, NULL, 'a'},
> - {"breaktrace", required_argument, NULL, 'b'},
> - {"distance", required_argument, NULL, 'd'},
> - {"duration", required_argument, NULL, 'D'},
> - {"help", no_argument, NULL, 'h'},
> - {"interval", required_argument, NULL, 'i'},
> - {"loops", required_argument, NULL, 'l'},
> - {"priority", required_argument, NULL, 'p'},
> - {"quiet", no_argument , NULL, 'q'},
> - {"smp", no_argument, NULL, 'S'},
> - {"threads", optional_argument, NULL, 't'},
> + {"affinity", optional_argument, NULL, OPT_AFFINITY},
> + {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
> + {"distance", required_argument, NULL, OPT_DISTANCE},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"interval", required_argument, NULL, OPT_INTERVAL},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"output", required_argument, NULL, OPT_OUTPUT },
> + {"priority", required_argument, NULL, OPT_PRIORITY},
> + {"quiet", no_argument , NULL, OPT_QUIET},
> + {"smp", no_argument, NULL, OPT_SMP},
> + {"threads", optional_argument, NULL, OPT_THREADS},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long (argc, argv, "a::b:d:i:l:D:p:qSt::h",
> @@ -208,6 +218,7 @@ static void process_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> if (smp) {
> warn("-a ignored due to --smp\n");
> @@ -223,20 +234,49 @@ static void process_options(int argc, char *argv[])
> setaffinity = AFFINITY_USEALL;
> }
> break;
> - case 'b': tracelimit = atoi(optarg); break;
> - case 'd': distance = atoi(optarg); break;
> - case 'D': duration = parse_time_string(optarg); break;
> - case 'i': interval = atoi(optarg); break;
> + case OPT_BREAKTRACE:
> + case 'b':
> + tracelimit = atoi(optarg);
> + break;
> + case OPT_DISTANCE:
> + case 'd':
> + distance = atoi(optarg);
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_INTERVAL:
> + case 'i':
> + interval = atoi(optarg);
> + break;
> + case OPT_HELP:
> case '?':
> - case 'h': display_help(0); break;
> - case 'l': max_cycles = atoi(optarg); break;
> - case 'p': priority = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> + case 'h':
> + display_help(0);
> + break;
> + case OPT_LOOPS:
> + case 'l':
> + max_cycles = atoi(optarg);
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIORITY:
> + case 'p':
> + priority = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_SMP:
> case 'S':
> smp = 1;
> num_threads = max_cpus;
> setaffinity = AFFINITY_USEALL;
> break;
> + case OPT_THREADS:
> case 't':
> if (smp) {
> warn("-t ignored due to --smp\n");
> @@ -316,6 +356,40 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
> }
> }
>
> +struct params_stats {
> + struct params *receiver;
> + struct params *sender;
> +};
> +
> +static void write_stats(FILE *f, void *data)
> +{
> + struct params_stats *ps = data;
> + struct params *s, *r;
> + unsigned int i;
> +
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + s = &ps->sender[i];
> + r = &ps->receiver[i];
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"sender\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", s->cpu);
> + fprintf(f, " \"priority\": %d,\n", s->priority);
> + fprintf(f, " \"samples\": %d,\n", s->samples);
> + fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
> + fprintf(f, " },\n");
> + fprintf(f, " \"receiver\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", r->cpu);
> + fprintf(f, " \"priority\": %d,\n", r->priority);
> + fprintf(f, " \"min\": %d,\n", r->mindiff);
> + fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
> + fprintf(f, " \"max\": %d\n", r->maxdiff);
> + fprintf(f, " }\n");
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
>
> int main(int argc, char *argv[])
> {
> @@ -439,6 +513,14 @@ int main(int argc, char *argv[])
> pthread_mutex_destroy(&syncmutex[i]);
> }
>
> + if (strlen(outfile) != 0) {
> + struct params_stats ps = {
> + .receiver = receiver,
> + .sender = sender,
> + };
> + rt_write_json(outfile, argc, argv, write_stats, &ps);
> + }
> +
> nomem:
>
> return 0;
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 09/13] sigwaittest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 09/13] sigwaittest: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/signaltest/signaltest.c | 1 +
> src/sigwaittest/sigwaittest.c | 117 ++++++++++++++++++++++++++++------
> 2 files changed, 100 insertions(+), 18 deletions(-)
>
> diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
> index 09039b299367..b1a71efdf42f 100644
> --- a/src/signaltest/signaltest.c
> +++ b/src/signaltest/signaltest.c
> @@ -361,6 +361,7 @@ static void write_stats(FILE *f, void *data)
> struct thread_stat *s;
> unsigned int i;
>
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> fprintf(f, " \"thread\": {\n");
> for (i = 0; i < num_threads; i++) {
> fprintf(f, " \"%u\": {\n", i);
> diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c
> index f10c24914d4a..0cdf30a6a769 100644
> --- a/src/sigwaittest/sigwaittest.c
> +++ b/src/sigwaittest/sigwaittest.c
> @@ -39,6 +39,7 @@
> #include <linux/unistd.h>
> #include <utmpx.h>
> #include <pthread.h>
> +#include <inttypes.h>
>
> #include "rt-utils.h"
> #include "rt-get_cpu.h"
> @@ -220,6 +221,7 @@ static void display_help(int error)
> "-f [OPT] --fork[=OPT] fork new processes instead of creating threads\n"
> "-i INTV --interval=INTV base interval of thread in us default=1000\n"
> "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --prio=PRIO priority\n"
> "-q --quiet print a summary only on exit\n"
> "-t --threads one thread per available processor\n"
> @@ -240,6 +242,13 @@ static int duration;
> static int interval = 1000;
> static int distance = 500;
> static int quiet;
> +static char outfile[MAX_PATH];
> +
> +enum option_value {
> + OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
> + OPT_FORK, OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT,
> + OPT_PRIORITY, OPT_QUIET, OPT_THREADS
> +};
>
> static void process_options(int argc, char *argv[])
> {
> @@ -251,17 +260,18 @@ static void process_options(int argc, char *argv[])
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"affinity", optional_argument, NULL, 'a'},
> - {"breaktrace", required_argument, NULL, 'b'},
> - {"distance", required_argument, NULL, 'd'},
> - {"duration", required_argument, NULL, 'D'},
> - {"fork", optional_argument, NULL, 'f'},
> - {"help", no_argument, NULL, 'h'},
> - {"interval", required_argument, NULL, 'i'},
> - {"loops", required_argument, NULL, 'l'},
> - {"priority", required_argument, NULL, 'p'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"threads", optional_argument, NULL, 't'},
> + {"affinity", optional_argument, NULL, OPT_AFFINITY},
> + {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
> + {"distance", required_argument, NULL, OPT_DISTANCE},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"fork", optional_argument, NULL, OPT_FORK},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"interval", required_argument, NULL, OPT_INTERVAL},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"output", required_argument, NULL, OPT_OUTPUT },
> + {"priority", required_argument, NULL, OPT_PRIORITY},
> + {"quiet", no_argument, NULL, OPT_QUIET},
> + {"threads", optional_argument, NULL, OPT_THREADS},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long (argc, argv, "a::b:d:D:f::hi:l:p:qt::",
> @@ -269,6 +279,7 @@ static void process_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> if (optarg != NULL) {
> affinity = atoi(optarg);
> @@ -280,9 +291,19 @@ static void process_options(int argc, char *argv[])
> setaffinity = AFFINITY_USEALL;
> }
> break;
> - case 'b': thistracelimit = atoi(optarg); break;
> - case 'd': distance = atoi(optarg); break;
> - case 'D': duration = parse_time_string(optarg); break;
> + case OPT_BREAKTRACE:
> + case 'b':
> + thistracelimit = atoi(optarg);
> + break;
> + case OPT_DISTANCE:
> + case 'd':
> + distance = atoi(optarg);
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_FORK:
> case 'f':
> if (optarg != NULL) {
> wasforked = 1;
> @@ -294,14 +315,31 @@ static void process_options(int argc, char *argv[])
> } else
> mustfork = 1;
> break;
> + case OPT_HELP:
> case '?':
> case 'h':
> display_help(0);
> break;
> - case 'i': interval = atoi(optarg); break;
> - case 'l': max_cycles = atoi(optarg); break;
> - case 'p': priority = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> + case OPT_INTERVAL:
> + case 'i':
> + interval = atoi(optarg);
> + break;
> + case OPT_LOOPS:
> + case 'l':
> + max_cycles = atoi(optarg);
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIORITY:
> + case 'p':
> + priority = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_THREADS:
> case 't':
> if (optarg != NULL)
> num_threads = atoi(optarg);
> @@ -388,6 +426,41 @@ static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
> }
> }
>
> +struct params_stats {
> + struct params *receiver;
> + struct params *sender;
> +};
> +
> +static void write_stats(FILE *f, void *data)
> +{
> + struct params_stats *ps = data;
> + struct params *s, *r;
> + unsigned int i;
> +
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + s = &ps->sender[i];
> + r = &ps->receiver[i];
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"sender\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", s->cpu);
> + fprintf(f, " \"priority\": %d,\n", s->priority);
> + fprintf(f, " \"samples\": %d,\n", s->samples);
> + fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
> + fprintf(f, " },\n");
> + fprintf(f, " \"receiver\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", r->cpu);
> + fprintf(f, " \"priority\": %d,\n", r->priority);
> + fprintf(f, " \"min\": %d,\n", r->mindiff);
> + fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
> + fprintf(f, " \"max\": %d\n", r->maxdiff);
> + fprintf(f, " }\n");
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> int main(int argc, char *argv[])
> {
> int i, totalsize = 0;
> @@ -627,6 +700,14 @@ int main(int argc, char *argv[])
> }
> }
>
> + if (strlen(outfile) != 0) {
> + struct params_stats ps = {
> + .receiver = receiver,
> + .sender = sender,
> + };
> + rt_write_json(outfile, argc, argv, write_stats, &ps);
> + }
> +
> nomem:
> if (mustfork) {
> munmap(param, totalsize);
> --
> 2.30.0
>
>
Doesn't apply
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 10/13] svsematest: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 10/13] svsematest: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/svsematest/svsematest.c | 124 ++++++++++++++++++++++++++++++------
> 1 file changed, 104 insertions(+), 20 deletions(-)
>
> diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c
> index 7a298e0dea8c..23f84bcbd3dc 100644
> --- a/src/svsematest/svsematest.c
> +++ b/src/svsematest/svsematest.c
> @@ -20,6 +20,7 @@
> #include <string.h>
> #include <time.h>
> #include <utmpx.h>
> +#include <inttypes.h>
>
> #include <linux/unistd.h>
>
> @@ -233,6 +234,7 @@ static void display_help(int error)
> "-f [OPT] --fork[=OPT] fork new processes instead of creating threads\n"
> "-i INTV --interval=INTV base interval of thread in us default=1000\n"
> "-l LOOPS --loops=LOOPS number of loops: default=0(endless)\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --prio=PRIO priority\n"
> "-S --smp SMP testing: options -a -t and same priority\n"
> " of all threads\n"
> @@ -255,6 +257,13 @@ static int distance = 500;
> static int smp;
> static int sameprio;
> static int quiet;
> +static char outfile[MAX_PATH];
> +
> +enum option_value {
> + OPT_AFFINITY=1, OPT_BREAKTRACE, OPT_DISTANCE, OPT_DURATION,
> + OPT_FORK, OPT_HELP, OPT_INTERVAL, OPT_LOOPS, OPT_OUTPUT,
> + OPT_PRIORITY, OPT_QUIET, OPT_SMP, OPT_THREADS
> +};
>
> static void process_options(int argc, char *argv[])
> {
> @@ -266,18 +275,19 @@ static void process_options(int argc, char *argv[])
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"affinity", optional_argument, NULL, 'a'},
> - {"breaktrace", required_argument, NULL, 'b'},
> - {"distance", required_argument, NULL, 'd'},
> - {"duration", required_argument, NULL, 'D'},
> - {"fork", optional_argument, NULL, 'f'},
> - {"help", no_argument, NULL, 'h'},
> - {"interval", required_argument, NULL, 'i'},
> - {"loops", required_argument, NULL, 'l'},
> - {"priority", required_argument, NULL, 'p'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"smp", no_argument, NULL, 'S'},
> - {"threads", optional_argument, NULL, 't'},
> + {"affinity", optional_argument, NULL, OPT_AFFINITY},
> + {"breaktrace", required_argument, NULL, OPT_BREAKTRACE},
> + {"distance", required_argument, NULL, OPT_DISTANCE},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"fork", optional_argument, NULL, OPT_FORK},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"interval", required_argument, NULL, OPT_INTERVAL},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"output", required_argument, NULL, OPT_OUTPUT},
> + {"priority", required_argument, NULL, OPT_PRIORITY},
> + {"quiet", no_argument, NULL, OPT_QUIET},
> + {"smp", no_argument, NULL, OPT_SMP},
> + {"threads", optional_argument, NULL, OPT_THREADS},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long (argc, argv, "a::b:d:D:f::hi:l:p:qSt::",
> @@ -285,6 +295,7 @@ static void process_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> + case OPT_AFFINITY:
> case 'a':
> if (smp) {
> warn("-a ignored due to --smp\n");
> @@ -300,9 +311,19 @@ static void process_options(int argc, char *argv[])
> setaffinity = AFFINITY_USEALL;
> }
> break;
> - case 'b': thistracelimit = atoi(optarg); break;
> - case 'd': distance = atoi(optarg); break;
> - case 'D': duration = parse_time_string(optarg); break;
> + case OPT_BREAKTRACE:
> + case 'b':
> + thistracelimit = atoi(optarg);
> + break;
> + case OPT_DISTANCE:
> + case 'd':
> + distance = atoi(optarg);
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_FORK:
> case 'f':
> if (optarg != NULL) {
> wasforked = 1;
> @@ -314,16 +335,36 @@ static void process_options(int argc, char *argv[])
> } else
> mustfork = 1;
> break;
> - case 'h': display_help(0); break;
> - case 'i': interval = atoi(optarg); break;
> - case 'l': max_cycles = atoi(optarg); break;
> - case 'p': priority = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> + case OPT_HELP:
> + case 'h':
> + display_help(0);
> + break;
> + case OPT_INTERVAL:
> + case 'i':
> + interval = atoi(optarg);
> + break;
> + case OPT_LOOPS:
> + case 'l':
> + max_cycles = atoi(optarg);
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIORITY:
> + case 'p':
> + priority = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_SMP:
> case 'S':
> smp = 1;
> num_threads = max_cpus;
> setaffinity = AFFINITY_USEALL;
> break;
> + case OPT_THREADS:
> case 't':
> if (smp) {
> warn("-t ignored due to --smp\n");
> @@ -380,6 +421,41 @@ static void sighand(int sig)
> mustshutdown = 1;
> }
>
> +struct params_stats {
> + struct params *receiver;
> + struct params *sender;
> +};
> +
> +static void write_stats(FILE *f, void *data)
> +{
> + struct params_stats *ps = data;
> + struct params *s, *r;
> + unsigned int i;
> +
> + fprintf(f, " \"num_threads\": %d,\n", num_threads);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < num_threads; i++) {
> + s = &ps->sender[i];
> + r = &ps->receiver[i];
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"sender\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", s->cpu);
> + fprintf(f, " \"priority\": %d,\n", s->priority);
> + fprintf(f, " \"samples\": %d,\n", s->samples);
> + fprintf(f, " \"interval\": %ld\n", r->delay.tv_nsec/1000);
> + fprintf(f, " },\n");
> + fprintf(f, " \"receiver\": {\n");
> + fprintf(f, " \"cpu\": %d,\n", r->cpu);
> + fprintf(f, " \"priority\": %d,\n", r->priority);
> + fprintf(f, " \"min\": %d,\n", r->mindiff);
> + fprintf(f, " \"avg\": %.2f,\n", r->sumdiff/r->samples);
> + fprintf(f, " \"max\": %d\n", r->maxdiff);
> + fprintf(f, " }\n");
> + fprintf(f, " }%s\n", i == num_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> static void print_stat(FILE *fp, struct params *receiver, struct params *sender,
> int verbose, int quiet)
> {
> @@ -696,6 +772,14 @@ int main(int argc, char *argv[])
> }
> }
>
> + if (strlen(outfile) != 0) {
> + struct params_stats ps = {
> + .receiver = receiver,
> + .sender = sender,
> + };
> + rt_write_json(outfile, argc, argv, write_stats, &ps);
> + }
> +
> nosem:
> for (i = 0; i < num_threads; i++)
> semctl(receiver[i].semid, -1, IPC_RMID);
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 11/13] oslat: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 11/13] oslat: " Daniel Wagner
@ 2021-02-17 3:51 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:51 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/oslat/oslat.c | 97 +++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 82 insertions(+), 15 deletions(-)
>
> diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
> index 9e6f70600830..987f2002985d 100644
> --- a/src/oslat/oslat.c
> +++ b/src/oslat/oslat.c
> @@ -29,7 +29,7 @@
> #include <numa.h>
> #include <math.h>
> #include <limits.h>
> -#include <linux/unistd.h>
> +#include <inttypes.h>
>
> #include <sys/prctl.h>
> #include <sys/stat.h>
> @@ -41,6 +41,8 @@
> #include <sys/mman.h>
> #include <sys/syscall.h>
>
> +#include <linux/unistd.h>
> +
> #include "rt-utils.h"
> #include "rt-numa.h"
> #include "rt-error.h"
> @@ -171,6 +173,7 @@ struct global {
> uint64_t bias;
> int single_preheat_thread;
> int output_omit_zero_buckets;
> + char outfile[MAX_PATH];
>
> /* Mutable state. */
> volatile enum command cmd;
> @@ -479,6 +482,39 @@ static void write_summary(struct thread *t)
> printf("\n");
> }
>
> +static void write_summary_json(FILE *f, void *data)
> +{
> + struct thread *t = data;
> + int i, j, comma;
> +
> + fprintf(f, " \"num_threads\": %d,\n", g.n_threads);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < g.n_threads; ++i) {
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"cpu\": %d,\n", t[i].core_i);
> + fprintf(f, " \"freq\": %d,\n", t[i].cpu_mhz);
> + fprintf(f, " \"min\": %" PRIu64 ",\n", t[i].minlat);
> + fprintf(f, " \"avg\": %3lf,\n", t[i].average);
> + fprintf(f, " \"max\": %" PRIu64 ",\n", t[i].maxlat);
> + fprintf(f, " \"duration\": %.3f,\n",
> + cycles_to_sec(&(t[i]), t[i].runtime));
> + fprintf(f, " \"histogram\": {");
> + for (j = 0, comma = 0; j < g.bucket_size; j++) {
> + if (t[i].buckets[j] == 0)
> + continue;
> + fprintf(f, "%s", comma ? ",\n" : "\n");
> + fprintf(f, " \"%" PRIu64 "\": %" PRIu64,
> + g.bias+j+1, t[i].buckets[j]);
> + comma = 1;
> + }
> + if (comma)
> + fprintf(f, "\n");
> + fprintf(f, " }\n");
> + fprintf(f, " }%s\n", i == g.n_threads - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> static void run_expt(struct thread *threads, int runtime_secs)
> {
> int i;
> @@ -533,6 +569,7 @@ static void usage(int error)
> " NOTE: please make sure the CPU frequency on all testing cores\n"
> " are locked before using this parmater. If you don't know how\n"
> " to lock the freq then please don't use this parameter.\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-T, --trace-threshold Stop the test when threshold triggered (in us),\n"
> " print a marker in ftrace and stop ftrace too.\n"
> "-v, --version Display the version of the software.\n"
> @@ -557,34 +594,45 @@ static int workload_select(char *name)
> return -1;
> }
>
> +enum option_value {
> + OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
> + OPT_DURATION, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH,
> + OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, OPT_OUTPUT,
> + OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, OPT_VERSION
> +
> +};
> +
> /* Process commandline options */
> static void parse_options(int argc, char *argv[])
> {
> while (1) {
> + int option_index = 0;
> static struct option options[] = {
> - { "bucket-size", required_argument, NULL, 'b' },
> - { "cpu-list", required_argument, NULL, 'c' },
> - { "cpu-main-thread", required_argument, NULL, 'C'},
> - { "duration", required_argument, NULL, 'D' },
> - { "rtprio", required_argument, NULL, 'f' },
> - { "help", no_argument, NULL, 'h' },
> - { "trace-threshold", required_argument, NULL, 'T' },
> - { "workload", required_argument, NULL, 'w'},
> - { "workload-mem", required_argument, NULL, 'm'},
> - { "bias", no_argument, NULL, 'B'},
> - { "single-preheat", no_argument, NULL, 's'},
> - { "zero-omit", no_argument, NULL, 'u'},
> - { "version", no_argument, NULL, 'v'},
> + { "bucket-size",required_argument, NULL, OPT_BUCKETSIZE },
> + { "cpu-list", required_argument, NULL, OPT_CPU_LIST },
> + { "cpu-main-thread", required_argument, NULL, OPT_CPU_MAIN_THREAD},
> + { "duration", required_argument, NULL, OPT_DURATION },
> + { "rtprio", required_argument, NULL, OPT_RT_PRIO },
> + { "help", no_argument, NULL, OPT_HELP },
> + { "trace-threshold", required_argument, NULL, OPT_TRACE_TH },
> + { "workload", required_argument, NULL, OPT_WORKLOAD },
> + { "workload-mem", required_argument, NULL, OPT_WORKLOAD_MEM },
> + { "bias", no_argument, NULL, OPT_BIAS },
> + { "single-preheat", no_argument, NULL, OPT_SINGLE_PREHEAT },
> + { "output", required_argument, NULL, OPT_OUTPUT },
> + { "zero-omit", no_argument, NULL, OPT_ZERO_OMIT },
> + { "version", no_argument, NULL, OPT_VERSION },
> { NULL, 0, NULL, 0 },
> };
> int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:sw:T:vz",
> - options, NULL);
> + options, &option_index);
> long ncores;
>
> if (c == -1)
> break;
>
> switch (c) {
> + case OPT_BUCKETSIZE:
> case 'b':
> g.bucket_size = strtol(optarg, NULL, 10);
> if (g.bucket_size > 1024 || g.bucket_size <= 4) {
> @@ -593,12 +641,15 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_BIAS:
> case 'B':
> g.enable_bias = 1;
> break;
> + case OPT_CPU_LIST:
> case 'c':
> g.cpu_list = strdup(optarg);
> break;
> + case OPT_CPU_MAIN_THREAD:
> case 'C':
> ncores = sysconf(_SC_NPROCESSORS_CONF);
> g.cpu_main_thread = strtol(optarg, NULL, 10);
> @@ -608,6 +659,7 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_DURATION:
> case 'D':
> g.runtime = parse_time_string(optarg);
> if (!g.runtime) {
> @@ -615,6 +667,7 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_RT_PRIO:
> case 'f':
> g.rtprio = strtol(optarg, NULL, 10);
> if (g.rtprio < 1 || g.rtprio > 99) {
> @@ -622,6 +675,10 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_OUTPUT:
> + strncpy(g.outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_TRACE_TH:
> case 'T':
> g.trace_threshold = strtol(optarg, NULL, 10);
> if (g.trace_threshold <= 0) {
> @@ -630,6 +687,7 @@ static void parse_options(int argc, char *argv[])
> }
> enable_trace_mark();
> break;
> + case OPT_WORKLOAD:
> case 'w':
> if (workload_select(optarg)) {
> printf("Unknown workload '%s'. Please choose from: ", optarg);
> @@ -642,12 +700,14 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_WORKLOAD_MEM:
> case 'm':
> if (parse_mem_string(optarg, &g.workload_mem_size)) {
> printf("Unknown workload memory size '%s'.\n\n", optarg);
> exit(1);
> }
> break;
> + case OPT_SINGLE_PREHEAT:
> case 's':
> /*
> * Only use one core for pre-heat. Then if --bias is used, the
> @@ -655,6 +715,7 @@ static void parse_options(int argc, char *argv[])
> */
> g.single_preheat_thread = true;
> break;
> + case OPT_VERSION:
> case 'v':
> /*
> * Because we always dump the version even before parsing options,
> @@ -662,9 +723,11 @@ static void parse_options(int argc, char *argv[])
> */
> exit(0);
> break;
> + case OPT_ZERO_OMIT:
> case 'z':
> g.output_omit_zero_buckets = 1;
> break;
> + case OPT_HELP:
> case 'h':
> usage(0);
> break;
> @@ -781,6 +844,10 @@ int main(int argc, char *argv[])
>
> write_summary(threads);
>
> + if (strlen(g.outfile) != 0)
> + rt_write_json(g.outfile, argc, argv,
> + write_summary_json, threads);
> +
> if (g.cpu_list) {
> free(g.cpu_list);
> g.cpu_list = NULL;
> --
> 2.30.0
>
>
- Added a space after a common parse_options
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 12/13] rt-migrate-test: Add JSON output feature
2021-02-10 17:51 ` [PATCH rt-tests v5 12/13] rt-migrate-test: " Daniel Wagner
@ 2021-02-17 3:52 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:52 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Write the test results as JSON output to a file. This allows to
> simplifies any parsing later on.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/rt-migrate-test/rt-migrate-test.c | 120 ++++++++++++++++++++++----
> 1 file changed, 101 insertions(+), 19 deletions(-)
>
> diff --git a/src/rt-migrate-test/rt-migrate-test.c b/src/rt-migrate-test/rt-migrate-test.c
> index 9bf716c9178c..56b7b66ccdf4 100644
> --- a/src/rt-migrate-test/rt-migrate-test.c
> +++ b/src/rt-migrate-test/rt-migrate-test.c
> @@ -19,11 +19,14 @@
> #include <fcntl.h>
> #include <signal.h>
> #include <sys/time.h>
> -#include <linux/unistd.h>
> #include <sys/syscall.h>
> #include <errno.h>
> #include <sched.h>
> #include <pthread.h>
> +#include <inttypes.h>
> +
> +#include <linux/unistd.h>
> +
> #include "rt-utils.h"
>
> int nr_tasks;
> @@ -99,6 +102,7 @@ static int done;
> static int loop;
> static int duration;
> static int quiet;
> +static char outfile[MAX_PATH];
>
> static pthread_barrier_t start_barrier;
> static pthread_barrier_t end_barrier;
> @@ -160,6 +164,7 @@ static void usage(int error)
> "-h --help Print this help message\n"
> "-l LOOPS --loops=LOOPS Number of iterations to run (50)\n"
> "-m TIME --maxerr=TIME Max allowed error (microsecs)\n"
> + " --output=FILENAME write final results into FILENAME, JSON formatted\n"
> "-p PRIO --prio=PRIO base priority to start RT tasks with (2)\n"
> "-q --quiet print a summary only on exit\n"
> "-r TIME --run-time=TIME Run time (ms) to busy loop the threads (20)\n"
> @@ -169,22 +174,29 @@ static void usage(int error)
> exit(error);
> }
>
> +enum option_value {
> + OPT_CHECK=1, OPT_DURATION, OPT_EQUAL, OPT_HELP, OPT_LOOPS,
> + OPT_MAXERR, OPT_OUTPUT, OPT_PRIO, OPT_QUIET, OPT_RUN_TIME,
> + OPT_SLEEP_TIME
> +};
> +
> static void parse_options(int argc, char *argv[])
> {
> for (;;) {
> int option_index = 0;
> /** Options for getopt */
> static struct option long_options[] = {
> - {"check", no_argument, NULL, 'c'},
> - {"duration", required_argument, NULL, 'D'},
> - {"equal", no_argument, NULL, 'e'},
> - {"help", no_argument, NULL, 'h'},
> - {"loops", required_argument, NULL, 'l'},
> - {"maxerr", required_argument, NULL, 'm'},
> - {"prio", required_argument, NULL, 'p'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"run-time", required_argument, NULL, 'r'},
> - {"sleep-time", required_argument, NULL, 's'},
> + {"check", no_argument, NULL, OPT_CHECK},
> + {"duration", required_argument, NULL, OPT_DURATION},
> + {"equal", no_argument, NULL, OPT_EQUAL},
> + {"help", no_argument, NULL, OPT_HELP},
> + {"loops", required_argument, NULL, OPT_LOOPS},
> + {"maxerr", required_argument, NULL, OPT_MAXERR},
> + {"output", required_argument, NULL, OPT_OUTPUT },
> + {"prio", required_argument, NULL, OPT_PRIO},
> + {"quiet", no_argument, NULL, OPT_QUIET},
> + {"run-time", required_argument, NULL, OPT_RUN_TIME},
> + {"sleep-time", required_argument, NULL, OPT_SLEEP_TIME},
> {NULL, 0, NULL, 0}
> };
> int c = getopt_long(argc, argv, "cD:ehl:m:p:qr:s:",
> @@ -192,21 +204,50 @@ static void parse_options(int argc, char *argv[])
> if (c == -1)
> break;
> switch (c) {
> - case 'c': check = 1; break;
> - case 'D': duration = parse_time_string(optarg); break;
> - case 'e': equal = 1; break;
> + case OPT_CHECK:
> + case 'c':
> + check = 1;
> + break;
> + case OPT_DURATION:
> + case 'D':
> + duration = parse_time_string(optarg);
> + break;
> + case OPT_EQUAL:
> + case 'e':
> + equal = 1;
> + break;
> + case OPT_HELP:
> case '?':
> case 'h':
> usage(0);
> break;
> - case 'l': nr_runs = atoi(optarg); break;
> - case 'm': max_err = usec2nano(atoi(optarg)); break;
> - case 'p': prio_start = atoi(optarg); break;
> - case 'q': quiet = 1; break;
> + case OPT_LOOPS:
> + case 'l':
> + nr_runs = atoi(optarg);
> + break;
> + case OPT_MAXERR:
> + case 'm':
> + max_err = usec2nano(atoi(optarg));
> + break;
> + case OPT_OUTPUT:
> + strncpy(outfile, optarg, strnlen(optarg, MAX_PATH-1));
> + break;
> + case OPT_PRIO:
> + case 'p':
> + prio_start = atoi(optarg);
> + break;
> + case OPT_QUIET:
> + case 'q':
> + quiet = 1;
> + break;
> + case OPT_RUN_TIME:
> case 'r':
> run_interval = atoi(optarg);
> break;
> - case 's': interval = atoi(optarg); break;
> + case OPT_SLEEP_TIME:
> + case 's':
> + interval = atoi(optarg);
> + break;
> default:
> usage(1);
> }
> @@ -313,6 +354,44 @@ static void print_results(void)
> }
> }
>
> +static void write_stats(FILE *f, void *data)
> +{
> + int i;
> + int t;
> + unsigned long long tasks_max[nr_tasks];
> + unsigned long long tasks_min[nr_tasks];
> + unsigned long long tasks_avg[nr_tasks];
> +
> + memset(tasks_max, 0, sizeof(tasks_max[0])*nr_tasks);
> + memset(tasks_min, 0xff, sizeof(tasks_min[0])*nr_tasks);
> + memset(tasks_avg, 0, sizeof(tasks_avg[0])*nr_tasks);
> +
> + for (i=0; i < nr_runs; i++) {
> + for (t=0; t < nr_tasks; t++) {
> + unsigned long long itv = intervals[i][t];
> +
> + if (tasks_max[t] < itv)
> + tasks_max[t] = itv;
> + if (tasks_min[t] > itv)
> + tasks_min[t] = itv;
> + tasks_avg[t] += itv;
> + }
> + }
> +
> + fprintf(f, " \"num_threads\": %d,\n", nr_tasks);
> + fprintf(f, " \"thread\": {\n");
> + for (i = 0; i < nr_tasks; i++) {
> + fprintf(f, " \"%u\": {\n", i);
> + fprintf(f, " \"prio\": %d,\n", calc_prio(i));
> + fprintf(f, " \"min\": %lld,\n", nano2usec(tasks_min[i]));
> + fprintf(f, " \"avg\": %lld,\n", nano2usec(tasks_avg[i]) / nr_runs);
> + fprintf(f, " \"max\": %lld,\n", nano2usec(tasks_max[i]));
> + fprintf(f, " \"total\": %lld\n", nano2usec(tasks_avg[i]));
> + fprintf(f, " }%s\n", i == nr_tasks - 1 ? "" : ",");
> + }
> + fprintf(f, " }\n");
> +}
> +
> static unsigned long busy_loop(unsigned long long start_time)
> {
> unsigned long long time;
> @@ -582,6 +661,9 @@ int main (int argc, char **argv)
>
> print_results();
>
> + if (strlen(outfile) != 0)
> + rt_write_json(outfile, argc, argv, write_stats, NULL);
> +
> if (stop) {
> /*
> * We use this test in bash while loops
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 13/13] oslat: Add quiet command line option
2021-02-10 17:51 ` [PATCH rt-tests v5 13/13] oslat: Add quiet command line option Daniel Wagner
@ 2021-02-17 3:52 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:52 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> The quiet option is useful for automated test setups where
> only the final result of the run is interesting.
>
> Furthermore, this makes oslat accept rt-tests standard options.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/oslat/oslat.c | 25 ++++++++++++++++++-------
> 1 file changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c
> index 987f2002985d..0d9afedbdc82 100644
> --- a/src/oslat/oslat.c
> +++ b/src/oslat/oslat.c
> @@ -171,6 +171,7 @@ struct global {
> uint64_t workload_mem_size;
> int enable_bias;
> uint64_t bias;
> + int quiet;
> int single_preheat_thread;
> int output_omit_zero_buckets;
> char outfile[MAX_PATH];
> @@ -565,6 +566,7 @@ static void usage(int error)
> " Total memory usage will be this value multiplies 2*N,\n"
> " because there will be src/dst buffers for each thread, and\n"
> " N is the number of processors for testing.\n"
> + "-q --quiet print a summary only on exit\n"
> "-s, --single-preheat Use a single thread when measuring latency at preheat stage\n"
> " NOTE: please make sure the CPU frequency on all testing cores\n"
> " are locked before using this parmater. If you don't know how\n"
> @@ -598,8 +600,8 @@ enum option_value {
> OPT_BUCKETSIZE=1, OPT_CPU_LIST, OPT_CPU_MAIN_THREAD,
> OPT_DURATION, OPT_RT_PRIO, OPT_HELP, OPT_TRACE_TH,
> OPT_WORKLOAD, OPT_WORKLOAD_MEM, OPT_BIAS, OPT_OUTPUT,
> - OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT, OPT_VERSION
> -
> + OPT_QUIET, OPT_SINGLE_PREHEAT, OPT_ZERO_OMIT,
> + OPT_VERSION
> };
>
> /* Process commandline options */
> @@ -618,13 +620,14 @@ static void parse_options(int argc, char *argv[])
> { "workload", required_argument, NULL, OPT_WORKLOAD },
> { "workload-mem", required_argument, NULL, OPT_WORKLOAD_MEM },
> { "bias", no_argument, NULL, OPT_BIAS },
> + { "quiet", no_argument, NULL, OPT_QUIET },
> { "single-preheat", no_argument, NULL, OPT_SINGLE_PREHEAT },
> { "output", required_argument, NULL, OPT_OUTPUT },
> { "zero-omit", no_argument, NULL, OPT_ZERO_OMIT },
> { "version", no_argument, NULL, OPT_VERSION },
> { NULL, 0, NULL, 0 },
> };
> - int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:sw:T:vz",
> + int i, c = getopt_long(argc, argv, "b:Bc:C:D:f:hm:qsw:T:vz",
> options, &option_index);
> long ncores;
>
> @@ -707,6 +710,10 @@ static void parse_options(int argc, char *argv[])
> exit(1);
> }
> break;
> + case OPT_QUIET:
> + case 'q':
> + g.quiet = 1;
> + break;
> case OPT_SINGLE_PREHEAT:
> case 's':
> /*
> @@ -825,9 +832,11 @@ int main(int argc, char *argv[])
> signal(SIGINT, handle_alarm);
> signal(SIGTERM, handle_alarm);
>
> - dump_globals();
> + if (!g.quiet)
> + dump_globals();
>
> - printf("Pre-heat for 1 seconds...\n");
> + if (!g.quiet)
> + printf("Pre-heat for 1 seconds...\n");
> if (g.single_preheat_thread)
> g.n_threads = 1;
> else
> @@ -835,12 +844,14 @@ int main(int argc, char *argv[])
> run_expt(threads, 1);
> record_bias(threads);
>
> - printf("Test starts...\n");
> + if (!g.quiet)
> + printf("Test starts...\n");
> /* Reset n_threads to always run on all the cores */
> g.n_threads = g.n_threads_total;
> run_expt(threads, g.runtime);
>
> - printf("Test completed.\n\n");
> + if (!g.quiet)
> + printf("Test completed.\n\n");
>
> write_summary(threads);
>
> --
> 2.30.0
>
>
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param
2021-02-10 17:51 ` [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param Daniel Wagner
@ 2021-02-17 3:52 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:52 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Group thread realated data such as thread ID to struct thread_param.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/cyclictest/cyclictest.c | 34 +++++++++++++++++-----------------
> 1 file changed, 17 insertions(+), 17 deletions(-)
>
> diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
> index c4b2369bee6b..7c45732c1553 100644
> --- a/src/cyclictest/cyclictest.c
> +++ b/src/cyclictest/cyclictest.c
> @@ -113,6 +113,9 @@ static char *policyname(int policy);
>
> /* Struct to transfer parameters to the thread */
> struct thread_param {
> + pthread_t thread;
> + int threadstarted;
> + int tid;
> int prio;
> int policy;
> int mode;
> @@ -141,9 +144,6 @@ struct thread_stat {
> long *smis;
> long *hist_array;
> long *outliers;
> - pthread_t thread;
> - int threadstarted;
> - int tid;
> long reduce;
> long redmax;
> long cycleofmax;
> @@ -530,7 +530,7 @@ static void *timerthread(void *param)
> interval.tv_sec = par->interval / USEC_PER_SEC;
> interval.tv_nsec = (par->interval % USEC_PER_SEC) * 1000;
>
> - stat->tid = gettid();
> + par->tid = gettid();
>
> sigemptyset(&sigset);
> sigaddset(&sigset, par->signal);
> @@ -539,7 +539,7 @@ static void *timerthread(void *param)
> if (par->mode == MODE_CYCLIC) {
> sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
> sigev.sigev_signo = par->signal;
> - sigev.sigev_notify_thread_id = stat->tid;
> + sigev.sigev_notify_thread_id = par->tid;
> timer_create(par->clock, &sigev, &timer);
> tspec.it_interval = interval;
> }
> @@ -613,7 +613,7 @@ static void *timerthread(void *param)
> setitimer(ITIMER_REAL, &itimer, NULL);
> }
>
> - stat->threadstarted++;
> + par->threadstarted++;
>
> while (!shutdown) {
>
> @@ -719,7 +719,7 @@ static void *timerthread(void *param)
> shutdown++;
> pthread_mutex_lock(&break_thread_id_lock);
> if (break_thread_id == 0) {
> - break_thread_id = stat->tid;
> + break_thread_id = par->tid;
> tracemark("hit latency threshold (%llu > %d)",
> (unsigned long long) diff, tracelimit);
> break_thread_value = diff;
> @@ -795,7 +795,7 @@ static void *timerthread(void *param)
> /* switch to normal */
> schedp.sched_priority = 0;
> sched_setscheduler(0, SCHED_OTHER, &schedp);
> - stat->threadstarted = -1;
> + par->threadstarted = -1;
>
> return NULL;
> }
> @@ -1293,7 +1293,7 @@ static void print_tids(struct thread_param *par[], int nthreads)
>
> printf("# Thread Ids:");
> for (i = 0; i < nthreads; i++)
> - printf(" %05d", par[i]->stats->tid);
> + printf(" %05d", par[i]->tid);
> printf("\n");
> }
>
> @@ -1407,7 +1407,7 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
> fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
> "Min:%7ld Act:%5ld Avg:%5ld Max:%8ld";
>
> - fprintf(fp, fmt, index, stat->tid, par->prio,
> + fprintf(fp, fmt, index, par->tid, par->prio,
> par->interval, stat->cycles, stat->min,
> stat->act, stat->cycles ?
> (long)(stat->avg/stat->cycles) : 0, stat->max);
> @@ -1463,7 +1463,7 @@ static void rstat_print_stat(struct thread_param *par, int index, int verbose, i
> fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
> "Min:%7ld Act:%5ld Avg:%5ld Max:%8ld";
>
> - dprintf(fd, fmt, index, stat->tid, par->prio,
> + dprintf(fd, fmt, index, par->tid, par->prio,
> par->interval, stat->cycles, stat->min,
> stat->act, stat->cycles ?
> (long)(stat->avg/stat->cycles) : 0, stat->max);
> @@ -1966,9 +1966,9 @@ int main(int argc, char **argv)
> stat->min = 1000000;
> stat->max = 0;
> stat->avg = 0.0;
> - stat->threadstarted = 1;
> stat->smi_count = 0;
> - status = pthread_create(&stat->thread, &attr, timerthread, par);
> + par->threadstarted = 1;
> + status = pthread_create(&par->thread, &attr, timerthread, par);
> if (status)
> fatal("failed to create thread %d: %s\n", i, strerror(status));
>
> @@ -2038,10 +2038,10 @@ int main(int argc, char **argv)
> if (quiet)
> quiet = 2;
> for (i = 0; i < num_threads; i++) {
> - if (statistics[i]->threadstarted > 0)
> - pthread_kill(statistics[i]->thread, SIGTERM);
> - if (statistics[i]->threadstarted) {
> - pthread_join(statistics[i]->thread, NULL);
> + if (parameters[i]->threadstarted > 0)
> + pthread_kill(parameters[i]->thread, SIGTERM);
> + if (parameters[i]->threadstarted) {
> + pthread_join(parameters[i]->thread, NULL);
> if (quiet && !histogram)
> print_stat(stdout, parameters[i], i, 0, 0);
> }
> --
> 2.30.0
>
>
Why? I don't see any advantage to this, and according to the comments at
the top of the struct, thread_param is to transfer params to a thread
and thread_stat is for statistics. This is unnecessary churn, unless
you can convince me otherwise. I was worried that your JSON changes
would rely on this being changed, but as far as I can see, they do not!
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH rt-tests v5 02/13] signaltest: Move thread data to struct thread_param
2021-02-10 17:51 ` [PATCH rt-tests v5 02/13] signaltest: " Daniel Wagner
@ 2021-02-17 3:52 ` John Kacur
0 siblings, 0 replies; 27+ messages in thread
From: John Kacur @ 2021-02-17 3:52 UTC (permalink / raw
To: Daniel Wagner; +Cc: Clark Williams, linux-rt-users
On Wed, 10 Feb 2021, Daniel Wagner wrote:
> Group thread realated data such as thread ID to struct thread_param.
>
> Signed-off-by: Daniel Wagner <dwagner@suse.de>
> ---
> src/signaltest/signaltest.c | 44 ++++++++++++++++++-------------------
> 1 file changed, 22 insertions(+), 22 deletions(-)
>
> diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c
> index c34bc994d886..dd5633d5fc51 100644
> --- a/src/signaltest/signaltest.c
> +++ b/src/signaltest/signaltest.c
> @@ -40,6 +40,10 @@
>
> /* Struct to transfer parameters to the thread */
> struct thread_param {
> + pthread_t thread;
> + pthread_t tothread;
> + int threadstarted;
> + int tid;
> int id;
> int prio;
> int signal;
> @@ -47,6 +51,7 @@ struct thread_param {
> struct thread_stat *stats;
> int bufmsk;
> int cpu;
> + int interrupted;
> };
>
> /* Struct for statistics */
> @@ -58,11 +63,6 @@ struct thread_stat {
> long act;
> double avg;
> long *values;
> - pthread_t thread;
> - pthread_t tothread;
> - int threadstarted;
> - int tid;
> - int interrupted;
> };
>
> static int shutdown;
> @@ -86,7 +86,7 @@ void *signalthread(void *param)
> pthread_t thread;
> cpu_set_t mask;
>
> - stat->tid = gettid();
> + par->tid = gettid();
>
> if (par->cpu != -1) {
> CPU_ZERO(&mask);
> @@ -105,7 +105,7 @@ void *signalthread(void *param)
> schedp.sched_priority = par->prio;
> sched_setscheduler(0, policy, &schedp);
>
> - stat->threadstarted++;
> + par->threadstarted++;
>
> clock_gettime(CLOCK_MONOTONIC, &before);
>
> @@ -128,7 +128,7 @@ void *signalthread(void *param)
>
> /* Get current time */
> clock_gettime(CLOCK_MONOTONIC, &now);
> - pthread_kill(stat->tothread, SIGUSR1);
> + pthread_kill(par->tothread, SIGUSR1);
>
> /* Skip the first cycle */
> if (first) {
> @@ -148,7 +148,7 @@ void *signalthread(void *param)
>
> if (!stopped && tracelimit && !par->id && (diff > tracelimit)) {
> stat->act = diff;
> - stat->interrupted = 1;
> + par->interrupted = 1;
> stopped++;
> shutdown++;
> }
> @@ -167,7 +167,7 @@ void *signalthread(void *param)
> schedp.sched_priority = 0;
> sched_setscheduler(0, SCHED_OTHER, &schedp);
>
> - stat->threadstarted = -1;
> + par->threadstarted = -1;
>
> return NULL;
> }
> @@ -298,7 +298,7 @@ static void print_stat(struct thread_param *par, int index, int verbose)
> if (quiet != 1) {
> printf("T:%2d (%5d) P:%2d C:%7lu "
> "Min:%7ld Act:%5ld Avg:%5ld Max:%8ld\n",
> - index, stat->tid, par->prio,
> + index, par->tid, par->prio,
> stat->cycles, stat->min, stat->act,
> stat->cycles ?
> (long)(stat->avg/stat->cycles) : 0, stat->max);
> @@ -389,8 +389,8 @@ int main(int argc, char **argv)
> stat[i].min = 1000000;
> stat[i].max = -1000000;
> stat[i].avg = 0.0;
> - stat[i].threadstarted = 1;
> - status = pthread_create(&stat[i].thread, NULL, signalthread,
> + par[i].threadstarted = 1;
> + status = pthread_create(&par[i].thread, NULL, signalthread,
> &par[i]);
> if (status)
> fatal("failed to create thread %d: %s\n", i,
> @@ -401,18 +401,18 @@ int main(int argc, char **argv)
> int allstarted = 1;
>
> for (i = 0; i < num_threads; i++) {
> - if (stat[i].threadstarted != 2)
> + if (par[i].threadstarted != 2)
> allstarted = 0;
> }
> if (!allstarted)
> continue;
>
> for (i = 0; i < num_threads - 1; i++)
> - stat[i].tothread = stat[i+1].thread;
> - stat[i].tothread = stat[0].thread;
> + par[i].tothread = par[i+1].thread;
> + par[i].tothread = par[0].thread;
> break;
> }
> - pthread_kill(stat[0].thread, signum);
> + pthread_kill(par[0].thread, signum);
>
> while (!shutdown) {
> char lavg[256];
> @@ -443,12 +443,12 @@ int main(int argc, char **argv)
> if (quiet)
> quiet = 2;
> for (i = 0; i < num_threads; i++) {
> - if (stat[i].threadstarted > 0)
> - pthread_kill(stat[i].thread, SIGUSR1);
> - if (stat[i].interrupted)
> + if (par[i].threadstarted > 0)
> + pthread_kill(par[i].thread, SIGUSR1);
> + if (par[i].interrupted)
> printf("Thread %d exceeded trace limit.\n", i);
> - if (stat[i].threadstarted) {
> - pthread_join(stat[i].thread, NULL);
> + if (par[i].threadstarted) {
> + pthread_join(par[i].thread, NULL);
> print_stat(&par[i], i, 0);
> }
> if (stat[i].values)
> --
> 2.30.0
>
>
No for the same reasons I gave for cyclictest.
Unncessary churn, and it makes backporting fixes harder too.
John
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2021-02-17 3:53 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-02-10 17:51 [PATCH rt-tests v5 00/13] Generate machine-readable output Daniel Wagner
2021-02-10 17:51 ` [PATCH rt-tests v5 01/13] cyclictest: Move thread data to struct thread_param Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 02/13] signaltest: " Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 03/13] rt-utils: Add JSON common header output helper Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 04/13] cyclictest: Add JSON output feature Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 05/13] signaltest: " Daniel Wagner
2021-02-17 3:50 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 06/13] cyclicdeadline: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 07/13] pmqtest: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 08/13] ptsematest: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 09/13] sigwaittest: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 10/13] svsematest: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 11/13] oslat: " Daniel Wagner
2021-02-17 3:51 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 12/13] rt-migrate-test: " Daniel Wagner
2021-02-17 3:52 ` John Kacur
2021-02-10 17:51 ` [PATCH rt-tests v5 13/13] oslat: Add quiet command line option Daniel Wagner
2021-02-17 3:52 ` John Kacur
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.