295 lines
7.8 KiB
Diff
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
|
|
|