* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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 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