rt-tests/SOURCES/rt-tests-cyclictest-Get-a-s...

295 lines
7.8 KiB
Diff

From 26bd002f00753b3b6aa857eeee62c051a15b6fa5 Mon Sep 17 00:00:00 2001
From: John Kacur <jkacur@redhat.com>
Date: Fri, 6 Sep 2019 21:48:59 +0200
Subject: [PATCH] rt-tests: cyclictest: Get a snapshot of cyclictest without
interuppting it
Right now if you are running cyclictest you can send it SIGUSR1
and it will spill out the data at a moment in time, and keep running.
However, this can be problematic if you are using another program such
as rteval to consume the data.
This feature here lets you send SIGUSR2 to cyclictest and it dumps
status to shared memory so you can read it without interrupting
cyclictest and without interferring with the data it is outputing.
To use it, start cyclictest in one term, then in another term send it
SIGUSR2, and then you can just cat the results like this:
[jkacur@planxty rt-tests]$ ps ax | tail
14083 ? I 0:00 [kworker/1:0-events]
14108 ? I 0:01 [kworker/u16:3-events_unbound]
14150 ? I 0:00 [kworker/7:0-mm_percpu_wq]
14287 pts/9 SLl+ 0:14 ./cyclictest -t
14324 ? I 0:00 [kworker/1:2]
14341 ? I 0:00 [kworker/0:2]
14342 ? I 0:00 [kworker/2:1]
14363 ? I 0:00 [kworker/u16:0-events_unbound]
14381 pts/2 R+ 0:00 ps ax
14382 pts/2 S+ 0:00 tail
[jkacur@planxty rt-tests]$ cat /dev/shm/cyclictest_shm
[jkacur@planxty rt-tests]$ kill -s USR2 14287
[jkacur@planxty rt-tests]$ cat /dev/shm/cyclictest_shm
#---------------------------
# cyclictest current status:
T: 0 (14288) P: 0 I:1000 C: 124852 Min: 20 Act: 65 Avg: 104 Max: 354
T: 1 (14289) P: 0 I:1500 C: 83235 Min: 6 Act: 77 Avg: 82 Max: 330
T: 2 (14290) P: 0 I:2000 C: 62426 Min: 9 Act: 71 Avg: 110 Max: 358
T: 3 (14291) P: 0 I:2500 C: 49940 Min: 9 Act: 77 Avg: 111 Max: 453
T: 4 (14292) P: 0 I:3000 C: 41617 Min: 14 Act: 68 Avg: 69 Max: 815
T: 5 (14293) P: 0 I:3500 C: 35672 Min: 15 Act: 68 Avg: 105 Max: 360
T: 6 (14294) P: 0 I:4000 C: 31212 Min: 15 Act: 64 Avg: 103 Max: 372
T: 7 (14295) P: 0 I:4500 C: 27744 Min: 20 Act: 118 Avg: 93 Max: 681
#---------------------------
Signed-off-by: John Kacur <jkacur@redhat.com>
---
src/cyclictest/cyclictest.c | 184 ++++++++++++++++++++++++++++++++++++
1 file changed, 184 insertions(+)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index bca028fedffd..1c515ae1354c 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -231,10 +231,14 @@ static struct thread_param **parameters;
static struct thread_stat **statistics;
static void print_stat(FILE *fp, struct thread_param *par, int index, int verbose, int quiet);
+static void rstat_print_stat(struct thread_param *par, int index, int verbose, int quiet);
+static void rstat_setup(void);
static int latency_target_fd = -1;
static int32_t latency_target_value = 0;
+static int rstat_fd = -1;
+
/* Latency trick
* if the file /dev/cpu_dma_latency exists,
* open it and write a zero into it. This will tell
@@ -1475,6 +1479,22 @@ static void sighand(int sig)
fprintf(stderr, "#---------------------------\n");
quiet = oldquiet;
return;
+ } else if (sig == SIGUSR2) {
+ int i;
+ int oldquiet = quiet;
+
+ if (rstat_fd == -1) {
+ fprintf(stderr, "ERROR: rstat_fd not valid\n");
+ return;
+ }
+ quiet = 0;
+ dprintf(rstat_fd, "#---------------------------\n");
+ dprintf(rstat_fd, "# cyclictest current status:\n");
+ for (i = 0; i < num_threads; i++)
+ rstat_print_stat(parameters[i], i, 0, 0);
+ dprintf(rstat_fd, "#---------------------------\n");
+ quiet = oldquiet;
+ return;
}
shutdown = 1;
if (refresh_on_max)
@@ -1642,6 +1662,62 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
}
}
+static void rstat_print_stat(struct thread_param *par, int index, int verbose, int quiet)
+{
+ struct thread_stat *stat = par->stats;
+ int fd = rstat_fd;
+
+ if (!verbose) {
+ if (quiet != 1) {
+ char *fmt;
+ if (use_nsecs)
+ fmt = "T:%2d (%5d) P:%2d I:%ld C:%7lu "
+ "Min:%7ld Act:%8ld Avg:%8ld Max:%8ld";
+ else
+ 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,
+ par->interval, stat->cycles, stat->min,
+ stat->act, stat->cycles ?
+ (long)(stat->avg/stat->cycles) : 0, stat->max);
+
+ if (smi)
+ dprintf(fd," SMI:%8ld", stat->smi_count);
+
+ dprintf(fd, "\n");
+ }
+ } else {
+ while (stat->cycles != stat->cyclesread) {
+ unsigned long diff_smi;
+ long diff = stat->values
+ [stat->cyclesread & par->bufmsk];
+
+ if (smi)
+ diff_smi = stat->smis
+ [stat->cyclesread & par->bufmsk];
+
+ if (diff > stat->redmax) {
+ stat->redmax = diff;
+ stat->cycleofmax = stat->cyclesread;
+ }
+ if (++stat->reduce == oscope_reduction) {
+ if (!smi)
+ dprintf(fd, "%8d:%8lu:%8ld\n", index,
+ stat->cycleofmax, stat->redmax);
+ else
+ dprintf(fd, "%8d:%8lu:%8ld%8ld\n",
+ index, stat->cycleofmax,
+ stat->redmax, diff_smi);
+
+ stat->reduce = 0;
+ stat->redmax = 0;
+ }
+ stat->cyclesread++;
+ }
+ }
+}
+
/*
* thread that creates a named fifo and hands out run stats when someone
@@ -1729,6 +1805,105 @@ static void trigger_update(struct thread_param *par, int diff, int64_t ts)
pthread_mutex_unlock(&trigger_lock);
}
+/* Running status shared memory open */
+static int rstat_shm_open(void)
+{
+ int fd;
+
+ errno = 0;
+ fd = shm_unlink("/cyclictest_shm");
+
+ if ((fd == -1) && (errno != ENOENT)) {
+ fprintf(stderr, "ERROR: shm_unlink %s\n", strerror(errno));
+ return fd;
+ }
+
+ errno = 9;
+ fd = shm_open("/cyclictest_shm", O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+ if (fd == -1) {
+ fprintf(stderr, "ERROR: shm_open %s\n", strerror(errno));
+ }
+
+ rstat_fd = fd;
+
+ return fd;
+}
+
+static int rstat_ftruncate(int fd)
+{
+ int err;
+
+ errno = 0;
+ err = ftruncate(fd, _SC_PAGE_SIZE);
+ if (err) {
+ fprintf(stderr, "ftruncate error %s\n", strerror(errno));
+ }
+
+ return err;
+}
+
+static void *rstat_mmap(int fd)
+{
+ void *mptr;
+
+ errno = 0;
+ mptr = mmap(0, _SC_PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (mptr == (void*)-1) {
+ fprintf(stderr, "ERROR: mmap, %s\n", strerror(errno));
+ }
+
+ return mptr;
+}
+
+static int rstat_mlock(void *mptr)
+{
+ int err;
+
+ err = mlock(mptr, _SC_PAGE_SIZE);
+
+ errno = 0;
+ if (err == -1) {
+ fprintf(stderr, "ERROR, mlock %s\n", strerror(errno));
+ }
+
+ return err;
+}
+
+static void rstat_setup(void)
+{
+ int res;
+ void *mptr = NULL;
+
+ int sfd = rstat_shm_open();
+ if (sfd < 0)
+ goto rstat_err;
+
+ res = rstat_ftruncate(sfd);
+ if (res)
+ goto rstat_err1;
+
+ mptr = rstat_mmap(sfd);
+ if (mptr == MAP_FAILED)
+ goto rstat_err1;
+
+ res = rstat_mlock(mptr);
+ if (res)
+ goto rstat_err2;
+
+ return;
+
+rstat_err2:
+ munmap(mptr, _SC_PAGE_SIZE);
+rstat_err1:
+ close(sfd);
+ shm_unlink("/cyclictest_shm");
+rstat_err:
+ rstat_fd = -1;
+ return;
+}
+
+
int main(int argc, char **argv)
{
sigset_t sigset;
@@ -1869,6 +2044,7 @@ int main(int argc, char **argv)
}
+
mode = use_nanosleep + use_system;
sigemptyset(&sigset);
@@ -1878,6 +2054,10 @@ int main(int argc, char **argv)
signal(SIGINT, sighand);
signal(SIGTERM, sighand);
signal(SIGUSR1, sighand);
+ signal(SIGUSR2, sighand);
+
+ /* Set-up shm */
+ rstat_setup();
parameters = calloc(num_threads, sizeof(struct thread_param *));
if (!parameters)
@@ -2138,5 +2318,9 @@ int main(int argc, char **argv)
if (affinity_mask)
rt_bitmask_free(affinity_mask);
+ /* Remove running status shared memory file if it exists */
+ if (rstat_fd >= 0)
+ shm_unlink("/cyclictest_shm");
+
exit(ret);
}
--
2.20.1