diff --git a/.gitignore b/.gitignore index cda655d..d52a338 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/rt-tests-1.5.tar.xz +SOURCES/rt-tests-1.8.tar.xz diff --git a/.rt-tests.metadata b/.rt-tests.metadata index 76fa2df..77a85ed 100644 --- a/.rt-tests.metadata +++ b/.rt-tests.metadata @@ -1 +1 @@ -13ef79a90a810103e8a0fa5da92544b5d31c3838 SOURCES/rt-tests-1.5.tar.xz +50737a762ff27d6440798f10a33f720f476e1438 SOURCES/rt-tests-1.8.tar.xz diff --git a/SOURCES/cyclictest-Fix-setaffinity-error-on-large-NUMA-machines.patch b/SOURCES/cyclictest-Fix-setaffinity-error-on-large-NUMA-machines.patch new file mode 100644 index 0000000..96084c2 --- /dev/null +++ b/SOURCES/cyclictest-Fix-setaffinity-error-on-large-NUMA-machines.patch @@ -0,0 +1,84 @@ +From b07c57b33e4e24e873e680b8327f9be4f321caa9 Mon Sep 17 00:00:00 2001 +From: Yunfeng Ye +Date: Wed, 22 Apr 2020 10:19:52 +0800 +Subject: [PATCH] cyclictest: Fix setaffinity error on large NUMA machines + +An Error occurs when run: ./cyclictest -v -t 5 -p 80 -i 1000 -a 3 + +On large NUMA machines still getting the following error +WARN: Couldn't setaffinity in main thread: Invalid argument + +Instead of calling numa_bitmask_alloc() with max_cpus, use +numa_allocate_cpumask() to fix this. + +Also, make sure numa_available() is called before any other calls to the +numa library. Depending on how the options were invoked this could +happen in parse_cpumask for example. Note, this did not seem to cause +any problems in practice, but let's adhere to the library contract. + +Signed-off-by: John Kacur +--- + src/cyclictest/cyclictest.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c +index c5f1fd46567a..79bb1cb71c68 100644 +--- a/src/cyclictest/cyclictest.c ++++ b/src/cyclictest/cyclictest.c +@@ -1135,7 +1135,7 @@ static void use_current_cpuset(const int max_cpus) + + pid = getpid(); + +- curmask = numa_bitmask_alloc(sizeof(struct bitmask)); ++ curmask = numa_allocate_cpumask(); + numa_sched_getaffinity(pid, curmask); + + /* Clear bits that are not set in both the cpuset from the environment, +@@ -1225,6 +1225,20 @@ enum option_values { + OPT_TRACEMARK, OPT_POSIX_TIMERS, + }; + ++/* numa_available() must be called before any other calls to the numa library */ ++static void numa_initialize(void) ++{ ++ static int is_initialized; ++ ++ if (is_initialized == 1) ++ return; ++ ++ if (numa_available() != -1) ++ numa = 1; ++ ++ is_initialized = 1; ++} ++ + /* Process commandline options */ + static void process_options (int argc, char *argv[], int max_cpus) + { +@@ -1288,6 +1302,7 @@ static void process_options (int argc, char *argv[], int max_cpus) + /* smp sets AFFINITY_USEALL in OPT_SMP */ + if (smp) + break; ++ numa_initialize(); + if (optarg != NULL) { + parse_cpumask(optarg, max_cpus); + setaffinity = AFFINITY_SPECIFIED; +@@ -1460,12 +1475,9 @@ static void process_options (int argc, char *argv[], int max_cpus) + /* if smp wasn't requested, test for numa automatically */ + if (!smp) { + #ifdef NUMA +- if (numa_available() != -1) { +- numa = 1; +- if (setaffinity == AFFINITY_UNSPECIFIED) { +- setaffinity = AFFINITY_USEALL; +- } +- } ++ numa_initialize(); ++ if (setaffinity == AFFINITY_UNSPECIFIED) ++ setaffinity = AFFINITY_USEALL; + #else + warn("cyclictest was not built with the numa option\n"); + numa = 0; +-- +2.21.3 + diff --git a/SOURCES/cyclictest-Sync-manpage-with-the-help-option.patch b/SOURCES/cyclictest-Sync-manpage-with-the-help-option.patch deleted file mode 100644 index bc61d75..0000000 --- a/SOURCES/cyclictest-Sync-manpage-with-the-help-option.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 86936690f508b4d3241bff2f6dc8f40088b19e3f Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Fri, 22 Nov 2019 14:51:54 +0100 -Subject: [PATCH] cyclictest: Sync manpage with the help option - -Sync the manpage with the help option, as the manpage has not kept-up -with changes to help - -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.8 | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/cyclictest/cyclictest.8 b/src/cyclictest/cyclictest.8 -index b64a16ae8bbb..00e2d2403996 100644 ---- a/src/cyclictest/cyclictest.8 -+++ b/src/cyclictest/cyclictest.8 -@@ -67,6 +67,9 @@ Specify a length for the test run. - .br - Append 'm', 'h', or 'd' to specify minutes, hours or days. - .TP -+.B \-\-latency=PM_Q0S -+write PM_Q0S to /dev/cpu_dma_latency -+.TP - .B \-F, \-\-fifo= - Create a named pipe at path and write stats to it - .TP -@@ -95,9 +98,6 @@ Lock current and future memory allocations to prevent being paged out - Delay updating the screen until a new max latency is hit. (useful for - running cyclictest on low-bandwidth connections) - .TP --.B \-n, \-\-nanosleep --Use clock_nanosleep instead of posix interval timers. Setting this option runs the tests with clock_nanosleep instead of posix interval timers. --.TP - .B \-N, \-\-nsecs - Show results in nanoseconds instead of microseconds, which is the default unit. - .TP -@@ -165,6 +165,9 @@ where n=task number c=count v=latency value in us. - .TP - .B \-\-dbg_cyclictest - Print info userful for debugging cyclictest -+.TP -+.B \-x, \-\-posix_timers -+Use POSIX timers instead of clock_nanosleep. - - .SH SEE ALSO - .BR numa (3), --- -2.20.1 - diff --git a/SOURCES/deadline_test-Increase-buffer-to-avoid-overflow.patch b/SOURCES/deadline_test-Increase-buffer-to-avoid-overflow.patch deleted file mode 100644 index c7ae585..0000000 --- a/SOURCES/deadline_test-Increase-buffer-to-avoid-overflow.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 33dff61afb032e5374c6ec60d4f88cdf57e83c53 Mon Sep 17 00:00:00 2001 -From: Daniel Wagner -Date: Mon, 19 Aug 2019 08:43:04 +0200 -Subject: [PATCH 04/10] deadline_test: Increase buffer to avoid overflow -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Increase the size of the char buffer. gcc 9.1.1 reports: - -src/sched_deadline/deadline_test.c:1803:24: warning: ‘%d’ directive writing between 1 and 11 bytes into a region of size 10 [-Wformat-overflow=] - 1803 | sprintf(setcpu_buf, "%d", cpu_count - 1); - | ^~ -src/sched_deadline/deadline_test.c:1803:23: note: directive argument in the range [-2147483648, 2147483646] - 1803 | sprintf(setcpu_buf, "%d", cpu_count - 1); - | ^~~~ -src/sched_deadline/deadline_test.c:1803:3: note: ‘sprintf’ output between 2 and 12 bytes into a destination of size 10 - 1803 | sprintf(setcpu_buf, "%d", cpu_count - 1); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Signed-off-by: Daniel Wagner -Signed-off-by: John Kacur ---- - src/sched_deadline/deadline_test.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/sched_deadline/deadline_test.c b/src/sched_deadline/deadline_test.c -index e2898de328bb..5b5f40dbb74d 100644 ---- a/src/sched_deadline/deadline_test.c -+++ b/src/sched_deadline/deadline_test.c -@@ -1795,7 +1795,7 @@ int main (int argc, char **argv) - - /* -b has us bind to the last CPU. */ - if (!all_cpus && !setcpu) { -- setcpu_buf = malloc(10); -+ setcpu_buf = malloc(12); - if (!setcpu_buf) { - perror("malloc"); - exit(-1); --- -2.20.1 - diff --git a/SOURCES/pi_stress-Sync-man-page-with-help.patch b/SOURCES/pi_stress-Sync-man-page-with-help.patch deleted file mode 100644 index ece1232..0000000 --- a/SOURCES/pi_stress-Sync-man-page-with-help.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 8f96d299bf71bd922f0d45e1500c346e7e55db7c Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 23 Jan 2020 05:29:12 +0100 -Subject: [PATCH] rt-tests: pi_stress: Sync man page with help - -Sync the man page with help. -Specifically, remove the signal option which is not supported and -document the sched option - -Signed-off-by: John Kacur ---- - src/pi_tests/pi_stress.8 | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/src/pi_tests/pi_stress.8 b/src/pi_tests/pi_stress.8 -index 475d3c34f135..5e2af6189ca1 100644 ---- a/src/pi_tests/pi_stress.8 -+++ b/src/pi_tests/pi_stress.8 -@@ -21,7 +21,8 @@ pi_stress \- a stress test for POSIX Priority Inheritance mutexes - .IR groups - .RB [ \-d|\-\-debug ] - .RB [ \-v|\-\-verbose ] --.RB [ \-s|\-\-signal ] -+.RB [ \-s|\-\-sched -+.IR sched_opts ] - .RB [ \-r|\-\-rr ] - .RB [ \-p|\-\-prompt ] - .RB [ \-m|\-\-mlockall ] -@@ -63,12 +64,12 @@ Specify a length for the test run. - Append 'm', 'h', or 'd' to specify minutes, hours or days. - .IP \-v|\-\-verbose - Run with verbose messages --.IP \-s|\-\-signal --Terminate on receipt of SIGTERM (Ctrl-C). Default is to terminate on --any keypress. - .IP \-r|\-\-rr - Run inversion group threads as SCHED_RR (round-robin). The default is - to run the inversion threads as SCHED_FIFO. -+.IP \-s|\-\-sched -+scheduling options per thread type: -+id=[high|med|low],policy=[fifo,rr],priority=,policy=deadline,runtime=,deadline=,period= - .IP \-p|\-\-prompt - Prompt before actually starting the stress test - .IP \-u|\-\-uniprocessor --- -2.20.1 - diff --git a/SOURCES/pi_stress-limit-the-number-of-inversion-groups-to-th.patch b/SOURCES/pi_stress-limit-the-number-of-inversion-groups-to-th.patch new file mode 100644 index 0000000..c0e9cd2 --- /dev/null +++ b/SOURCES/pi_stress-limit-the-number-of-inversion-groups-to-th.patch @@ -0,0 +1,39 @@ +From 3359c4464c2a13ab04f15598b1c79040399978f5 Mon Sep 17 00:00:00 2001 +From: Clark Williams +Date: Tue, 21 Jul 2020 16:10:22 -0500 +Subject: [PATCH] pi_stress: limit the number of inversion groups to the number + of online cores + +Each inversion group is three SCHED_FIFO threads, so the chances of more groups +than online cores actually getting to run is very slim. Limit the number of +groups requested to be <= the number of online cpus. + +Signed-off-by: Clark Williams + +Changing the conversion in printf to %ld since the number of online +processors is a long. +Signed-off-by: John Kacur +--- + src/pi_tests/pi_stress.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/pi_tests/pi_stress.c b/src/pi_tests/pi_stress.c +index 0ed844c636cd..eba21d7727bc 100644 +--- a/src/pi_tests/pi_stress.c ++++ b/src/pi_tests/pi_stress.c +@@ -1327,6 +1327,12 @@ void process_command_line(int argc, char **argv) + break; + case 'g': + ngroups = strtol(optarg, NULL, 10); ++ if (ngroups > num_processors) { ++ pi_error("the number of groups cannot exceed " ++ "the number of online processors (%ld)\n", ++ num_processors); ++ exit(-1); ++ } + pi_info("number of groups set to %d\n", ngroups); + break; + case 'r': +-- +2.26.2 + diff --git a/SOURCES/pmqtest-Increase-buffer-to-avoid-overflow.patch b/SOURCES/pmqtest-Increase-buffer-to-avoid-overflow.patch deleted file mode 100644 index 42a0cab..0000000 --- a/SOURCES/pmqtest-Increase-buffer-to-avoid-overflow.patch +++ /dev/null @@ -1,50 +0,0 @@ -From f7c39616fe887f35abaa4b81466ab7f167e0a410 Mon Sep 17 00:00:00 2001 -From: Daniel Wagner -Date: Mon, 19 Aug 2019 08:43:01 +0200 -Subject: [PATCH 01/10] pmqtest: Increase buffer to avoid overflow -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Increase the size of the char buffer. gcc 9.1.1 reports: - -src/pmqtest/pmqtest.c: In function ‘main’: -src/pmqtest/pmqtest.c:46:21: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 8 [-Wformat-overflow=] - 46 | #define SYNCMQ_NAME "/syncmsg%d" - | ^~~~~~~~~~~~ - -src/pmqtest/pmqtest.c:445:3: note: ‘sprintf’ output between 10 and 19 bytes into a destination of size 16 - 445 | sprintf(mqname, SYNCMQ_NAME, i); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Signed-off-by: Daniel Wagner -Signed-off-by: John Kacur ---- - src/pmqtest/pmqtest.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/pmqtest/pmqtest.c b/src/pmqtest/pmqtest.c -index a04fc49872bf..3ce799bd6319 100644 ---- a/src/pmqtest/pmqtest.c -+++ b/src/pmqtest/pmqtest.c -@@ -440,7 +440,7 @@ int main(int argc, char *argv[]) - goto nomem; - - for (i = 0; i < num_threads; i++) { -- char mqname[16]; -+ char mqname[19]; - - sprintf(mqname, SYNCMQ_NAME, i); - receiver[i].syncmq = mq_open(mqname, oflag, 0777, &mqstat); -@@ -567,7 +567,7 @@ int main(int argc, char *argv[]) - } - nanosleep(&maindelay, NULL); - for (i = 0; i < num_threads; i++) { -- char mqname[16]; -+ char mqname[19]; - - mq_close(receiver[i].syncmq); - sprintf(mqname, SYNCMQ_NAME, i); --- -2.20.1 - diff --git a/SOURCES/rt-tests-Add-SPDX-tags.patch b/SOURCES/rt-tests-Add-SPDX-tags.patch deleted file mode 100644 index 57183ff..0000000 --- a/SOURCES/rt-tests-Add-SPDX-tags.patch +++ /dev/null @@ -1,701 +0,0 @@ -From 19a30e151b65f42e74db2a97f79ce21ce23d7c7c Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 25 Nov 2019 15:06:12 +0100 -Subject: [PATCH] rt-tests: Add SPDX tags V2 - -Add SPDX tags instead of having out-of-date and incomplete licences at -the top of files - -Audited again to make sure that GPL-2.0-only is used where appropriate -and not GPL-2.0-or-later (and the other way around) - -Signed-off-by: John Kacur ---- - src/backfire/backfire.c | 17 +-------------- - src/cyclictest/cyclictest.c | 5 +---- - src/cyclictest/rt_numa.h | 1 + - src/hackbench/hackbench.c | 1 + - src/hwlatdetect/hwlatdetect.py | 8 ++----- - src/include/bionic.h | 1 + - src/include/error.h | 1 + - src/include/pip_stress.h | 1 + - src/include/rt-get_cpu.h | 1 + - src/include/rt-sched.h | 24 +++++---------------- - src/include/rt-utils.h | 1 + - src/lib/error.c | 1 + - src/lib/rt-get_cpu.c | 1 + - src/lib/rt-sched.c | 25 ++++++---------------- - src/lib/rt-utils.c | 1 + - src/pi_tests/classic_pi.c | 22 ++++--------------- - src/pi_tests/pi_stress.c | 22 ++++--------------- - src/pi_tests/pip_stress.c | 14 +----------- - src/pi_tests/sigtest.c | 22 ++++--------------- - src/pi_tests/tst-mutexpi10.c | 27 ++++++------------------ - src/pmqtest/pmqtest.c | 16 +------------- - src/ptsematest/ptsematest.c | 17 +-------------- - src/queuelat/determine_maximum_mpps.sh | 3 +++ - src/queuelat/get_cpuinfo_mhz.sh | 3 +++ - src/queuelat/queuelat.c | 8 +++++++ - src/queuelat/targeted-ipi/targeted-ipi.c | 7 ++++++ - src/rt-migrate-test/rt-migrate-test.c | 19 +---------------- - src/sched_deadline/cyclicdeadline.c | 8 +++++++ - src/sched_deadline/deadline_test.c | 24 ++++++--------------- - src/signaltest/signaltest.c | 2 ++ - src/sigwaittest/sigwaittest.c | 2 ++ - src/ssdd/ssdd.c | 12 +++++------ - src/svsematest/svsematest.c | 16 ++------------ - 33 files changed, 95 insertions(+), 238 deletions(-) - -diff --git a/src/backfire/backfire.c b/src/backfire/backfire.c -index a8ac9f5e2b28..81a31d49f47b 100644 ---- a/src/backfire/backfire.c -+++ b/src/backfire/backfire.c -@@ -1,22 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * backfire - send signal back to caller -- * - * Copyright (C) 2007 Carsten Emde -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, -- * USA. - */ - - #include -diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c -index 1c515ae1354c..beac9a3ce946 100644 ---- a/src/cyclictest/cyclictest.c -+++ b/src/cyclictest/cyclictest.c -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-only - /* - * High resolution timer test software - * -@@ -6,10 +7,6 @@ - * (C) 2008-2012 Clark Williams - * (C) 2005-2007 Thomas Gleixner - * -- * This program is free software; you can redistribute it and/or -- * modify it under the terms of the GNU General Public License Version -- * 2 as published by the Free Software Foundation. -- * - */ - #include - #include -diff --git a/src/cyclictest/rt_numa.h b/src/cyclictest/rt_numa.h -index 983502d34c94..1f7c5a482150 100644 ---- a/src/cyclictest/rt_numa.h -+++ b/src/cyclictest/rt_numa.h -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * A numa library for cyclictest. - * The functions here are designed to work whether cyclictest has been -diff --git a/src/hackbench/hackbench.c b/src/hackbench/hackbench.c -index ba804f519950..5a883d341f2e 100644 ---- a/src/hackbench/hackbench.c -+++ b/src/hackbench/hackbench.c -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * This is the latest version of hackbench.c, that tests scheduler and - * unix-socket (or pipe) performance. -diff --git a/src/hwlatdetect/hwlatdetect.py b/src/hwlatdetect/hwlatdetect.py -index c11a6f8ea5b1..12228f45f852 100755 ---- a/src/hwlatdetect/hwlatdetect.py -+++ b/src/hwlatdetect/hwlatdetect.py -@@ -1,14 +1,10 @@ - #!/usr/bin/python3 - -+# SPDX-License-Identifier: GPL-2.0-only -+ - # (C) 2018,2019 Clark Williams - # (C) 2015,2016 Clark Williams - # (C) 2009 Clark Williams --# --# This program is free software; you can redistribute it and/or --# modify it under the terms of the GNU General Public License Version 2 --# as published by the Free Software Foundation. -- -- - - import sys - import os -diff --git a/src/include/bionic.h b/src/include/bionic.h -index 54f9c54b0824..e0433437f5d2 100644 ---- a/src/include/bionic.h -+++ b/src/include/bionic.h -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - #ifndef BIONIC_H - #define BIONIC_H - -diff --git a/src/include/error.h b/src/include/error.h -index 4acff4952dd6..d205e49ff041 100644 ---- a/src/include/error.h -+++ b/src/include/error.h -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - #ifndef __ERROR_H - #define __ERROR_H - -diff --git a/src/include/pip_stress.h b/src/include/pip_stress.h -index 8ed24522851c..ee8b545ab117 100644 ---- a/src/include/pip_stress.h -+++ b/src/include/pip_stress.h -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - #ifndef __PIP_STRESS_H - #define __PIP_STRESS_H - -diff --git a/src/include/rt-get_cpu.h b/src/include/rt-get_cpu.h -index 15d05fcb15fa..74bf8f0fac25 100644 ---- a/src/include/rt-get_cpu.h -+++ b/src/include/rt-get_cpu.h -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - #ifndef __RT_GET_CPU_H - #define __RT_GET_CPU_H - #include -diff --git a/src/include/rt-sched.h b/src/include/rt-sched.h -index 679c4bd10ae2..80171c76e0ee 100644 ---- a/src/include/rt-sched.h -+++ b/src/include/rt-sched.h -@@ -1,23 +1,9 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* -- rt-sched.h - sched_setattr() and sched_getattr() API -- -- (C) Dario Faggioli , 2009, 2010 -- Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner , 2009, 2010 -+ * Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner - * -diff --git a/src/lib/rt-get_cpu.c b/src/lib/rt-get_cpu.c -index 83430dd4d068..608cd9bb76e0 100644 ---- a/src/lib/rt-get_cpu.c -+++ b/src/lib/rt-get_cpu.c -@@ -1,3 +1,4 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * Copyright (C) 2009 John Kacur - */ -diff --git a/src/lib/rt-sched.c b/src/lib/rt-sched.c -index 4a8e3c42b49f..2aaf02d42aee 100644 ---- a/src/lib/rt-sched.c -+++ b/src/lib/rt-sched.c -@@ -1,23 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* -- rt-sched.h - sched_setattr() and sched_getattr() API -- -- (C) Dario Faggioli , 2009, 2010 -- Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner , 2009, 2010 -+ * Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner - * Copyright (C) 2010 Clark Williams -diff --git a/src/pi_tests/classic_pi.c b/src/pi_tests/classic_pi.c -index 695ee4c4bd03..64af8890276f 100644 ---- a/src/pi_tests/classic_pi.c -+++ b/src/pi_tests/classic_pi.c -@@ -1,22 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* -- classic_pi - Classic Priority Inversion deadlock test case -- -- Copyright (C) 2006, 2007 Clark Williams -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -- USA */ -+ * classic_pi - Classic Priority Inversion deadlock test case -+ * Copyright (C) 2006, 2007 Clark Williams -+ */ - - /* This program tests Priority Inheritance mutexes and their ability - to avoid Priority Inversion deadlocks -diff --git a/src/pi_tests/pi_stress.c b/src/pi_tests/pi_stress.c -index 1286370c474b..7fa98dfb9ad4 100644 ---- a/src/pi_tests/pi_stress.c -+++ b/src/pi_tests/pi_stress.c -@@ -1,22 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* -- pi_stress - Priority Inheritance stress test -- -- Copyright (C) 2006, 2007 Clark Williams -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -- USA */ -+ * pi_stress - Priority Inheritance stress test -+ * Copyright (C) 2006, 2007 Clark Williams -+ */ - - /* This program stress tests pthreads priority inheritance mutexes - -diff --git a/src/pi_tests/pip_stress.c b/src/pi_tests/pip_stress.c -index e6cf0ce940ca..c9dbd992e15d 100644 ---- a/src/pi_tests/pip_stress.c -+++ b/src/pi_tests/pip_stress.c -@@ -1,20 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - Pip stress - Priority Inheritance with processes - - Copyright (C) 2009, John Kacur -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . - */ - - /* -diff --git a/src/pi_tests/sigtest.c b/src/pi_tests/sigtest.c -index 0cf520c01335..17dd0d43bdc6 100644 ---- a/src/pi_tests/sigtest.c -+++ b/src/pi_tests/sigtest.c -@@ -1,22 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* -- sigtest - simple little program to verify signal behavior -- -- Copyright (C) 2006, 2007 Clark Williams -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 -- USA */ -+ * sigtest - simple little program to verify signal behavior -+ * Copyright (C) 2006, 2007 Clark Williams -+*/ - - #include - #include -diff --git a/src/pi_tests/tst-mutexpi10.c b/src/pi_tests/tst-mutexpi10.c -index a63ea23ba621..97a345edd26e 100644 ---- a/src/pi_tests/tst-mutexpi10.c -+++ b/src/pi_tests/tst-mutexpi10.c -@@ -1,25 +1,10 @@ -+// SPDX-License-Identifier: LGPL-2.1-or-later - /* -- Classic Priority Inversion deadlock test case -- -- Copyright (C) 2006 Free Software Foundation, Inc. -- This file is part of the GNU C Library. -- Contributed by Clark Williams, 2006 -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public License as -- published by the Free Software Foundation; either version 2.1 of the -- License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; see the file COPYING.LIB. If not, -- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- Boston, MA 02111-1307, USA. */ -- -+ * Classic Priority Inversion deadlock test case -+ * Copyright (C) 2006 Free Software Foundation, Inc. -+ * This file is part of the GNU C Library. -+ * Contributed by Clark Williams, 2006 -+ */ - - /* This program tests Priority Inheritance mutexes and their ability - to avoid Priority Inversion deadlocks -diff --git a/src/pmqtest/pmqtest.c b/src/pmqtest/pmqtest.c -index 3ce799bd6319..3ce29252b9a2 100644 ---- a/src/pmqtest/pmqtest.c -+++ b/src/pmqtest/pmqtest.c -@@ -1,22 +1,8 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * pmqtest.c - * - * Copyright (C) 2009 Carsten Emde -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, -- * USA. - */ - - #include -diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c -index 553759212ac9..78fa444c5578 100644 ---- a/src/ptsematest/ptsematest.c -+++ b/src/ptsematest/ptsematest.c -@@ -1,22 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later - /* - * ptsematest.c -- * - * Copyright (C) 2009 Carsten Emde -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, -- * USA. - */ - - #include -diff --git a/src/queuelat/determine_maximum_mpps.sh b/src/queuelat/determine_maximum_mpps.sh -index 3acd6ba2e362..52d54c0f9065 100755 ---- a/src/queuelat/determine_maximum_mpps.sh -+++ b/src/queuelat/determine_maximum_mpps.sh -@@ -1,5 +1,8 @@ - #!/bin/bash - -+# SPDX-License-Identifier: GPL-2.0-or-later -+# Copyright (C) 2018 Marcelo Tosatti -+ - # A script to determine the maximum mpps. Logic: - # Increase mpps in 0.5 units - # -diff --git a/src/queuelat/get_cpuinfo_mhz.sh b/src/queuelat/get_cpuinfo_mhz.sh -index fb5158f31040..eafdd9577424 100755 ---- a/src/queuelat/get_cpuinfo_mhz.sh -+++ b/src/queuelat/get_cpuinfo_mhz.sh -@@ -1,5 +1,8 @@ - #!/bin/bash - -+# SPDX-License-Identifier: GPL-2.0-or-later -+# Copyright (C) 2018 Marcelo Tosatti -+ - mhz=`cat /proc/cpuinfo | grep "cpu MHz" | uniq | cut -f 3 -d " "` - echo $mhz - -diff --git a/src/queuelat/queuelat.c b/src/queuelat/queuelat.c -index a5525e41776a..cccb50ef0cc4 100644 ---- a/src/queuelat/queuelat.c -+++ b/src/queuelat/queuelat.c -@@ -1,3 +1,11 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+/* -+ * Copyright (C) 2018 Marcelo Tosatti -+ * Copyright (C) 2019 John Kacur -+ * Copyright (C) 2019 Clark Williams -+ */ -+ - #include - #include - #include -diff --git a/src/queuelat/targeted-ipi/targeted-ipi.c b/src/queuelat/targeted-ipi/targeted-ipi.c -index 4a10e0b24ecb..be2b153260c5 100644 ---- a/src/queuelat/targeted-ipi/targeted-ipi.c -+++ b/src/queuelat/targeted-ipi/targeted-ipi.c -@@ -1,3 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+/* -+ * Copyright (C) 2018 Marcelo Tosatti -+ * Copyright (C) 2019 John Kacur -+ * Copyright (C) 2019 Clark Williams -+ */ -+ - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - - #include -diff --git a/src/rt-migrate-test/rt-migrate-test.c b/src/rt-migrate-test/rt-migrate-test.c -index f0a285d1d45f..4863238edeb4 100644 ---- a/src/rt-migrate-test/rt-migrate-test.c -+++ b/src/rt-migrate-test/rt-migrate-test.c -@@ -1,24 +1,7 @@ -+// SPDX-License-Identifier: GPL-2.0-only - /* - * rt-migrate-test.c -- * - * Copyright (C) 2007-2009 Steven Rostedt -- * -- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License (not later!) -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- * -- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - #include - #ifndef __USE_XOPEN2K -diff --git a/src/sched_deadline/cyclicdeadline.c b/src/sched_deadline/cyclicdeadline.c -index 7b5e8b36c4ea..a08e28e73c42 100644 ---- a/src/sched_deadline/cyclicdeadline.c -+++ b/src/sched_deadline/cyclicdeadline.c -@@ -1,3 +1,11 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ -+/* -+ * Copyright (C) 2016 Red Hat Inc, Steven Rostedt -+ * Copyright (C) 2019 John Kacur -+ * Copyright (C) 2019 Clark Williams -+ */ -+ - #include - #include - #include -diff --git a/src/sched_deadline/deadline_test.c b/src/sched_deadline/deadline_test.c -index 5b5f40dbb74d..4cef2609912e 100644 ---- a/src/sched_deadline/deadline_test.c -+++ b/src/sched_deadline/deadline_test.c -@@ -1,22 +1,12 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ - /* - * Copyright (C) 2016 Red Hat Inc, Steven Rostedt -- * -- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; version 2 of the License (not later!) -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, see -- * -- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- * -+ * Copyright (C) 2019 John Kacur -+ * Copyright (C) 2019 Clark Williams -+ */ -+ -+/* - * deadline_test.c - * - * This program is used to test the deadline scheduler (SCHED_DEADLINE tasks). -diff --git a/src/signaltest/signaltest.c b/src/signaltest/signaltest.c -index 4c952561d7f2..b5c86c5635cb 100644 ---- a/src/signaltest/signaltest.c -+++ b/src/signaltest/signaltest.c -@@ -1,3 +1,5 @@ -+// SPDX-License-Identifier: GPL-2.0-only -+ - /* - * RT signal roundtrip test software - * -diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c -index 2d0c04132fa7..4678b68675b2 100644 ---- a/src/sigwaittest/sigwaittest.c -+++ b/src/sigwaittest/sigwaittest.c -@@ -1,3 +1,5 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ - /* - * sigwaittest.c - * -diff --git a/src/ssdd/ssdd.c b/src/ssdd/ssdd.c -index 080ed17107a8..f165da96e23a 100644 ---- a/src/ssdd/ssdd.c -+++ b/src/ssdd/ssdd.c -@@ -1,3 +1,9 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+/* -+ * Copyright (C) 2019 Joe Korty -+ */ -+ - /* - * Have a tracer do a bunch of PTRACE_SINGLESTEPs against - * a tracee as fast as possible. Create several of these -@@ -16,12 +22,6 @@ - * The tracer waits on each PTRACE_SINGLESTEP with a waitpid(2) - * and checks that waitpid's return values for correctness. - * -- * This program was originally written by -- * Joe Korty -- * This program is free software; you can redistribute it and / or modify -- * it under the terms of the GNU General Public License Version 2 -- * of the licence, or (at your option) any later version -- * see COPYING for more information - */ - #include - #include -diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c -index 15e36af76288..7c15393fe1be 100644 ---- a/src/svsematest/svsematest.c -+++ b/src/svsematest/svsematest.c -@@ -1,22 +1,10 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ - /* - * svsematest.c - * - * Copyright (C) 2009 Carsten Emde - * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, -- * USA. - */ - - #include --- -2.20.1 - diff --git a/SOURCES/rt-tests-Add-a-man-page-for-get_cyclictest_snapshot.patch b/SOURCES/rt-tests-Add-a-man-page-for-get_cyclictest_snapshot.patch new file mode 100644 index 0000000..ca2184c --- /dev/null +++ b/SOURCES/rt-tests-Add-a-man-page-for-get_cyclictest_snapshot.patch @@ -0,0 +1,66 @@ +From 82aa302cc1b5fba57792dbf43721897aa3305cff Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 6 Jul 2020 13:18:40 -0400 +Subject: [PATCH 4/7] rt-tests: Add a man page for get_cyclictest_snapshot + +Add a man page for get_cyclictest_snapshot based on -h + +Signed-off-by: John Kacur +--- + src/cyclictest/get_cyclictest_snapshot.8 | 44 ++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + create mode 100644 src/cyclictest/get_cyclictest_snapshot.8 + +diff --git a/src/cyclictest/get_cyclictest_snapshot.8 b/src/cyclictest/get_cyclictest_snapshot.8 +new file mode 100644 +index 000000000000..e9251a8e821f +--- /dev/null ++++ b/src/cyclictest/get_cyclictest_snapshot.8 +@@ -0,0 +1,44 @@ ++.\" Hey, EMACS: -*- nroff -*- ++.TH GET_CYCLICTEST_SNAPSHOT 8 "July 6, 2020" ++.\" Please adjust this date whenever revising the manpage. ++.\" ++.\" Some roff macros, for reference: ++.\" .nh disable hyphenation ++.\" .hy enable hyphenation ++.\" .ad l left justify ++.\" .ad b justify to both left and right margins ++.\" .nf disable filling ++.\" .fi enable filling ++.\" .br insert line break ++.\" .sp insert n+1 empty lines ++.\" for manpage-specific macros, see man(7) ++.SH NAME ++get_cyclictest_snapshot \- Get a snapshot of running instances of cyclictest ++.SH SYNOPSIS ++.SY get_cyclictest_snapshot ++.OP [\-h]\ [\-l]\ [\-s\ [pid [pid ...]]] ++.br ++.OP [\-p\ [pid\ [pid ...]]] ++.SH OPTIONS ++Without options, this program will send USR2 to cyclictest to create a snapshot and then print it out. ++.br ++.TP ++Optional arguments: ++.TP ++.B -h, --help ++show this help message and exit ++.TP ++.B -l, --list ++list the main pid(s) of running instances of cyclictest ++.TP ++.B -s [pid [pid ...]], --snapshot [pid [pid ...]] ++take a snapshot of running instances of cyclictest ++.br ++by sending USR2 to cyclictest ++.TP ++.B -p [pid [pid ...]], --print [pid [pid ...]] ++print the snapshots ++.SH SEE ALSO ++.BR cyclictest (8), ++.SH AUTHOR ++get_cyclictest_snapshot was written by John Kacur +-- +2.21.3 + diff --git a/SOURCES/rt-tests-Install-new-man-page-get_cyclictest_snapshot.patch b/SOURCES/rt-tests-Install-new-man-page-get_cyclictest_snapshot.patch new file mode 100644 index 0000000..5dda144 --- /dev/null +++ b/SOURCES/rt-tests-Install-new-man-page-get_cyclictest_snapshot.patch @@ -0,0 +1,29 @@ +From 7731b805fa5a38e7e2dc0e551e102d2d5e6fa8d7 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 6 Jul 2020 23:19:24 -0400 +Subject: [PATCH] rt-tests: Install new man page get_cyclictest_snapshot.8 + +Install the new man page, get_cyclictest_snapshot.8 + +Signed-off-by: John Kacur +--- + Makefile | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 05fc5eda71fa..be7831277c88 100644 +--- a/Makefile ++++ b/Makefile +@@ -47,7 +47,8 @@ MANPAGES = src/cyclictest/cyclictest.8 \ + src/queuelat/queuelat.8 \ + src/sched_deadline/deadline_test.8 \ + src/ssdd/ssdd.8 \ +- src/sched_deadline/cyclicdeadline.8 ++ src/sched_deadline/cyclicdeadline.8 \ ++ src/cyclictest/get_cyclictest_snapshot.8 + + ifdef PYLIB + MANPAGES += src/hwlatdetect/hwlatdetect.8 +-- +2.21.3 + diff --git a/SOURCES/rt-tests-Set-affinity-before-applying-numa.patch b/SOURCES/rt-tests-Set-affinity-before-applying-numa.patch deleted file mode 100644 index 6ad027e..0000000 --- a/SOURCES/rt-tests-Set-affinity-before-applying-numa.patch +++ /dev/null @@ -1,110 +0,0 @@ -From e5f59a301e6585145c5b738a4e9327e943e16404 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Fri, 6 Sep 2019 20:59:42 +0200 -Subject: [PATCH 1/8] rt-tests: Set affinity before applying numa - -There are three changes here. - -1. If affinity is not specified, but numa is available, then numa -implies AFFINITY_USEALL. - -2. Move setting affinity before applying numa -We need to set the affinity before applying numa, so that we don't -apply numa settings to cpus we don't intend to run on. - -3. Allow a greater number of threads than cpus to run in a round robin -fashion in the case of numa. - -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.c | 34 +++++++++++++++++++++------------- - 1 file changed, 21 insertions(+), 13 deletions(-) - -diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c -index d101e3d14854..52f93da7d074 100644 ---- a/src/cyclictest/cyclictest.c -+++ b/src/cyclictest/cyclictest.c -@@ -1349,8 +1349,12 @@ static void process_options (int argc, char *argv[], int max_cpus) - /* if smp wasn't requested, test for numa automatically */ - if (!smp) { - #ifdef NUMA -- if (numa_available() != -1) -+ if (numa_available() != -1) { - numa = 1; -+ if (setaffinity == AFFINITY_UNSPECIFIED) { -+ setaffinity = AFFINITY_USEALL; -+ } -+ } - #else - warn("cyclictest was not built with the numa option\n"); - numa = 0; -@@ -1716,6 +1720,7 @@ int main(int argc, char **argv) - sigset_t sigset; - int signum = SIGALRM; - int mode; -+ int cpu; - int max_cpus = sysconf(_SC_NPROCESSORS_ONLN); - int i, ret = -1; - int status; -@@ -1877,6 +1882,16 @@ int main(int argc, char **argv) - if (status != 0) - fatal("error from pthread_attr_init for thread %d: %s\n", i, strerror(status)); - -+ switch (setaffinity) { -+ case AFFINITY_UNSPECIFIED: cpu = -1; break; -+ case AFFINITY_SPECIFIED: -+ cpu = cpu_for_thread(i, max_cpus); -+ if (verbose) -+ printf("Thread %d using cpu %d.\n", i, cpu); -+ break; -+ case AFFINITY_USEALL: cpu = i % max_cpus; break; -+ } -+ - node = -1; - if (numa) { - void *stack; -@@ -1884,7 +1899,7 @@ int main(int argc, char **argv) - size_t stksize; - - /* find the memory node associated with the cpu i */ -- node = rt_numa_numa_node_of_cpu(i); -+ node = rt_numa_numa_node_of_cpu(cpu); - - /* get the stack size set for for this thread */ - if (pthread_attr_getstack(&attr, &currstk, &stksize)) -@@ -1895,7 +1910,7 @@ int main(int argc, char **argv) - stksize = PTHREAD_STACK_MIN * 2; - - /* allocate memory for a stack on appropriate node */ -- stack = rt_numa_numa_alloc_onnode(stksize, node, i); -+ stack = rt_numa_numa_alloc_onnode(stksize, node, cpu); - - /* touch the stack pages to pre-fault them in */ - memset(stack, 0, stksize); -@@ -1965,20 +1980,13 @@ int main(int argc, char **argv) - interval += distance; - if (verbose) - printf("Thread %d Interval: %d\n", i, interval); -+ - par->max_cycles = max_cycles; - par->stats = stat; - par->node = node; - par->tnum = i; -- switch (setaffinity) { -- case AFFINITY_UNSPECIFIED: par->cpu = -1; break; -- case AFFINITY_SPECIFIED: -- par->cpu = cpu_for_thread(i, max_cpus); -- if (verbose) -- printf("Thread %d using cpu %d.\n", i, -- par->cpu); -- break; -- case AFFINITY_USEALL: par->cpu = i % max_cpus; break; -- } -+ par->cpu = cpu; -+ - stat->min = 1000000; - stat->max = 0; - stat->avg = 0.0; --- -2.20.1 - diff --git a/SOURCES/rt-tests-Tweak-the-cyclictest-man-page.patch b/SOURCES/rt-tests-Tweak-the-cyclictest-man-page.patch new file mode 100644 index 0000000..5ed211b --- /dev/null +++ b/SOURCES/rt-tests-Tweak-the-cyclictest-man-page.patch @@ -0,0 +1,29 @@ +From 89f9ce00774c02388bd29e0da05147282d24830e Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 6 Jul 2020 13:21:42 -0400 +Subject: [PATCH 5/7] rt-tests: Tweak the cyclictest man page + +Tweak the cyclictest man page with the .SY macro to make the cyclictest +command stand out apart from the options + +Signed-off-by: John Kacur +--- + src/cyclictest/cyclictest.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cyclictest/cyclictest.8 b/src/cyclictest/cyclictest.8 +index 00e2d2403996..44b5d0dbcc4a 100644 +--- a/src/cyclictest/cyclictest.8 ++++ b/src/cyclictest/cyclictest.8 +@@ -15,7 +15,7 @@ + .SH NAME + cyclictest \- High resolution test program + .SH SYNOPSIS +-.B cyclictest ++.SY cyclictest + .RI "[ \-hfmnqrsvMS ] [\-a " proc " ] [\-A " align " ] [\-b " usec " ] [\-c " clock " ] [\-d " dist " ] \ + [\-h " histogram " ] [\-i " intv " ] [\-l " loop " ] [\-o " red " ] [\-p " prio " ] \ + [\-t " num " ] [\-D " time "] [\-w] [\-W] [\-y " policy " ] [ \-S | \-U ]" +-- +2.21.3 + diff --git a/SOURCES/rt-tests-cyclicdeadline-Add-a-simple-manpage.patch b/SOURCES/rt-tests-cyclicdeadline-Add-a-simple-manpage.patch deleted file mode 100644 index 7e8fcf5..0000000 --- a/SOURCES/rt-tests-cyclicdeadline-Add-a-simple-manpage.patch +++ /dev/null @@ -1,90 +0,0 @@ -From f90391d1907279150c15c5e0afeeb4291943f636 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 16 Jan 2020 17:59:26 +0100 -Subject: [PATCH] rt-tests: cyclicdeadline: Add a simple manpage for - cyclicdeadline - -- Add a simple manpage for cyclicdeadline -- Install it from the Makefile - -Signed-off-by: John Kacur ---- - Makefile | 1 + - src/sched_deadline/cyclicdeadline.8 | 53 +++++++++++++++++++++++++++++ - 2 files changed, 54 insertions(+) - create mode 100644 src/sched_deadline/cyclicdeadline.8 - -diff --git a/Makefile b/Makefile -index 552b3fe885cc..e2142ba3f4e9 100644 ---- a/Makefile -+++ b/Makefile -@@ -193,6 +193,7 @@ install: all install_hwlatdetect - gzip -c src/queuelat/queuelat.8 >"$(DESTDIR)$(mandir)/man8/queuelat.8.gz" - gzip -c src/sched_deadline/deadline_test.8 >"$(DESTDIR)$(mandir)/man8/deadline_test.8.gz" - gzip -c src/ssdd/ssdd.8 >"$(DESTDIR)$(mandir)/man8/ssdd.8.gz" -+ gzip -c src/sched_deadline/cyclicdeadline.8 >"$(DESTDIR)$(mandir)/man8/cyclicdeadline.8.gz" - - .PHONY: install_hwlatdetect - install_hwlatdetect: hwlatdetect -diff --git a/src/sched_deadline/cyclicdeadline.8 b/src/sched_deadline/cyclicdeadline.8 -new file mode 100644 -index 000000000000..91766fb391c4 ---- /dev/null -+++ b/src/sched_deadline/cyclicdeadline.8 -@@ -0,0 +1,53 @@ -+.\" Hey, EMACS: -*- nroff -*- -+.TH CYCLICDEADLINE 8 "January 16, 2020" -+.\" Please adjust this date whenever revising the manpage. -+.\" -+.\" Some roff macros, for reference: -+.\" .nh disable hyphenation -+.\" .hy enable hyphenation -+.\" .ad l left justify -+.\" .ad b justify to both left and right margins -+.\" .nf disable filling -+.\" .fi enable filling -+.\" .br insert line break -+.\" .sp insert n+1 empty lines -+.\" for manpage-specific macros, see man(7) -+.SH NAME -+cyclicdeadline \- This program is used to test the deadline scheduler (SCHED_DEADLINE) using a cyclictest style program -+.PP -+.SH SYNOPSIS -+.B cyclicdeadline -+.RI "[-ha] [-c cpulist] [-i interval] [-s step] [-t nr_threads] [-D duration] -+.PP -+.SH DESCRIPTION -+.B cyclicdeadline -+is a cyclictest style program for testing the deadline scheduler -+.PP -+.SH OPTIONS -+.TP -+.B \-h -+Show this help menu -+.TP -+.B \-a -+Use all CPUs -+.TP -+.B \-c cpulist -+Comma / hypen separated list of CPUs to run deadline tasks on -+.TP -+.B \-i interval -+The shortest deadline for the tasks in us. (default 1000us) -+.TP -+.B \-s step -+The amount to increase the deadline for each task in us. (default 500us) -+.TP -+.B \-t nr_threads -+The number of threads to run as deadline (default 1) -+.TP -+.B \-D time -+Specify a length for the test to run -+.br -+Append 'm', 'h', or 'd' to specify minutes, hours, or days -+.SH AUTHOR -+cyclicdeadline was written by Steven Rostedt -+.PP -+This manual page was written by John Kacur --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Assume-libnuma-version-2-by-defa.patch b/SOURCES/rt-tests-cyclictest-Assume-libnuma-version-2-by-defa.patch deleted file mode 100644 index cd97daf..0000000 --- a/SOURCES/rt-tests-cyclictest-Assume-libnuma-version-2-by-defa.patch +++ /dev/null @@ -1,32 +0,0 @@ -From bb93611dd8248c0a4c05b9ccd9a93a78432044d7 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 19 Sep 2019 20:19:17 +0200 -Subject: [PATCH 7/8] rt-tests: cyclictest: Assume libnuma version 2 by default - -Most distributions have used libnuma version 2 for awhile now, so make -it the default. - -This doesn't prevent people from defining it as version 1, or compiling -without numa. - -Signed-off-by: John Kacur ---- - src/cyclictest/rt_numa.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/cyclictest/rt_numa.h b/src/cyclictest/rt_numa.h -index e0f4b2e9d8b2..7adeb3c01324 100644 ---- a/src/cyclictest/rt_numa.h -+++ b/src/cyclictest/rt_numa.h -@@ -29,7 +29,7 @@ static int numa = 0; - #include - - #ifndef LIBNUMA_API_VERSION --#define LIBNUMA_API_VERSION 1 -+#define LIBNUMA_API_VERSION 2 - #endif - - static void * --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Don-t-allow-OPT_SYSTEM-with-OPT_POSIX_TIMERS.patch b/SOURCES/rt-tests-cyclictest-Don-t-allow-OPT_SYSTEM-with-OPT_POSIX_TIMERS.patch deleted file mode 100644 index 824937b..0000000 --- a/SOURCES/rt-tests-cyclictest-Don-t-allow-OPT_SYSTEM-with-OPT_POSIX_TIMERS.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 0bf35a2fb58177318353c3a2e02df5b20728d5b9 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 16 Sep 2019 23:43:32 +0200 -Subject: [PATCH 5/8] rt-tests: cyclictest: Don't allow OPT_SYSTEM with - OPT_POSIX_TIMERS - -OPT_SYSTEM means use sys_nanosleep and sys_setitimer -if you try to combine it with OPT_POSIX_TIMERS, it breaks. - -cyclictest becomes unkillable with ctrl-C and only the first thread is -updated. - -Fix this by issuing a warning if the user tries to combine the two -options and then use clock_nanosleep. - -Reported-by: Tom Rix -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c -index 3a78912b34f8..6be0525822ca 100644 ---- a/src/cyclictest/cyclictest.c -+++ b/src/cyclictest/cyclictest.c -@@ -1353,6 +1353,13 @@ static void process_options (int argc, char *argv[], int max_cpus) - } - } - -+ if ((use_system == MODE_SYS_OFFSET) && (use_nanosleep == MODE_CYCLIC)) { -+ warn("The system option requires clock_nanosleep\n"); -+ warn("and is not compatible with posix_timers\n"); -+ warn("Using clock_nanosleep\n"); -+ use_nanosleep = MODE_CLOCK_NANOSLEEP; -+ } -+ - /* if smp wasn't requested, test for numa automatically */ - if (!smp) { - #ifdef NUMA --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Fix-warning-cpu-may-be-used-uninitialized.patch b/SOURCES/rt-tests-cyclictest-Fix-warning-cpu-may-be-used-uninitialized.patch deleted file mode 100644 index 5501b51..0000000 --- a/SOURCES/rt-tests-cyclictest-Fix-warning-cpu-may-be-used-uninitialized.patch +++ /dev/null @@ -1,33 +0,0 @@ -From f70d5f0de62114cfcd8d8b5032138111730665e6 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 16 Sep 2019 21:06:28 +0200 -Subject: [PATCH 4/8] =?UTF-8?q?rt-tests:=20cyclictest:=20Fix=20=20warning:?= - =?UTF-8?q?=20=E2=80=98cpu=E2=80=99=20may=20be=20used=20uninitialized?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Fix warning 'cpu' maybe uninitialized by giving it a default value in -the switch statement. Note, this is a false positive, but documenting -the default value in the switch statement isn't a bad thing. - -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c -index 72fb35da3238..3a78912b34f8 100644 ---- a/src/cyclictest/cyclictest.c -+++ b/src/cyclictest/cyclictest.c -@@ -1897,6 +1897,7 @@ int main(int argc, char **argv) - printf("Thread %d using cpu %d.\n", i, cpu); - break; - case AFFINITY_USEALL: cpu = i % max_cpus; break; -+ default: cpu = -1; - } - - node = -1; --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Get-a-snapshot-of-cyclictest.patch b/SOURCES/rt-tests-cyclictest-Get-a-snapshot-of-cyclictest.patch deleted file mode 100644 index 6452685..0000000 --- a/SOURCES/rt-tests-cyclictest-Get-a-snapshot-of-cyclictest.patch +++ /dev/null @@ -1,294 +0,0 @@ -From 26bd002f00753b3b6aa857eeee62c051a15b6fa5 Mon Sep 17 00:00:00 2001 -From: John Kacur -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 ---- - 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 - diff --git a/SOURCES/rt-tests-cyclictest-Just-use-LIBNUMA_API_VERSION-2.patch b/SOURCES/rt-tests-cyclictest-Just-use-LIBNUMA_API_VERSION-2.patch deleted file mode 100644 index 0c41da0..0000000 --- a/SOURCES/rt-tests-cyclictest-Just-use-LIBNUMA_API_VERSION-2.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 97632deddf783249e0e3d34630792c7696b7d5d5 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Tue, 24 Sep 2019 19:37:48 +0200 -Subject: [PATCH 8/8] rt-tests: cyclictest: Just use LIBNUMA_API_VERSION 2 - -This removes support for LIBNUMA_API_VERSION 1. - -You can still build without numa support by doing -make NUMA=0 - -You can also build with numa and run on machines without numa support. - -Suggested-by: Sebastian Siewior -Signed-off-by: John Kacur ---- - src/cyclictest/rt_numa.h | 98 +--------------------------------------- - 1 file changed, 1 insertion(+), 97 deletions(-) - -diff --git a/src/cyclictest/rt_numa.h b/src/cyclictest/rt_numa.h -index 7adeb3c01324..983502d34c94 100644 ---- a/src/cyclictest/rt_numa.h -+++ b/src/cyclictest/rt_numa.h -@@ -1,16 +1,7 @@ - /* - * A numa library for cyclictest. - * The functions here are designed to work whether cyclictest has been -- * compiled with numa support or not, and whether the user uses the --numa -- * option or not. -- * They should also work correctly with older versions of the numactl lib -- * such as the one found on RHEL5, or with the newer version 2 and above. -- * -- * The difference in behavior hinges on whether LIBNUMA_API_VERSION >= 2, -- * in which case we will employ the bitmask affinity behavior -or- -- * either LIBNUMA_API_VERSION < 2 or NUMA support is missing altogether, -- * in which case we retain the older affinity behavior which can either -- * specify a single CPU core or else use all cores. -+ * compiled with numa support or not. - * - * (C) 2010 John Kacur - * (C) 2010 Clark Williams -@@ -28,10 +19,6 @@ static int numa = 0; - #ifdef NUMA - #include - --#ifndef LIBNUMA_API_VERSION --#define LIBNUMA_API_VERSION 2 --#endif -- - static void * - threadalloc(size_t size, int node) - { -@@ -69,8 +56,6 @@ static void *rt_numa_numa_alloc_onnode(size_t size, int node, int cpu) - return stack; - } - --#if LIBNUMA_API_VERSION >= 2 -- - /* - * Use new bit mask CPU affinity behavior - */ -@@ -110,87 +95,6 @@ static inline void rt_bitmask_free(struct bitmask *mask) - numa_bitmask_free(mask); - } - --#else /* LIBNUMA_API_VERSION == 1 */ -- --struct bitmask { -- unsigned long size; /* number of bits in the map */ -- unsigned long *maskp; --}; --#define BITS_PER_LONG (8*sizeof(long)) -- --/* -- * Map legacy CPU affinity behavior onto bit mask infrastructure -- */ --static int rt_numa_numa_node_of_cpu(int cpu) --{ -- unsigned char cpumask[256]; -- int node, idx, bit; -- int max_node, max_cpus; -- -- max_node = numa_max_node(); -- max_cpus = sysconf(_SC_NPROCESSORS_ONLN); -- -- if (cpu > max_cpus) { -- errno = EINVAL; -- return -1; -- } -- -- /* calculate bitmask index and relative bit position of cpu */ -- idx = cpu / 8; -- bit = cpu % 8; -- -- for (node = 0; node <= max_node; node++) { -- if (numa_node_to_cpus(node, (void *) cpumask, sizeof(cpumask))) -- return -1; -- -- if (cpumask[idx] & (1<maskp[i/BITS_PER_LONG] & (1<<(i % BITS_PER_LONG)); -- return (bit != 0); --} -- --static inline struct bitmask* rt_numa_parse_cpustring(const char* s, -- int max_cpus) --{ -- int cpu; -- struct bitmask *mask = NULL; -- cpu = atoi(s); -- if (0 <= cpu && cpu < max_cpus) { -- mask = malloc(sizeof(*mask)); -- if (mask) { -- /* Round up to integral number of longs to contain -- * max_cpus bits */ -- int nlongs = (max_cpus+BITS_PER_LONG-1)/BITS_PER_LONG; -- -- mask->maskp = calloc(nlongs, sizeof(long)); -- if (mask->maskp) { -- mask->maskp[cpu/BITS_PER_LONG] |= -- (1UL << (cpu % BITS_PER_LONG)); -- mask->size = max_cpus; -- } else { -- free(mask); -- mask = NULL; -- } -- } -- } -- return mask; --} -- --static inline void rt_bitmask_free(struct bitmask *mask) --{ -- free(mask->maskp); -- free(mask); --} -- --#endif /* LIBNUMA_API_VERSION */ - - #else /* ! NUMA */ - --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Make-tracemark-work-correctly-ag.patch b/SOURCES/rt-tests-cyclictest-Make-tracemark-work-correctly-ag.patch deleted file mode 100644 index 33765ee..0000000 --- a/SOURCES/rt-tests-cyclictest-Make-tracemark-work-correctly-ag.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 33f07f6ee2053dc16dd667c763326515e87f19e3 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 16 Sep 2019 20:37:22 +0200 -Subject: [PATCH] rt-tests: cyclictest: Make tracemark work correctly again - -commit f5ccfbe4d6641e48f56152be135d901dd31cba7e -was a little too aggressive removing ftrace code. - -We were able to remove ftrace code because this functionality is -available using trace-cmd, in conjunction with the tracemark option in -cyclictest. Put back the parts of tracemark needed to make this work -correctly. - -After this patch you can get tracing info like this as an example. - -trace-cmd record -p function ./cyclictest -t -b100 --tracemark - -Signed-off-by: John Kacur - -Corrected a typo -Reported-by: Kurt Kanzenbach -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c -index 52f93da7d074..72fb35da3238 100644 ---- a/src/cyclictest/cyclictest.c -+++ b/src/cyclictest/cyclictest.c -@@ -184,6 +184,7 @@ static void trigger_update(struct thread_param *par, int diff, int64_t ts); - - static int shutdown; - static int tracelimit = 0; -+static int trace_marker = 0; - static int verbose = 0; - static int oscope_reduction = 1; - static int lockall = 0; -@@ -400,6 +401,9 @@ static void debugfs_prepare(void) - - static void enable_trace_mark(void) - { -+ if (!trace_marker) -+ return; -+ - debugfs_prepare(); - open_tracemark_fd(); - } -@@ -1167,6 +1171,7 @@ static void process_options (int argc, char *argv[], int max_cpus) - {"spike", required_argument, NULL, OPT_TRIGGER }, - {"spike-nodes", required_argument, NULL, OPT_TRIGGER_NODES }, - {"threads", optional_argument, NULL, OPT_THREADS }, -+ {"tracemark", no_argument, NULL, OPT_TRACEMARK }, - {"unbuffered", no_argument, NULL, OPT_UNBUFFERED }, - {"verbose", no_argument, NULL, OPT_VERBOSE }, - {"dbg_cyclictest", no_argument, NULL, OPT_DBGCYCLIC }, -@@ -1343,6 +1348,8 @@ static void process_options (int argc, char *argv[], int max_cpus) - fatal("--smi is not available on your arch\n"); - #endif - break; -+ case OPT_TRACEMARK: -+ trace_marker = 1; break; - } - } - --- -2.20.1 - diff --git a/SOURCES/rt-tests-cyclictest-Move-ftrace-helpers-into-rt-util.patch b/SOURCES/rt-tests-cyclictest-Move-ftrace-helpers-into-rt-util.patch new file mode 100644 index 0000000..99112be --- /dev/null +++ b/SOURCES/rt-tests-cyclictest-Move-ftrace-helpers-into-rt-util.patch @@ -0,0 +1,259 @@ +From dc433f68c9f19eb0a28e0f00342dfd33f319f0fa Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Mon, 17 Aug 2020 17:55:04 -0400 +Subject: [PATCH 1/2] rt-tests: cyclictest: Move ftrace helpers into + rt-utils.[ch] + +Then they can be further used by other programs too. + +Two trivial things to mention. + +Firstly, move trace_marker out of enable_trace_mark(). No functional change. + +Secondly, remove the fileprefix setting in process_options(), because if +tracelimit is non-zero, fileprefix will be after all replaced by a further call +to get_debugfileprefix() in debugfs_prepare(). + +Signed-off-by: Peter Xu +Signed-off-by: John Kacur +--- + src/cyclictest/cyclictest.c | 90 +------------------------------------ + src/include/rt-utils.h | 3 ++ + src/lib/rt-utils.c | 82 +++++++++++++++++++++++++++++++++ + 3 files changed, 86 insertions(+), 89 deletions(-) + +diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c +index eb61be394f2e..dd418939a0c2 100644 +--- a/src/cyclictest/cyclictest.c ++++ b/src/cyclictest/cyclictest.c +@@ -219,8 +219,6 @@ static pthread_barrier_t align_barr; + static pthread_barrier_t globalt_barr; + static struct timespec globalt; + +-static char *procfileprefix = "/proc/sys/kernel/"; +-static char *fileprefix; + static char fifopath[MAX_PATH]; + static char histfile[MAX_PATH]; + +@@ -330,89 +328,6 @@ static inline int64_t calctime(struct timespec t) + return time; + } + +-static int trace_file_exists(char *name) +-{ +- struct stat sbuf; +- char *tracing_prefix = get_debugfileprefix(); +- char path[MAX_PATH]; +- strcat(strcpy(path, tracing_prefix), name); +- return stat(path, &sbuf) ? 0 : 1; +-} +- +-#define TRACEBUFSIZ 1024 +-static __thread char tracebuf[TRACEBUFSIZ]; +- +-static void tracemark(char *fmt, ...) __attribute__((format(printf, 1, 2))); +-static void tracemark(char *fmt, ...) +-{ +- va_list ap; +- int len; +- +- /* bail out if we're not tracing */ +- /* or if the kernel doesn't support trace_mark */ +- if (tracemark_fd < 0 || trace_fd < 0) +- return; +- +- va_start(ap, fmt); +- len = vsnprintf(tracebuf, TRACEBUFSIZ, fmt, ap); +- va_end(ap); +- +- /* write the tracemark message */ +- write(tracemark_fd, tracebuf, len); +- +- /* now stop any trace */ +- write(trace_fd, "0\n", 2); +-} +- +-static void open_tracemark_fd(void) +-{ +- char path[MAX_PATH]; +- +- /* +- * open the tracemark file if it's not already open +- */ +- if (tracemark_fd < 0) { +- sprintf(path, "%s/%s", fileprefix, "trace_marker"); +- tracemark_fd = open(path, O_WRONLY); +- if (tracemark_fd < 0) { +- warn("unable to open trace_marker file: %s\n", path); +- return; +- } +- } +- +- /* +- * if we're not tracing and the tracing_on fd is not open, +- * open the tracing_on file so that we can stop the trace +- * if we hit a breaktrace threshold +- */ +- if (trace_fd < 0) { +- sprintf(path, "%s/%s", fileprefix, "tracing_on"); +- if ((trace_fd = open(path, O_WRONLY)) < 0) +- warn("unable to open tracing_on file: %s\n", path); +- } +-} +- +-static void debugfs_prepare(void) +-{ +- if (mount_debugfs(NULL)) +- fatal("could not mount debugfs"); +- +- fileprefix = get_debugfileprefix(); +- if (!trace_file_exists("tracing_enabled") && +- !trace_file_exists("tracing_on")) +- warn("tracing_enabled or tracing_on not found\n" +- "debug fs not mounted"); +-} +- +-static void enable_trace_mark(void) +-{ +- if (!trace_marker) +- return; +- +- debugfs_prepare(); +- open_tracemark_fd(); +-} +- + /* + * Raise the soft priority limit up to prio, if that is less than or equal + * to the hard limit +@@ -1498,9 +1413,6 @@ static void process_options (int argc, char *argv[], int max_cpus) + "on this processor\n"); + } + +- if (tracelimit) +- fileprefix = procfileprefix; +- + if (clocksel < 0 || clocksel > ARRAY_SIZE(clocksources)) + error = 1; + +@@ -2065,7 +1977,7 @@ int main(int argc, char **argv) + /* use the /dev/cpu_dma_latency trick if it's there */ + set_latency_target(); + +- if (tracelimit) ++ if (tracelimit && trace_marker) + enable_trace_mark(); + + if (check_timer()) +diff --git a/src/include/rt-utils.h b/src/include/rt-utils.h +index 6ec2b2011959..51489b408e6c 100644 +--- a/src/include/rt-utils.h ++++ b/src/include/rt-utils.h +@@ -27,4 +27,7 @@ pid_t gettid(void); + + int parse_time_string(char *val); + ++void enable_trace_mark(void); ++void tracemark(char *fmt, ...) __attribute__((format(printf, 1, 2))); ++ + #endif /* __RT_UTILS.H */ +diff --git a/src/lib/rt-utils.c b/src/lib/rt-utils.c +index 1998a327d036..f786588706cd 100644 +--- a/src/lib/rt-utils.c ++++ b/src/lib/rt-utils.c +@@ -24,7 +24,13 @@ + #include "rt-sched.h" + #include "error.h" + ++#define TRACEBUFSIZ 1024 ++ + static char debugfileprefix[MAX_PATH]; ++static char *fileprefix; ++static int trace_fd = -1; ++static int tracemark_fd = -1; ++static __thread char tracebuf[TRACEBUFSIZ]; + + /* + * Finds the tracing directory in a mounted debugfs +@@ -355,3 +361,79 @@ int parse_time_string(char *val) + } + return t; + } ++ ++void open_tracemark_fd(void) ++{ ++ char path[MAX_PATH]; ++ ++ /* ++ * open the tracemark file if it's not already open ++ */ ++ if (tracemark_fd < 0) { ++ sprintf(path, "%s/%s", fileprefix, "trace_marker"); ++ tracemark_fd = open(path, O_WRONLY); ++ if (tracemark_fd < 0) { ++ warn("unable to open trace_marker file: %s\n", path); ++ return; ++ } ++ } ++ ++ /* ++ * if we're not tracing and the tracing_on fd is not open, ++ * open the tracing_on file so that we can stop the trace ++ * if we hit a breaktrace threshold ++ */ ++ if (trace_fd < 0) { ++ sprintf(path, "%s/%s", fileprefix, "tracing_on"); ++ if ((trace_fd = open(path, O_WRONLY)) < 0) ++ warn("unable to open tracing_on file: %s\n", path); ++ } ++} ++ ++int trace_file_exists(char *name) ++{ ++ struct stat sbuf; ++ char *tracing_prefix = get_debugfileprefix(); ++ char path[MAX_PATH]; ++ strcat(strcpy(path, tracing_prefix), name); ++ return stat(path, &sbuf) ? 0 : 1; ++} ++ ++void debugfs_prepare(void) ++{ ++ if (mount_debugfs(NULL)) ++ fatal("could not mount debugfs"); ++ ++ fileprefix = get_debugfileprefix(); ++ if (!trace_file_exists("tracing_enabled") && ++ !trace_file_exists("tracing_on")) ++ warn("tracing_enabled or tracing_on not found\n" ++ "debug fs not mounted"); ++} ++ ++void tracemark(char *fmt, ...) ++{ ++ va_list ap; ++ int len; ++ ++ /* bail out if we're not tracing */ ++ /* or if the kernel doesn't support trace_mark */ ++ if (tracemark_fd < 0 || trace_fd < 0) ++ return; ++ ++ va_start(ap, fmt); ++ len = vsnprintf(tracebuf, TRACEBUFSIZ, fmt, ap); ++ va_end(ap); ++ ++ /* write the tracemark message */ ++ write(tracemark_fd, tracebuf, len); ++ ++ /* now stop any trace */ ++ write(trace_fd, "0\n", 2); ++} ++ ++void enable_trace_mark(void) ++{ ++ debugfs_prepare(); ++ open_tracemark_fd(); ++} +-- +2.26.2 + diff --git a/SOURCES/rt-tests-cyclictest-remove-the-debug-log-pid-xxx-in-.patch b/SOURCES/rt-tests-cyclictest-remove-the-debug-log-pid-xxx-in-.patch new file mode 100644 index 0000000..9efe7e8 --- /dev/null +++ b/SOURCES/rt-tests-cyclictest-remove-the-debug-log-pid-xxx-in-.patch @@ -0,0 +1,32 @@ +From caaec484d88fe4dfc1f83b8ce2e2ff1167193517 Mon Sep 17 00:00:00 2001 +From: Yunfeng Ye +Date: Thu, 2 Jul 2020 10:22:21 +0800 +Subject: [PATCH] rt-tests: cyclictest: remove the debug log "pid = xxx" in + rstat_shm_open() + +The infomation "pid = xxx" is printed with other infomation on the same +line. so remove this left over debug message in rstat_shm_open(). + +Signed-off-by: yeyunfeng + +Edited the descriptioin in the log a little bit. +Signed-off-by: John Kacur +--- + src/cyclictest/cyclictest.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c +index 79bb1cb71c68..eb61be394f2e 100644 +--- a/src/cyclictest/cyclictest.c ++++ b/src/cyclictest/cyclictest.c +@@ -1921,7 +1921,6 @@ static int rstat_shm_open(void) + pid_t pid; + + pid = getpid(); +- printf("pid = %d", pid); + + snprintf(shm_name, SHM_BUF_SIZE, "%s%d", "/cyclictest", pid); + +-- +2.21.3 + diff --git a/SOURCES/rt-tests-cyclictest.8-Remove-invalid-tracing-options.patch b/SOURCES/rt-tests-cyclictest.8-Remove-invalid-tracing-options.patch deleted file mode 100644 index 7289707..0000000 --- a/SOURCES/rt-tests-cyclictest.8-Remove-invalid-tracing-options.patch +++ /dev/null @@ -1,117 +0,0 @@ -From abc74dca458bb81b81ad40efecda69a6fa28fd3c Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Sat, 14 Sep 2019 04:57:35 +0200 -Subject: [PATCH] rt-tests: cyclictest.8: Remove invalid tracing options from - the manpage - -Most tracing options have been removed from cyclictest since the -user can now use trace-cmd together with cyclictest to get the same -functionality. Update the manpage to reflect this. - -Reported-by: Tom Rix -Signed-off-by: John Kacur ---- - src/cyclictest/cyclictest.8 | 35 ----------------------------------- - 1 file changed, 35 deletions(-) - -diff --git a/src/cyclictest/cyclictest.8 b/src/cyclictest/cyclictest.8 -index a05d1f4c9d4a..b64a16ae8bbb 100644 ---- a/src/cyclictest/cyclictest.8 -+++ b/src/cyclictest/cyclictest.8 -@@ -52,9 +52,6 @@ Align thread wakeups to a specific offset in microseconds - .B \-b, \-\-breaktrace=USEC - Send break trace command when latency > USEC - .TP --.B \-B, \-\-preemptirqs --Both preempt and irqsoff tracing (used with -b) --.TP - .B \-c, \-\-clock=CLOCK - select clock - .br -@@ -62,9 +59,6 @@ select clock - .br - 1 = CLOCK_REALTIME - .TP --.B \-C, \-\-context --context switch tracing (used with \-b) --.TP - .B \-d, \-\-distance=DIST - Distance of thread intervals in us, default = 500 - .TP -@@ -73,12 +67,6 @@ Specify a length for the test run. - .br - Append 'm', 'h', or 'd' to specify minutes, hours or days. - .TP --.B \-E, \-\-event --event tracing (used with \-b) --.TP --.B \-f, \-\-ftrace --Enable function tracing using ftrace as tracer. This option is available only with \-b. --.TP - .B \-F, \-\-fifo= - Create a named pipe at path and write stats to it - .TP -@@ -94,9 +82,6 @@ Dump the latency histogram to instead of stdout. - .B \-i, \-\-interval=INTV - Set the base interval of the thread(s) in microseconds (default is 1000us). This sets the interval of the first thread. See also \-d. - .TP --.B \-I, \-\-irqsoff --Irgsoff tracing (used with \-b) --.TP - .B \-l, \-\-loops=LOOPS - Set the number of loops. The default is 0 (endless). This option is useful for automated tests with a given number of test cycles. Cyclictest is stopped once the number of timer intervals has been reached. - .TP -@@ -113,26 +98,16 @@ running cyclictest on low-bandwidth connections) - .B \-n, \-\-nanosleep - Use clock_nanosleep instead of posix interval timers. Setting this option runs the tests with clock_nanosleep instead of posix interval timers. - .TP --.B \-\-notrace --suppress tracing --.TP - .B \-N, \-\-nsecs - Show results in nanoseconds instead of microseconds, which is the default unit. - .TP - .B \-o, \-\-oscope=RED - Oscilloscope mode, reduce verbose output by RED. - .TP --.B \-O, \-\-traceopt=TRACING_OPTION --Used to pass tracing options to ftrace tracers. May be invoked multiple --times for multiple trace options. For example trace options look at /sys/kernel/debug/tracing/trace_options --.TP - .B \-p, \-\-prio=PRIO - Set the priority of the first thread. The given priority is set to the first test thread. Each further thread gets a lower priority: - Priority(Thread N) = max(Priority(Thread N\-1) \- 1, 0) - .TP --.B \-P, \-\-preemptoff --Preempt off tracing (used with -b) --.TP - .B \-\-policy=NAME - set the scheduler policy of the measurement threads - where NAME is one of: other, normal, batch, idle, fifo, rr -@@ -178,10 +153,6 @@ the number of available CPUs. See \-d, \-i and \-p for further information. - .B \-\-tracemark - write a trace mark when \-b latency is exceeded. - .TP --.B \-T, \-\-tracer=TRACEFUNC --set the ftrace tracer function. Used with the \-b option. Must be one --of the trace functions available from /kernel/debug/tracing/available_tracers --.TP - .B \-u, \-\-unbuffered - force unbuffered output for live processing - .TP -@@ -192,12 +163,6 @@ n:c:v - - where n=task number c=count v=latency value in us. - .TP --.B \\-w, \-\-wakeup --task wakeup tracing (used with \-b) --.TP --.B \\-W, \-\-wakeuprt --rt-task wakeup tracing (used with \-b) --.TP - .B \-\-dbg_cyclictest - Print info userful for debugging cyclictest - --- -2.20.1 - diff --git a/SOURCES/rt-tests-determine_maximum_mpps.sh-Fix-quoting-and-o.patch b/SOURCES/rt-tests-determine_maximum_mpps.sh-Fix-quoting-and-o.patch deleted file mode 100644 index e2fd822..0000000 --- a/SOURCES/rt-tests-determine_maximum_mpps.sh-Fix-quoting-and-o.patch +++ /dev/null @@ -1,165 +0,0 @@ -From f19e2cbc5f811acbdbcb0eb4a2ec745e0e1804d8 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Fri, 17 Jan 2020 04:04:27 +0100 -Subject: [PATCH 4/5] rt-tests: determine_maximum_mpps.sh: Fix quoting and - other shell issue - -Fix a number of issues in the script determine_maximum_mpps.sh such as -1. Convert legacy backticks to $(...) notation -2. Double quote where necessary to prevent globbing -3. Double quote where necessary to prevent word splitting. - -Note: these fixes are more than just cosmetic, they are needed for the -script to work correctly. - -Signed-off-by: John Kacur ---- - src/queuelat/determine_maximum_mpps.sh | 75 +++++++++++++------------- - 1 file changed, 38 insertions(+), 37 deletions(-) - -diff --git a/src/queuelat/determine_maximum_mpps.sh b/src/queuelat/determine_maximum_mpps.sh -index f6cf1dea27cf..f785147f1bbd 100755 ---- a/src/queuelat/determine_maximum_mpps.sh -+++ b/src/queuelat/determine_maximum_mpps.sh -@@ -17,65 +17,65 @@ echo "Determining maximum mpps the machine can handle" - echo "Will take a few minutes to determine mpps value" - echo "And 10 minutes run to confirm the final mpps value is stable" - --for mpps in `seq 3 3 50`; do -- echo testing $mpps Mpps -+for mpps in $(seq 3 3 50); do -+ echo testing "$mpps" Mpps - -- OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -+ OUTFILE=$(mktemp) -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(sh get_cpuinfo_mhz.sh)" -p "$mpps" -t 30 > "$OUTFILE" - -- exceeded=`grep exceeded $OUTFILE` -+ exceeded=$(grep exceeded "$OUTFILE") - if [ ! -z "$exceeded" ]; then -- echo mpps failed: $mpps -+ echo mpps failed: "$mpps" - break; - fi - echo success - done --echo first loop mpps: $mpps -+echo first loop mpps: "$mpps" - - first_mpps=$(($mpps - 1)) --for mpps in `seq $first_mpps -1 3`; do -- echo testing $mpps Mpps -+for mpps in $(seq $first_mpps -1 3); do -+ echo testing "$mpps" Mpps - -- OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -+ OUTFILE=$(mktemp) -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(sh get_cpuinfo_mhz.sh)" -p "$mpps" -t 30 > "$OUTFILE" - -- exceeded=`grep exceeded $OUTFILE` -+ exceeded=$(grep exceeded "$OUTFILE") - if [ -z "$exceeded" ]; then -- echo mpps success $mpps -+ echo mpps success "$mpps" - break; - fi - echo failure - done - --second_mpps=`echo "$mpps + 0.3" | bc` --echo second loop mpps: $mpps -+second_mpps=$(echo "$mpps + 0.3" | bc) -+echo second loop mpps: "$mpps" - --for mpps in `seq $second_mpps 0.3 $first_mpps`; do -- echo testing $mpps Mpps -+for mpps in $(seq "$second_mpps" 0.3 $first_mpps); do -+ echo testing "$mpps" Mpps - -- OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -+ OUTFILE=$(mktemp) -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(sh get_cpuinfo_mhz.sh)" -p "$mpps" -t 30 > "$OUTFILE" - -- exceeded=`grep exceeded $OUTFILE` -+ exceeded=$(grep exceeded "$OUTFILE") - if [ ! -z "$exceeded" ]; then -- echo mpps failure $mpps -+ echo mpps failure "$mpps" - break; - fi - echo success - done - --echo third loop mpps: $mpps --third_mpps=`echo "$mpps -0.1" | bc` -+echo third loop mpps: "$mpps" -+third_mpps=$(echo "$mpps -0.1" | bc) - --for mpps in `seq $third_mpps -0.1 3`; do -- echo testing $mpps Mpps -+for mpps in $(seq "$third_mpps" -0.1 3); do -+ echo testing "$mpps" Mpps - -- OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -+ OUTFILE=$(mktemp) -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(sh get_cpuinfo_mhz.sh)" -p "$mpps" -t 30 > "$OUTFILE" - -- exceeded=`grep exceeded $OUTFILE` -+ exceeded=$(grep exceeded "$OUTFILE") - if [ -z "$exceeded" ]; then -- echo mpps success $mpps -+ echo mpps success "$mpps" - break; - fi - echo failure -@@ -89,14 +89,14 @@ while [ $queuelat_failure == 1 ]; do - echo -n "Starting 10 runs of 30 seconds with " - echo "$mpps Mpps" - -- for i in `seq 1 10`; do -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -- exceeded=`grep exceeded $OUTFILE` -+ for i in $(seq 1 10); do -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(get_cpuinfo_mhz.sh)" -p "$mpps" -t 30 > "$OUTFILE" -+ exceeded=$(grep exceeded "$OUTFILE") - - if [ ! -z "$exceeded" ]; then - echo "mpps failure (run $i) $mpps" - export queuelat_failure=1 -- mpps=`echo $mpps - 0.1 | bc` -+ mpps=$(echo "$mpps" - 0.1 | bc) - export mpps - break - fi -@@ -113,19 +113,20 @@ while [ $queuelat_failure == 1 ]; do - echo -n "Starting 10 minutes run with " - echo "$mpps Mpps" - -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 600 > $OUTFILE -- exceeded=`grep exceeded $OUTFILE` -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f "$(get_cpuinfo_mhz.sh)" -p "$mpps" -t 600 > "$OUTFILE" -+ exceeded=$(grep exceeded "$OUTFILE") - - if [ ! -z "$exceeded" ]; then - echo "mpps failure (run $i) $mpps" - export queuelat_failure=1 -- export mpps=`echo $mpps - 0.1 | bc` -+ mpps=$(echo "$mpps" - 0.1 | bc) -+ export mpps - continue - fi - echo "run $i success" - done - --echo Final mpps is: $mpps -+echo Final mpps is: "$mpps" - - unset queuelat_failure - unset mpps --- -2.20.1 - diff --git a/SOURCES/rt-tests-get_cyclictest_snapshot-Warn-if-no-cyclicte.patch b/SOURCES/rt-tests-get_cyclictest_snapshot-Warn-if-no-cyclicte.patch new file mode 100644 index 0000000..f17b9ac --- /dev/null +++ b/SOURCES/rt-tests-get_cyclictest_snapshot-Warn-if-no-cyclicte.patch @@ -0,0 +1,76 @@ +From c7b4217ff2b04d774ee5e2728eeb5da1cba275ff Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Mon, 6 Jul 2020 16:07:17 -0400 +Subject: [PATCH 7/7] rt-tests: get_cyclictest_snapshot: Warn if no cyclictest + instance found + +- Print a warning if no cyclictest instance is found. +- Also fix up the method take_snapshot for the case when the user + provides a pid. + +Signed-off-by: John Kacur +--- + src/cyclictest/get_cyclictest_snapshot.py | 23 +++++++++++++++++++++-- + 1 file changed, 21 insertions(+), 2 deletions(-) + +diff --git a/src/cyclictest/get_cyclictest_snapshot.py b/src/cyclictest/get_cyclictest_snapshot.py +index 27fc629ca53e..aed9681e4cc5 100755 +--- a/src/cyclictest/get_cyclictest_snapshot.py ++++ b/src/cyclictest/get_cyclictest_snapshot.py +@@ -19,6 +19,14 @@ args = parser.parse_args() + class Snapshot: + """ Class for getting a snapshot of a running cyclictest instance """ + ++ warned = False ++ ++ def print_warning(): ++ """ print a warning one time only even if called multiple times """ ++ if not Snapshot.warned: ++ Snapshot.warned = True ++ print("No cyclictest instance found") ++ + def __init__(self): + self.pids = [] + self.shm_files = [] +@@ -36,18 +44,27 @@ class Snapshot: + def take_snapshot(self, spids=None): + """ Send USR2 to all running instances of cyclictest, + or just to a specific pid (spids) if specified. """ +- for pid in self.pids: +- if (spids is None) or (pid in spids): ++ if spids is None: ++ if not self.pids: ++ Snapshot.print_warning() ++ for pid in self.pids: ++ subprocess.run(["kill", "-s", "USR2", pid]) ++ else: ++ for pid in spids: + subprocess.run(["kill", "-s", "USR2", pid]) + + def print_pids(self): + """ Print the list of pids of running cyclictest instances. """ ++ if not self.pids: ++ Snapshot.print_warning() + for pid in self.pids: + print(pid) + + def print(self, spids=None): + """ Print the data in /dev/shm/cyclictest* """ + if spids is None: ++ if not self.shm_files: ++ Snapshot.print_warning() + for shm_file in self.shm_files: + with open(shm_file, 'r') as f: + data = f.read() +@@ -59,6 +76,8 @@ class Snapshot: + with open(shm_file, 'r') as f: + data = f.read() + print(data) ++ else: ++ Snapshot.print_warning() + + snapshot = Snapshot() + +-- +2.21.3 + diff --git a/SOURCES/rt-tests-improvements-to-the-python-style-in-get_cyc.patch b/SOURCES/rt-tests-improvements-to-the-python-style-in-get_cyc.patch new file mode 100644 index 0000000..38d527f --- /dev/null +++ b/SOURCES/rt-tests-improvements-to-the-python-style-in-get_cyc.patch @@ -0,0 +1,114 @@ +From 3ee764c75dd0cdb2ade1a832ed3769ed4964cd30 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Thu, 2 Jul 2020 21:19:55 -0400 +Subject: [PATCH 1/7] rt-tests: improvements to the python style in + get_cyclictest_snapshot + +Improvements to the python style in get_cyclictest_snapshot + +- Add comments to the methods, functions, class and moduleb +- Put imports on individual lines +- Use "is" and "is not" with None insteald of == or != +- Don't compare the length of lists to zero, to determine if they are + empty + +Signed-off-by: John Kacur +--- + src/cyclictest/get_cyclictest_snapshot.py | 38 +++++++++++++---------- + 1 file changed, 22 insertions(+), 16 deletions(-) + +diff --git a/src/cyclictest/get_cyclictest_snapshot.py b/src/cyclictest/get_cyclictest_snapshot.py +index 7dddfc5d65b0..27fc629ca53e 100755 +--- a/src/cyclictest/get_cyclictest_snapshot.py ++++ b/src/cyclictest/get_cyclictest_snapshot.py +@@ -1,9 +1,14 @@ + #!/usr/bin/env python3 ++""" Program to get a snapshot of a running instance of cyclictest """ + + # SPDX-License-Identifier: GPL-2.0-or-later + # Copyright (C) 2020 John Kacur + +-import subprocess, signal, argparse, re, glob, sys ++import subprocess ++import argparse ++import re ++import glob ++import sys + + parser = argparse.ArgumentParser(description='Get a snapshot of running instances of cyclictest') + parser.add_argument('-l', '--list', action='store_true', help='list the main pid(s) of running instances of cyclictest') +@@ -11,8 +16,8 @@ parser.add_argument('-s', '--snapshot', nargs='*', metavar='pid', help='take a s + parser.add_argument('-p', '--print', nargs='*', metavar='pid', help='print the snapshots') + args = parser.parse_args() + +- + class Snapshot: ++ """ Class for getting a snapshot of a running cyclictest instance """ + + def __init__(self): + self.pids = [] +@@ -20,6 +25,7 @@ class Snapshot: + self.refresh() + + def refresh(self): ++ """ Create a list of running cyclictest instances. """ + self.pids = [] + self.shm_files = glob.glob('/dev/shm/cyclictest*') + self.shm_files.sort() +@@ -27,21 +33,21 @@ class Snapshot: + pid = re.search('[0-9]*$', shm_file).group() + self.pids += [pid] + +- # Send USR2 to all running instances of cyclictest or just to +- # a specific pid (spid) if specified + def take_snapshot(self, spids=None): ++ """ Send USR2 to all running instances of cyclictest, ++ or just to a specific pid (spids) if specified. """ + for pid in self.pids: +- if (spids == None) or (pid in spids): +- # print("kill -s USR2 ", pid) ++ if (spids is None) or (pid in spids): + subprocess.run(["kill", "-s", "USR2", pid]) + + def print_pids(self): ++ """ Print the list of pids of running cyclictest instances. """ + for pid in self.pids: + print(pid) + +- # Print the data in /dev/shm/cyclictest* + def print(self, spids=None): +- if spids == None: ++ """ Print the data in /dev/shm/cyclictest* """ ++ if spids is None: + for shm_file in self.shm_files: + with open(shm_file, 'r') as f: + data = f.read() +@@ -59,17 +65,17 @@ snapshot = Snapshot() + if args.list: + snapshot.print_pids() + +-if args.snapshot != None: +- if len(args.snapshot) == 0: +- snapshot.take_snapshot() +- else: ++if args.snapshot is not None: ++ if args.snapshot: + snapshot.take_snapshot(args.snapshot) +- +-if args.print != None: +- if len(args.print) == 0: +- snapshot.print() + else: ++ snapshot.take_snapshot() ++ ++if args.print is not None: ++ if args.print: + snapshot.print(args.print) ++ else: ++ snapshot.print() + + if len(sys.argv) == 1: + snapshot.take_snapshot() +-- +2.21.3 + diff --git a/SOURCES/rt-tests-oslat-Init-commit.patch b/SOURCES/rt-tests-oslat-Init-commit.patch new file mode 100644 index 0000000..60727a5 --- /dev/null +++ b/SOURCES/rt-tests-oslat-Init-commit.patch @@ -0,0 +1,1043 @@ +From c86dec5765e1ad0bd1d0c429ca7c138c11da2c80 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Mon, 17 Aug 2020 17:55:05 -0400 +Subject: [PATCH 2/2] rt-tests: oslat: Init commit + +oslat was initially a standalone program [1]. This patch merges oslat into +rt-tests repo. + +This is a direct port of oslat v0.1.7 into rt-tests. It naturally bumps the +version to latest rt-tests version. + +[1] https://github.com/xzpeter/oslat + +Signed-off-by: Peter Xu +A few minor fixes to the grammar in the man page +Signed-off-by: John Kacur +--- + Makefile | 10 +- + src/oslat/oslat.8 | 66 ++++ + src/oslat/oslat.c | 896 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 970 insertions(+), 2 deletions(-) + create mode 100644 src/oslat/oslat.8 + create mode 100644 src/oslat/oslat.c + +diff --git a/Makefile b/Makefile +index be7831277c88..3f59efba2885 100644 +--- a/Makefile ++++ b/Makefile +@@ -17,7 +17,8 @@ sources = cyclictest.c \ + cyclicdeadline.c \ + deadline_test.c \ + queuelat.c \ +- ssdd.c ++ ssdd.c \ ++ oslat.c + + TARGETS = $(sources:.c=) + LIBS = -lrt -lpthread +@@ -48,7 +49,8 @@ MANPAGES = src/cyclictest/cyclictest.8 \ + src/sched_deadline/deadline_test.8 \ + src/ssdd/ssdd.8 \ + src/sched_deadline/cyclicdeadline.8 \ +- src/cyclictest/get_cyclictest_snapshot.8 ++ src/cyclictest/get_cyclictest_snapshot.8 \ ++ src/oslat/oslat.8 + + ifdef PYLIB + MANPAGES += src/hwlatdetect/hwlatdetect.8 +@@ -97,6 +99,7 @@ VPATH += src/hackbench: + VPATH += src/sched_deadline: + VPATH += src/queuelat: + VPATH += src/ssdd: ++VPATH += src/oslat: + + $(OBJDIR)/%.o: %.c | $(OBJDIR) + $(CC) -D VERSION=$(VERSION) -c $< $(CFLAGS) $(CPPFLAGS) -o $@ +@@ -164,6 +167,9 @@ queuelat: $(OBJDIR)/queuelat.o $(OBJDIR)/librttest.a + ssdd: $(OBJDIR)/ssdd.o $(OBJDIR)/librttest.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(RTTESTLIB) + ++oslat: $(OBJDIR)/oslat.o $(OBJDIR)/librttest.a ++ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(RTTESTLIB) $(NUMA_LIBS) ++ + %.8.gz: %.8 + gzip -nc $< > $@ + +diff --git a/src/oslat/oslat.8 b/src/oslat/oslat.8 +new file mode 100644 +index 000000000000..85f2c5bcdf5c +--- /dev/null ++++ b/src/oslat/oslat.8 +@@ -0,0 +1,66 @@ ++.TH OSLAT 8 "August 17, 2020" ++.\" for manpage-specific macros, see man(7) ++.SH NAME ++oslat \- OS Latency Detector ++.SH SYNOPSIS ++.SY oslat ++.RI "[ \-shvz ] [ \-b " bucket-size " ] [ \-B " bias " ] [ \-c " cpu-list " ] \ ++[ \-C " cpu-main-thread " ] [ \-f " rt-prio " ] [ \-m " workload-mem " ] \ ++[\-t " runtime " ] [ \-T " trace-threshold " ] [ \-w " workload " ]" ++.SH DESCRIPTION ++.B oslat ++is an open source userspace polling mode stress program to detect OS level ++latency. The program runs a busy loop with no or various workloads, collecting ++TSC information and measuring the time frequently during the process. ++.SH OPTIONS ++.TP ++.B \-b, \-\-bucket-size=N ++Specify the number of the buckets (4-1024). ++.TP ++.B \-B, \-\-bias=USEC ++Add a bias to all the buckets using the estimated mininum. ++.TP ++.B \-c, \-\-cpu-list=CPULIST ++Specify CPUs to run on. For example, '1,3,5,7-15'. ++.TP ++.B \-C, \-\-cpu-main-thread=CORE ++Specify which CPU the main thread runs on. Default is cpu0. ++.TP ++.B \-f, \-\-rtprio=PRIORITY ++Using specific SCHED_FIFO priority (1-99). Otherwise use the default ++priority, normally it will be SCHED_OTHER. ++.TP ++.B \-m, \-\-workload-mem=SIZE ++Size of the memory to use for the workload (e.g., 4K, 1M). ++Total memory usage will be this value multiplies 2*N, ++because there will be src/dst buffers for each thread, and ++N is the number of processors for testing. ++.TP ++.B \-t, \-\-runtime=SEC ++Specify test duration, e.g., 60, 20m, 2H (m/M: minutes, h/H: hours, d/D: days). ++By default the unit is s/second. ++.TP ++.B \-T, \-\-trace-threshold=THRESHOLD ++Stop the test when threshold triggered (in USEC). At the meantime, print a ++marker in ftrace and stop ftrace too. ++.TP ++.B \-w, \-\-workload=WORKLOAD ++Specify a kind of workload, default is no workload. Options: "no", "memmove". ++.TP ++.B \-s, \-\-single-preheat ++Use a single thread when measuring latency at preheat stage ++NOTE: please make sure the CPU frequency on all testing cores ++are locked before using this parmater. If you don't know how ++to lock the freq then please don't use this parameter. ++.TP ++.B \-h, \-\-help ++Show the help message. ++.TP ++.B \-v, \-\-version ++Show the version of the program. ++.TP ++.B \-z, \-\-zero-omit ++Don't display buckets in the output histogram if all zeros. ++.SH AUTHOR ++.B oslat ++was written by Peter Xu . +diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c +new file mode 100644 +index 000000000000..d79691926247 +--- /dev/null ++++ b/src/oslat/oslat.c +@@ -0,0 +1,896 @@ ++/* ++ * oslat - OS latency detector ++ * ++ * Copyright 2020 Red Hat Inc. ++ * ++ * Authors: Peter Xu ++ * ++ * Some of the utility code based on sysjitter-1.3: ++ * Copyright 2010-2015 David Riddoch ++ * ++ * This program is free software: you can redistribute it and/or modify it ++ * under the terms of version 3 of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program. If not, see . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rt-utils.h" ++#include "error.h" ++ ++#ifdef __GNUC__ ++# define atomic_inc(ptr) __sync_add_and_fetch((ptr), 1) ++# if defined(__x86_64__) ++# define relax() __asm__ __volatile__("pause" ::: "memory") ++static inline void frc(uint64_t* pval) ++{ ++ uint32_t low, high; ++ /* See rdtsc_ordered() of Linux */ ++ __asm__ __volatile__("lfence"); ++ __asm__ __volatile__("rdtsc" : "=a" (low) , "=d" (high)); ++ *pval = ((uint64_t) high << 32) | low; ++} ++# elif defined(__i386__) ++# define relax() __asm__ __volatile__("pause" ::: "memory") ++static inline void frc(uint64_t* pval) ++{ ++ __asm__ __volatile__("rdtsc" : "=A" (*pval)); ++} ++# elif defined(__PPC64__) ++# define relax() do{}while(0) ++static inline void frc(uint64_t* pval) ++{ ++ __asm__ __volatile__("mfspr %0, 268\n" : "=r" (*pval)); ++} ++# else ++# error Need frc() for this platform. ++# endif ++#else ++# error Need to add support for this compiler. ++#endif ++ ++typedef uint64_t stamp_t; /* timestamp */ ++typedef uint64_t cycles_t; /* number of cycles */ ++typedef unsigned char bool; ++ ++#define true 1 ++#define false 0 ++ ++enum command { ++ WAIT, ++ GO, ++ STOP ++}; ++ ++enum workload_type { ++ WORKLOAD_NONE = 0, ++ WORKLOAD_MEMMOVE, ++ WORKLOAD_NUM, ++}; ++ ++/* This workload needs pre-allocated memory */ ++#define WORK_NEED_MEM (1UL << 0) ++ ++typedef void (*workload_fn)(char *src, char *dst, size_t size); ++ ++struct workload { ++ const char *w_name; ++ uint64_t w_flags; ++ workload_fn w_fn; ++}; ++ ++/* We'll have buckets 1us, 2us, ..., (BUCKET_SIZE) us. */ ++#define BUCKET_SIZE (32) ++ ++/* Default size of the workloads per thread (in bytes, which is 16KB) */ ++#define WORKLOAD_MEM_SIZE (16UL << 10) ++ ++/* By default, no workload */ ++#define WORKLOAD_DEFUALT WORKLOAD_NONE ++ ++struct thread { ++ int core_i; ++ pthread_t thread_id; ++ ++ /* NOTE! this is also how many ticks per us */ ++ unsigned cpu_mhz; ++ cycles_t int_total; ++ stamp_t frc_start; ++ stamp_t frc_stop; ++ cycles_t runtime; ++ stamp_t *buckets; ++ uint64_t minlat; ++ /* Maximum latency detected */ ++ uint64_t maxlat; ++ /* ++ * The extra part of the interruptions that cannot be put into even the ++ * biggest bucket. We'll use this to calculate a more accurate average at ++ * the end of the tests. ++ */ ++ uint64_t overflow_sum; ++ int memory_allocated; ++ ++ /* Buffers used for the workloads */ ++ char * src_buf; ++ char * dst_buf; ++ ++ /* These variables are calculated after the test */ ++ double average; ++}; ++ ++struct global { ++ /* Configuration. */ ++ unsigned runtime_secs; ++ /* Number of threads running for current test (either pre heat or real run) */ ++ unsigned n_threads; ++ /* Number of threads to test for the real run */ ++ unsigned n_threads_total; ++ struct timeval tv_start; ++ int rtprio; ++ int bucket_size; ++ int trace_threshold; ++ int runtime; ++ /* The core that we run the main thread. Default is cpu0 */ ++ int cpu_main_thread; ++ char * cpu_list; ++ char * app_name; ++ struct workload * workload; ++ uint64_t workload_mem_size; ++ int enable_bias; ++ uint64_t bias; ++ bool single_preheat_thread; ++ bool output_omit_zero_buckets; ++ ++ /* Mutable state. */ ++ volatile enum command cmd; ++ volatile unsigned n_threads_started; ++ volatile unsigned n_threads_ready; ++ volatile unsigned n_threads_running; ++ volatile unsigned n_threads_finished; ++}; ++ ++static struct global g; ++ ++static void workload_nop(char *dst, char *src, size_t size) ++{ ++ /* Nop */ ++} ++ ++static void workload_memmove(char *dst, char *src, size_t size) ++{ ++ memmove(dst, src, size); ++} ++ ++struct workload workload_list[WORKLOAD_NUM] = { ++ { "no", 0, workload_nop }, ++ { "memmove", WORK_NEED_MEM, workload_memmove }, ++}; ++ ++#define TEST(x) \ ++ do { \ ++ if( ! (x) ) \ ++ test_fail(#x, __LINE__); \ ++ } while( 0 ) ++ ++#define TEST0(x) TEST((x) == 0) ++ ++static void test_fail(const char* what, int line) ++{ ++ fprintf(stderr, "ERROR:\n"); ++ fprintf(stderr, "ERROR: TEST(%s)\n", what); ++ fprintf(stderr, "ERROR: at line %d\n", line); ++ fprintf(stderr, "ERROR: errno=%d (%s)\n", errno, strerror(errno)); ++ fprintf(stderr, "ERROR:\n"); ++ exit(1); ++} ++ ++static int move_to_core(int core_i) ++{ ++ cpu_set_t cpus; ++ CPU_ZERO(&cpus); ++ CPU_SET(core_i, &cpus); ++ return sched_setaffinity(0, sizeof(cpus), &cpus); ++} ++ ++static cycles_t __measure_cpu_hz(void) ++{ ++ struct timeval tvs, tve; ++ stamp_t s, e; ++ double sec; ++ ++ frc(&s); ++ e = s; ++ gettimeofday(&tvs, NULL); ++ while( e - s < 1000000 ) ++ frc(&e); ++ gettimeofday(&tve, NULL); ++ sec = tve.tv_sec - tvs.tv_sec + (tve.tv_usec - tvs.tv_usec) / 1e6; ++ return (cycles_t) ((e - s) / sec); ++} ++ ++static unsigned measure_cpu_mhz(void) ++{ ++ cycles_t m, mprev, d; ++ ++ mprev = __measure_cpu_hz(); ++ do { ++ m = __measure_cpu_hz(); ++ if( m > mprev ) d = m - mprev; ++ else d = mprev - m; ++ mprev = m; ++ } while( d > m / 1000 ); ++ ++ return (unsigned) (m / 1000000); ++} ++ ++static void thread_init(struct thread* t) ++{ ++ t->cpu_mhz = measure_cpu_mhz(); ++ t->maxlat = 0; ++ t->overflow_sum = 0; ++ t->minlat = (uint64_t)-1; ++ ++ /* NOTE: all the buffers are not freed until the process quits. */ ++ if (!t->memory_allocated) { ++ TEST(t->buckets = calloc(1, sizeof(t->buckets[0]) * g.bucket_size)); ++ if (g.workload->w_flags & WORK_NEED_MEM) { ++ TEST0(posix_memalign((void **)&t->src_buf, getpagesize(), ++ g.workload_mem_size)); ++ memset(t->src_buf, 0, g.workload_mem_size); ++ TEST0(posix_memalign((void **)&t->dst_buf, getpagesize(), ++ g.workload_mem_size)); ++ memset(t->dst_buf, 0, g.workload_mem_size); ++ } ++ t->memory_allocated = 1; ++ } else { ++ /* Clear the buckets */ ++ memset(t->buckets, 0, sizeof(t->buckets[0]) * g.bucket_size); ++ } ++} ++ ++static float cycles_to_sec(const struct thread* t, uint64_t cycles) ++{ ++ return cycles / (t->cpu_mhz * 1e6); ++} ++ ++static void insert_bucket(struct thread *t, stamp_t value) ++{ ++ int index, us; ++ uint64_t extra; ++ ++ index = value / t->cpu_mhz; ++ assert(index >= 0); ++ us = index + 1; ++ assert(us > 0); ++ ++ if (g.trace_threshold && us >= g.trace_threshold) { ++ char *line = "%s: Trace threshold (%d us) triggered with %u us! " ++ "Stopping the test.\n"; ++ tracemark(line, g.app_name, g.trace_threshold, us); ++ err_quit(line, g.app_name, g.trace_threshold, us); ++ } ++ ++ /* Update max latency */ ++ if (us > t->maxlat) { ++ t->maxlat = us; ++ } ++ ++ if (us < t->minlat) { ++ t->minlat = us; ++ } ++ ++ if (g.bias) { ++ /* t->bias will be set after pre-heat if user enabled it */ ++ us -= g.bias; ++ /* ++ * Negative should hardly happen, but if it happens, we assume we're in ++ * the smallest bucket, which is 1us. Same to index. ++ */ ++ if (us <= 0) { ++ us = 1; ++ } ++ index -= g.bias; ++ if (index < 0) { ++ index = 0; ++ } ++ } ++ ++ /* Too big the jitter; put into the last bucket */ ++ if (index >= g.bucket_size) { ++ /* Keep the extra bit (in us) */ ++ extra = index - g.bucket_size; ++ if (t->overflow_sum + extra < t->overflow_sum) { ++ /* The uint64_t even overflowed itself; bail out */ ++ printf("Accumulated overflow too much!\n"); ++ exit(1); ++ } ++ t->overflow_sum += extra; ++ index = g.bucket_size - 1; ++ } ++ ++ t->buckets[index]++; ++ if (t->buckets[index] == 0) { ++ printf("Bucket %d overflowed\n", index); ++ exit(1); ++ } ++} ++ ++static void doit(struct thread* t) ++{ ++ stamp_t ts1, ts2; ++ workload_fn workload_fn = g.workload->w_fn; ++ ++ frc(&ts2); ++ do { ++ workload_fn(t->dst_buf, t->src_buf, g.workload_mem_size); ++ frc(&ts1); ++ insert_bucket(t, ts1 - ts2); ++ ts2 = ts1; ++ } while (g.cmd == GO); ++} ++ ++static int set_fifo_prio(int prio) ++{ ++ struct sched_param param; ++ ++ memset(¶m, 0, sizeof(param)); ++ param.sched_priority = prio; ++ return sched_setscheduler(0, SCHED_FIFO, ¶m); ++} ++ ++static void* thread_main(void* arg) ++{ ++ /* Important thing to note here is that once we start bashing the CPU, we ++ * need to keep doing so to prevent the core from changing frequency or ++ * dropping into a low power state. ++ */ ++ struct thread* t = arg; ++ ++ /* Alloc memory in the thread itself after setting affinity to get the ++ * best chance of getting numa-local memory. Doesn't matter so much for ++ * the "struct thread" since we expect that to stay cache resident. ++ */ ++ TEST(move_to_core(t->core_i) == 0); ++ if (g.rtprio) ++ TEST(set_fifo_prio(g.rtprio) == 0); ++ ++ /* Don't bash the cpu until all threads have got going. */ ++ atomic_inc(&g.n_threads_started); ++ while( g.cmd == WAIT ) ++ usleep(1000); ++ ++ thread_init(t); ++ ++ /* Ensure we all start at the same time. */ ++ atomic_inc(&g.n_threads_running); ++ while( g.n_threads_running != g.n_threads ) ++ relax(); ++ ++ frc(&t->frc_start); ++ doit(t); ++ frc(&t->frc_stop); ++ ++ t->runtime = t->frc_stop - t->frc_start; ++ ++ /* Wait for everyone to finish so we don't disturb them by exiting and ++ * waking the main thread. ++ */ ++ atomic_inc(&g.n_threads_finished); ++ while( g.n_threads_finished != g.n_threads ) ++ relax(); ++ ++ return NULL; ++} ++ ++#define putfield(label, val, fmt, end) do { \ ++ printf("%12s:\t", label); \ ++ for (i = 0; i < g.n_threads; ++i) \ ++ printf(" %"fmt, val); \ ++ printf("%s\n", end); \ ++ } while (0) ++ ++void calculate(struct thread *t) ++{ ++ int i, j; ++ double sum; ++ uint64_t count; ++ ++ for (i = 0; i < g.n_threads; ++i) { ++ /* Calculate average */ ++ sum = count = 0; ++ for (j = 0; j < g.bucket_size; j++) { ++ sum += 1.0 * t[i].buckets[j] * (g.bias+j+1); ++ count += t[i].buckets[j]; ++ } ++ /* Add the extra amount of huge spikes in */ ++ sum += t->overflow_sum; ++ t[i].average = sum / count; ++ } ++} ++ ++static void write_summary(struct thread* t) ++{ ++ int i, j, k, print_dotdotdot = 0; ++ char bucket_name[64]; ++ ++ calculate(t); ++ ++ putfield("Core", t[i].core_i, "d", ""); ++ putfield("CPU Freq", t[i].cpu_mhz, "u", " (Mhz)"); ++ ++ for (j = 0; j < g.bucket_size; j++) { ++ if (j < g.bucket_size-1 && g.output_omit_zero_buckets) { ++ for (k = 0; k < g.n_threads; k++) { ++ if (t[k].buckets[j] != 0) ++ break; ++ } ++ if (k == g.n_threads) { ++ print_dotdotdot = 1; ++ continue; ++ } ++ } ++ ++ if (print_dotdotdot) { ++ printf(" ...\n"); ++ print_dotdotdot = 0; ++ } ++ ++ snprintf(bucket_name, sizeof(bucket_name), "%03"PRIu64 ++ " (us)", g.bias+j+1); ++ putfield(bucket_name, t[i].buckets[j], PRIu64, ++ (j==g.bucket_size-1) ? " (including overflows)" : ""); ++ } ++ ++ putfield("Minimum", t[i].minlat, PRIu64, " (us)"); ++ putfield("Average", t[i].average, ".3lf", " (us)"); ++ putfield("Maximum", t[i].maxlat, PRIu64, " (us)"); ++ putfield("Max-Min", t[i].maxlat - t[i].minlat, PRIu64, " (us)"); ++ putfield("Duration", cycles_to_sec(&(t[i]), t[i].runtime), ++ ".3f", " (sec)"); ++ printf("\n"); ++} ++ ++static void run_expt(struct thread* threads, int runtime_secs) ++{ ++ int i; ++ ++ g.runtime_secs = runtime_secs; ++ g.n_threads_started = 0; ++ g.n_threads_ready = 0; ++ g.n_threads_running = 0; ++ g.n_threads_finished = 0; ++ g.cmd = WAIT; ++ ++ for( i = 0; i < g.n_threads; ++i ) { ++ TEST0(pthread_create(&(threads[i].thread_id), NULL, ++ thread_main, &(threads[i]))); ++ } ++ while( g.n_threads_started != g.n_threads ) { ++ usleep(1000); ++ } ++ ++ gettimeofday(&g.tv_start, NULL); ++ g.cmd = GO; ++ ++ alarm(runtime_secs); ++ ++ /* Go to sleep until the threads have done their stuff. */ ++ for( i = 0; i < g.n_threads; ++i ) { ++ pthread_join(threads[i].thread_id, NULL); ++ } ++} ++ ++static void handle_alarm(int code) ++{ ++ g.cmd = STOP; ++} ++ ++const char *helpmsg = ++ "Usage: %s [options]\n" ++ "\n" ++ "This is an OS latency detector by running busy loops on specified cores.\n" ++ "Please run this tool using root.\n" ++ "\n" ++ "Available options:\n" ++ "\n" ++ " -b, --bucket-size Specify the number of the buckets (4-1024)\n" ++ " -B, --bias Add a bias to all the buckets using the estimated mininum\n" ++ " -c, --cpu-list Specify CPUs to run on, e.g. '1,3,5,7-15'\n" ++ " -C, --cpu-main-thread Specify which CPU the main thread runs on. Default is cpu0.\n" ++ " -f, --rtprio Using SCHED_FIFO priority (1-99)\n" ++ " -m, --workload-mem Size of the memory to use for the workload (e.g., 4K, 1M).\n" ++ " 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" ++ " -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" ++ " to lock the freq then please don't use this parameter.\n" ++ " -t, --runtime Specify test duration, e.g., 60, 20m, 2H\n" ++ " (m/M: minutes, h/H: hours, d/D: days)\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" ++ " -w, --workload Specify a kind of workload, default is no workload\n" ++ " (options: no, memmove)\n" ++ " -z, --zero-omit Don't display buckets in the output histogram if all zeros.\n" ++ "\n" ++ ; ++ ++static void usage(void) ++{ ++ printf(helpmsg, g.app_name); ++ exit(1); ++} ++ ++/* TODO: use libnuma? */ ++static int parse_cpu_list(char *cpu_list, cpu_set_t *cpu_set) ++{ ++ struct bitmask *cpu_mask; ++ int i, n_cores; ++ ++ n_cores = sysconf(_SC_NPROCESSORS_CONF); ++ ++ if (!cpu_list) { ++ for (i = 0; i < n_cores; i++) ++ CPU_SET(i, cpu_set); ++ return n_cores; ++ } ++ ++ cpu_mask = numa_parse_cpustring_all(cpu_list); ++ if (cpu_mask) { ++ for (i = 0; i < n_cores; i++) { ++ if (numa_bitmask_isbitset(cpu_mask, i)) { ++ CPU_SET(i, cpu_set); ++ } ++ } ++ numa_bitmask_free(cpu_mask); ++ } else { ++ warn("Unknown cpu-list: %s, using all available cpus\n", cpu_list); ++ for (i = 0; i < n_cores; i++) ++ CPU_SET(i, cpu_set); ++ } ++ ++ return n_cores; ++} ++ ++static int parse_runtime(const char *str) ++{ ++ char *endptr; ++ int v = strtol(str, &endptr, 10); ++ ++ if (!*endptr) { ++ return v; ++ } ++ ++ switch (*endptr) { ++ case 'd': ++ case 'D': ++ /* Days */ ++ v *= 24; ++ case 'h': ++ case 'H': ++ /* Hours */ ++ v *= 60; ++ case 'm': ++ case 'M': ++ /* Minutes */ ++ v *= 60; ++ case 's': ++ case 'S': ++ /* Seconds */ ++ break; ++ default: ++ printf("Unknown runtime suffix: %s\n", endptr); ++ v = 0; ++ break; ++ } ++ ++ return v; ++} ++ ++static int parse_mem_size(char *str, uint64_t *val) ++{ ++ char *endptr; ++ int v = strtol(str, &endptr, 10); ++ ++ if (!*endptr) { ++ return v; ++ } ++ ++ switch (*endptr) { ++ case 'g': ++ case 'G': ++ v *= 1024; ++ case 'm': ++ case 'M': ++ v *= 1024; ++ case 'k': ++ case 'K': ++ v *= 1024; ++ case 'b': ++ case 'B': ++ break; ++ default: ++ return -1; ++ } ++ ++ *val = v; ++ ++ return 0; ++} ++ ++static int workload_select(char *name) ++{ ++ int i = 0; ++ ++ for (i = 0; i < WORKLOAD_NUM; i++) { ++ if (!strcmp(name, workload_list[i].w_name)) { ++ g.workload = &workload_list[i]; ++ return 0; ++ } ++ } ++ ++ return -1; ++} ++ ++/* Process commandline options */ ++static void parse_options(int argc, char *argv[]) ++{ ++ while (1) { ++ static struct option options[] = { ++ { "bucket-size", required_argument, NULL, 'b' }, ++ { "cpu-list", required_argument, NULL, 'c' }, ++ { "cpu-main-thread", required_argument, NULL, 'C'}, ++ { "runtime", required_argument, NULL, 't' }, ++ { "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'}, ++ { NULL, 0, NULL, 0 }, ++ }; ++ int i, c = getopt_long(argc, argv, "b:Bc:C:f:hm:st:w:T:vz", ++ options, NULL); ++ long ncores; ++ ++ if (c == -1) ++ break; ++ ++ switch (c) { ++ case 'b': ++ g.bucket_size = strtol(optarg, NULL, 10); ++ if (g.bucket_size > 1024 || g.bucket_size <= 4) { ++ printf("Illegal bucket size: %s (should be: 4-1024)\n", ++ optarg); ++ exit(1); ++ } ++ break; ++ case 'B': ++ g.enable_bias = 1; ++ break; ++ case 'c': ++ g.cpu_list = strdup(optarg); ++ break; ++ case 'C': ++ ncores = sysconf(_SC_NPROCESSORS_CONF); ++ g.cpu_main_thread = strtol(optarg, NULL, 10); ++ if (g.cpu_main_thread < 0 || g.cpu_main_thread > ncores) { ++ printf("Illegal core for main thread: %s (should be: 0-%ld)\n", ++ optarg, ncores); ++ exit(1); ++ } ++ break; ++ case 't': ++ g.runtime = parse_runtime(optarg); ++ if (!g.runtime) { ++ printf("Illegal runtime: %s\n", optarg); ++ exit(1); ++ } ++ break; ++ case 'f': ++ g.rtprio = strtol(optarg, NULL, 10); ++ if (g.rtprio < 1 || g.rtprio > 99) { ++ printf("Illegal RT priority: %s (should be: 1-99)\n", optarg); ++ exit(1); ++ } ++ break; ++ case 'T': ++ g.trace_threshold = strtol(optarg, NULL, 10); ++ if (g.trace_threshold <= 0) { ++ printf("Parameter --trace-threshold needs to be positive\n"); ++ exit(1); ++ } ++ enable_trace_mark(); ++ break; ++ case 'w': ++ if (workload_select(optarg)) { ++ printf("Unknown workload '%s'. Please choose from: ", optarg); ++ for (i = 0; i < WORKLOAD_NUM; i++) { ++ printf("'%s'", workload_list[i].w_name); ++ if (i != WORKLOAD_NUM - 1) { ++ printf(", "); ++ } ++ } ++ printf("\n\n"); ++ exit(1); ++ } ++ break; ++ case 'm': ++ if (parse_mem_size(optarg, &g.workload_mem_size)) { ++ printf("Unknown workload memory size '%s'.\n\n", optarg); ++ exit(1); ++ } ++ break; ++ case 's': ++ /* ++ * Only use one core for pre-heat. Then if --bias is used, the ++ * bias will be exactly the min value of the pre-heat core. ++ */ ++ g.single_preheat_thread = true; ++ break; ++ case 'v': ++ /* ++ * Because we always dump the version even before parsing options, ++ * what we need to do is to quit.. ++ */ ++ exit(0); ++ break; ++ case 'z': ++ g.output_omit_zero_buckets = 1; ++ break; ++ default: ++ usage(); ++ break; ++ } ++ } ++} ++ ++void dump_globals(void) ++{ ++ printf("Total runtime: \t\t%d seconds\n", g.runtime); ++ printf("Thread priority: \t"); ++ if (g.rtprio) { ++ printf("SCHED_FIFO:%d\n", g.rtprio); ++ } else { ++ printf("default\n"); ++ } ++ printf("CPU list: \t\t%s\n", g.cpu_list ?: "(all cores)"); ++ printf("CPU for main thread: \t%d\n", g.cpu_main_thread); ++ printf("Workload: \t\t%s\n", g.workload->w_name); ++ printf("Workload mem: \t\t%"PRIu64" (KiB)\n", ++ (g.workload->w_flags & WORK_NEED_MEM) ? ++ (g.workload_mem_size / 1024) : 0); ++ printf("Preheat cores: \t\t%d\n", g.single_preheat_thread ? ++ 1 : g.n_threads_total); ++ printf("\n"); ++} ++ ++static void record_bias(struct thread *t) ++{ ++ int i; ++ uint64_t bias = (uint64_t)-1; ++ ++ if (!g.enable_bias) { ++ return; ++ } ++ ++ /* Record the min value of minlat on all the threads */ ++ for( i = 0; i < g.n_threads; ++i ) { ++ if (t[i].minlat < bias) { ++ bias = t[i].minlat; ++ } ++ } ++ g.bias = bias; ++ printf("Global bias set to %" PRId64 " (us)\n", bias); ++} ++ ++int main(int argc, char* argv[]) ++{ ++ struct thread* threads; ++ int i, n_cores; ++ cpu_set_t cpu_set; ++ ++ CPU_ZERO(&cpu_set); ++ ++ g.app_name = argv[0]; ++ g.rtprio = 0; ++ g.bucket_size = BUCKET_SIZE; ++ g.runtime = 1; ++ g.workload = &workload_list[WORKLOAD_DEFUALT]; ++ g.workload_mem_size = WORKLOAD_MEM_SIZE; ++ /* Run the main thread on cpu0 by default */ ++ g.cpu_main_thread = 0; ++ ++ printf("\nVersion: %1.2f\n\n", VERSION); ++ ++ parse_options(argc, argv); ++ ++ TEST(mlockall(MCL_CURRENT | MCL_FUTURE) == 0); ++ ++ n_cores = parse_cpu_list(g.cpu_list, &cpu_set); ++ ++ TEST( threads = calloc(1, CPU_COUNT(&cpu_set) * sizeof(threads[0])) ); ++ for( i = 0; i < n_cores; ++i ) ++ if (CPU_ISSET(i, &cpu_set) && move_to_core(i) == 0) ++ threads[g.n_threads_total++].core_i = i; ++ ++ if (CPU_ISSET(0, &cpu_set) && g.rtprio) { ++ printf("WARNING: Running SCHED_FIFO workload on CPU 0 " ++ "may hang the main thread\n"); ++ } ++ ++ TEST(move_to_core(g.cpu_main_thread) == 0); ++ ++ signal(SIGALRM, handle_alarm); ++ signal(SIGINT, handle_alarm); ++ signal(SIGTERM, handle_alarm); ++ ++ dump_globals(); ++ ++ printf("Pre-heat for 1 seconds...\n"); ++ if (g.single_preheat_thread) { ++ g.n_threads = 1; ++ } else { ++ g.n_threads = g.n_threads_total; ++ } ++ run_expt(threads, 1); ++ record_bias(threads); ++ ++ 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"); ++ ++ write_summary(threads); ++ ++ if (g.cpu_list) { ++ free(g.cpu_list); ++ g.cpu_list = NULL; ++ } ++ ++ return 0; ++} +-- +2.26.2 + diff --git a/SOURCES/rt-tests-oslat-Proper-reformat-of-code.patch b/SOURCES/rt-tests-oslat-Proper-reformat-of-code.patch new file mode 100644 index 0000000..fb8fb70 --- /dev/null +++ b/SOURCES/rt-tests-oslat-Proper-reformat-of-code.patch @@ -0,0 +1,1526 @@ +From 8dad377d0e54c3e31da50deb55cd7c257e542d8f Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 19 Aug 2020 16:19:40 -0400 +Subject: [PATCH] rt-tests: oslat: Proper reformat of code + +Format the code with kernel coding style. Meanwhile use spdx license +identifier as suggested by John. + +Signed-off-by: Peter Xu +Signed-off-by: John Kacur +--- + src/oslat/oslat.c | 1323 ++++++++++++++++++++++----------------------- + 1 file changed, 649 insertions(+), 674 deletions(-) + +diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c +index d79691926247..f1a82f2367d2 100644 +--- a/src/oslat/oslat.c ++++ b/src/oslat/oslat.c +@@ -1,3 +1,4 @@ ++// SPDX-License-Identifier: GPL-3.0-only + /* + * oslat - OS latency detector + * +@@ -7,18 +8,6 @@ + * + * Some of the utility code based on sysjitter-1.3: + * Copyright 2010-2015 David Riddoch +- * +- * This program is free software: you can redistribute it and/or modify it +- * under the terms of version 3 of the GNU General Public License as +- * published by the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License along +- * with this program. If not, see . + */ + + #include +@@ -59,25 +48,25 @@ + # define atomic_inc(ptr) __sync_add_and_fetch((ptr), 1) + # if defined(__x86_64__) + # define relax() __asm__ __volatile__("pause" ::: "memory") +-static inline void frc(uint64_t* pval) ++static inline void frc(uint64_t *pval) + { +- uint32_t low, high; +- /* See rdtsc_ordered() of Linux */ +- __asm__ __volatile__("lfence"); +- __asm__ __volatile__("rdtsc" : "=a" (low) , "=d" (high)); +- *pval = ((uint64_t) high << 32) | low; ++ uint32_t low, high; ++ /* See rdtsc_ordered() of Linux */ ++ __asm__ __volatile__("lfence"); ++ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)); ++ *pval = ((uint64_t) high << 32) | low; + } + # elif defined(__i386__) + # define relax() __asm__ __volatile__("pause" ::: "memory") +-static inline void frc(uint64_t* pval) ++static inline void frc(uint64_t *pval) + { +- __asm__ __volatile__("rdtsc" : "=A" (*pval)); ++ __asm__ __volatile__("rdtsc" : "=A" (*pval)); + } + # elif defined(__PPC64__) +-# define relax() do{}while(0) +-static inline void frc(uint64_t* pval) ++# define relax() do { } while (0) ++static inline void frc(uint64_t *pval) + { +- __asm__ __volatile__("mfspr %0, 268\n" : "=r" (*pval)); ++ __asm__ __volatile__("mfspr %0, 268\n" : "=r" (*pval)); + } + # else + # error Need frc() for this platform. +@@ -88,21 +77,20 @@ static inline void frc(uint64_t* pval) + + typedef uint64_t stamp_t; /* timestamp */ + typedef uint64_t cycles_t; /* number of cycles */ +-typedef unsigned char bool; + + #define true 1 + #define false 0 + + enum command { +- WAIT, +- GO, +- STOP ++ WAIT, ++ GO, ++ STOP + }; + + enum workload_type { +- WORKLOAD_NONE = 0, +- WORKLOAD_MEMMOVE, +- WORKLOAD_NUM, ++ WORKLOAD_NONE = 0, ++ WORKLOAD_MEMMOVE, ++ WORKLOAD_NUM, + }; + + /* This workload needs pre-allocated memory */ +@@ -111,9 +99,9 @@ enum workload_type { + typedef void (*workload_fn)(char *src, char *dst, size_t size); + + struct workload { +- const char *w_name; +- uint64_t w_flags; +- workload_fn w_fn; ++ const char *w_name; ++ uint64_t w_flags; ++ workload_fn w_fn; + }; + + /* We'll have buckets 1us, 2us, ..., (BUCKET_SIZE) us. */ +@@ -123,774 +111,761 @@ struct workload { + #define WORKLOAD_MEM_SIZE (16UL << 10) + + /* By default, no workload */ +-#define WORKLOAD_DEFUALT WORKLOAD_NONE ++#define WORKLOAD_DEFAULT WORKLOAD_NONE + + struct thread { +- int core_i; +- pthread_t thread_id; +- +- /* NOTE! this is also how many ticks per us */ +- unsigned cpu_mhz; +- cycles_t int_total; +- stamp_t frc_start; +- stamp_t frc_stop; +- cycles_t runtime; +- stamp_t *buckets; +- uint64_t minlat; +- /* Maximum latency detected */ +- uint64_t maxlat; +- /* +- * The extra part of the interruptions that cannot be put into even the +- * biggest bucket. We'll use this to calculate a more accurate average at +- * the end of the tests. +- */ +- uint64_t overflow_sum; +- int memory_allocated; +- +- /* Buffers used for the workloads */ +- char * src_buf; +- char * dst_buf; +- +- /* These variables are calculated after the test */ +- double average; ++ int core_i; ++ pthread_t thread_id; ++ ++ /* NOTE! this is also how many ticks per us */ ++ unsigned int cpu_mhz; ++ cycles_t int_total; ++ stamp_t frc_start; ++ stamp_t frc_stop; ++ cycles_t runtime; ++ stamp_t *buckets; ++ uint64_t minlat; ++ /* Maximum latency detected */ ++ uint64_t maxlat; ++ /* ++ * The extra part of the interruptions that cannot be put into even the ++ * biggest bucket. We'll use this to calculate a more accurate average at ++ * the end of the tests. ++ */ ++ uint64_t overflow_sum; ++ int memory_allocated; ++ ++ /* Buffers used for the workloads */ ++ char *src_buf; ++ char *dst_buf; ++ ++ /* These variables are calculated after the test */ ++ double average; + }; + + struct global { +- /* Configuration. */ +- unsigned runtime_secs; +- /* Number of threads running for current test (either pre heat or real run) */ +- unsigned n_threads; +- /* Number of threads to test for the real run */ +- unsigned n_threads_total; +- struct timeval tv_start; +- int rtprio; +- int bucket_size; +- int trace_threshold; +- int runtime; +- /* The core that we run the main thread. Default is cpu0 */ +- int cpu_main_thread; +- char * cpu_list; +- char * app_name; +- struct workload * workload; +- uint64_t workload_mem_size; +- int enable_bias; +- uint64_t bias; +- bool single_preheat_thread; +- bool output_omit_zero_buckets; +- +- /* Mutable state. */ +- volatile enum command cmd; +- volatile unsigned n_threads_started; +- volatile unsigned n_threads_ready; +- volatile unsigned n_threads_running; +- volatile unsigned n_threads_finished; ++ /* Configuration. */ ++ unsigned int runtime_secs; ++ /* ++ * Number of threads running for current test ++ * (either pre heat or real run) ++ */ ++ unsigned int n_threads; ++ /* Number of threads to test for the real run */ ++ unsigned int n_threads_total; ++ struct timeval tv_start; ++ int rtprio; ++ int bucket_size; ++ int trace_threshold; ++ int runtime; ++ /* The core that we run the main thread. Default is cpu0 */ ++ int cpu_main_thread; ++ char *cpu_list; ++ char *app_name; ++ struct workload *workload; ++ uint64_t workload_mem_size; ++ int enable_bias; ++ uint64_t bias; ++ int single_preheat_thread; ++ int output_omit_zero_buckets; ++ ++ /* Mutable state. */ ++ volatile enum command cmd; ++ volatile unsigned int n_threads_started; ++ volatile unsigned int n_threads_running; ++ volatile unsigned int n_threads_finished; + }; + + static struct global g; + + static void workload_nop(char *dst, char *src, size_t size) + { +- /* Nop */ ++ /* Nop */ + } + + static void workload_memmove(char *dst, char *src, size_t size) + { +- memmove(dst, src, size); ++ memmove(dst, src, size); + } + + struct workload workload_list[WORKLOAD_NUM] = { +- { "no", 0, workload_nop }, +- { "memmove", WORK_NEED_MEM, workload_memmove }, ++ { "no", 0, workload_nop }, ++ { "memmove", WORK_NEED_MEM, workload_memmove }, + }; + +-#define TEST(x) \ +- do { \ +- if( ! (x) ) \ +- test_fail(#x, __LINE__); \ +- } while( 0 ) ++#define TEST(x) \ ++ do { \ ++ if (!(x)) \ ++ test_fail(#x, __LINE__); \ ++ } while (0) + + #define TEST0(x) TEST((x) == 0) + +-static void test_fail(const char* what, int line) ++static void test_fail(const char *what, int line) + { +- fprintf(stderr, "ERROR:\n"); +- fprintf(stderr, "ERROR: TEST(%s)\n", what); +- fprintf(stderr, "ERROR: at line %d\n", line); +- fprintf(stderr, "ERROR: errno=%d (%s)\n", errno, strerror(errno)); +- fprintf(stderr, "ERROR:\n"); +- exit(1); ++ fprintf(stderr, "ERROR:\n"); ++ fprintf(stderr, "ERROR: TEST(%s)\n", what); ++ fprintf(stderr, "ERROR: at line %d\n", line); ++ fprintf(stderr, "ERROR: errno=%d (%s)\n", errno, strerror(errno)); ++ fprintf(stderr, "ERROR:\n"); ++ exit(1); + } + + static int move_to_core(int core_i) + { +- cpu_set_t cpus; +- CPU_ZERO(&cpus); +- CPU_SET(core_i, &cpus); +- return sched_setaffinity(0, sizeof(cpus), &cpus); ++ cpu_set_t cpus; ++ ++ CPU_ZERO(&cpus); ++ CPU_SET(core_i, &cpus); ++ return sched_setaffinity(0, sizeof(cpus), &cpus); + } + + static cycles_t __measure_cpu_hz(void) + { +- struct timeval tvs, tve; +- stamp_t s, e; +- double sec; +- +- frc(&s); +- e = s; +- gettimeofday(&tvs, NULL); +- while( e - s < 1000000 ) +- frc(&e); +- gettimeofday(&tve, NULL); +- sec = tve.tv_sec - tvs.tv_sec + (tve.tv_usec - tvs.tv_usec) / 1e6; +- return (cycles_t) ((e - s) / sec); ++ struct timeval tvs, tve; ++ stamp_t s, e; ++ double sec; ++ ++ frc(&s); ++ e = s; ++ gettimeofday(&tvs, NULL); ++ while (e - s < 1000000) ++ frc(&e); ++ gettimeofday(&tve, NULL); ++ sec = tve.tv_sec - tvs.tv_sec + (tve.tv_usec - tvs.tv_usec) / 1e6; ++ return (cycles_t) ((e - s) / sec); + } + +-static unsigned measure_cpu_mhz(void) ++static unsigned int measure_cpu_mhz(void) + { +- cycles_t m, mprev, d; +- +- mprev = __measure_cpu_hz(); +- do { +- m = __measure_cpu_hz(); +- if( m > mprev ) d = m - mprev; +- else d = mprev - m; +- mprev = m; +- } while( d > m / 1000 ); +- +- return (unsigned) (m / 1000000); ++ cycles_t m, mprev, d; ++ ++ mprev = __measure_cpu_hz(); ++ do { ++ m = __measure_cpu_hz(); ++ if (m > mprev) ++ d = m - mprev; ++ else ++ d = mprev - m; ++ mprev = m; ++ } while (d > m / 1000); ++ ++ return (unsigned int) (m / 1000000); + } + +-static void thread_init(struct thread* t) ++static void thread_init(struct thread *t) + { +- t->cpu_mhz = measure_cpu_mhz(); +- t->maxlat = 0; +- t->overflow_sum = 0; +- t->minlat = (uint64_t)-1; +- +- /* NOTE: all the buffers are not freed until the process quits. */ +- if (!t->memory_allocated) { +- TEST(t->buckets = calloc(1, sizeof(t->buckets[0]) * g.bucket_size)); +- if (g.workload->w_flags & WORK_NEED_MEM) { +- TEST0(posix_memalign((void **)&t->src_buf, getpagesize(), +- g.workload_mem_size)); +- memset(t->src_buf, 0, g.workload_mem_size); +- TEST0(posix_memalign((void **)&t->dst_buf, getpagesize(), +- g.workload_mem_size)); +- memset(t->dst_buf, 0, g.workload_mem_size); +- } +- t->memory_allocated = 1; +- } else { +- /* Clear the buckets */ +- memset(t->buckets, 0, sizeof(t->buckets[0]) * g.bucket_size); +- } ++ t->cpu_mhz = measure_cpu_mhz(); ++ t->maxlat = 0; ++ t->overflow_sum = 0; ++ t->minlat = (uint64_t)-1; ++ ++ /* NOTE: all the buffers are not freed until the process quits. */ ++ if (!t->memory_allocated) { ++ TEST(t->buckets = calloc(1, sizeof(t->buckets[0]) * g.bucket_size)); ++ if (g.workload->w_flags & WORK_NEED_MEM) { ++ TEST0(posix_memalign((void **)&t->src_buf, getpagesize(), ++ g.workload_mem_size)); ++ memset(t->src_buf, 0, g.workload_mem_size); ++ TEST0(posix_memalign((void **)&t->dst_buf, getpagesize(), ++ g.workload_mem_size)); ++ memset(t->dst_buf, 0, g.workload_mem_size); ++ } ++ t->memory_allocated = 1; ++ } else { ++ /* Clear the buckets */ ++ memset(t->buckets, 0, sizeof(t->buckets[0]) * g.bucket_size); ++ } + } + +-static float cycles_to_sec(const struct thread* t, uint64_t cycles) ++static float cycles_to_sec(const struct thread *t, uint64_t cycles) + { +- return cycles / (t->cpu_mhz * 1e6); ++ return cycles / (t->cpu_mhz * 1e6); + } + + static void insert_bucket(struct thread *t, stamp_t value) + { +- int index, us; +- uint64_t extra; +- +- index = value / t->cpu_mhz; +- assert(index >= 0); +- us = index + 1; +- assert(us > 0); +- +- if (g.trace_threshold && us >= g.trace_threshold) { +- char *line = "%s: Trace threshold (%d us) triggered with %u us! " +- "Stopping the test.\n"; +- tracemark(line, g.app_name, g.trace_threshold, us); +- err_quit(line, g.app_name, g.trace_threshold, us); +- } +- +- /* Update max latency */ +- if (us > t->maxlat) { +- t->maxlat = us; +- } +- +- if (us < t->minlat) { +- t->minlat = us; +- } +- +- if (g.bias) { +- /* t->bias will be set after pre-heat if user enabled it */ +- us -= g.bias; +- /* +- * Negative should hardly happen, but if it happens, we assume we're in +- * the smallest bucket, which is 1us. Same to index. +- */ +- if (us <= 0) { +- us = 1; +- } +- index -= g.bias; +- if (index < 0) { +- index = 0; +- } +- } +- +- /* Too big the jitter; put into the last bucket */ +- if (index >= g.bucket_size) { +- /* Keep the extra bit (in us) */ +- extra = index - g.bucket_size; +- if (t->overflow_sum + extra < t->overflow_sum) { +- /* The uint64_t even overflowed itself; bail out */ +- printf("Accumulated overflow too much!\n"); +- exit(1); +- } +- t->overflow_sum += extra; +- index = g.bucket_size - 1; +- } +- +- t->buckets[index]++; +- if (t->buckets[index] == 0) { +- printf("Bucket %d overflowed\n", index); +- exit(1); +- } ++ int index, us; ++ uint64_t extra; ++ ++ index = value / t->cpu_mhz; ++ assert(index >= 0); ++ us = index + 1; ++ assert(us > 0); ++ ++ if (g.trace_threshold && us >= g.trace_threshold) { ++ char *line = "%s: Trace threshold (%d us) triggered with %u us!\n" ++ "Stopping the test.\n"; ++ tracemark(line, g.app_name, g.trace_threshold, us); ++ err_quit(line, g.app_name, g.trace_threshold, us); ++ } ++ ++ /* Update max latency */ ++ if (us > t->maxlat) ++ t->maxlat = us; ++ ++ if (us < t->minlat) ++ t->minlat = us; ++ ++ if (g.bias) { ++ /* t->bias will be set after pre-heat if user enabled it */ ++ us -= g.bias; ++ /* ++ * Negative should hardly happen, but if it happens, we assume we're in ++ * the smallest bucket, which is 1us. Same to index. ++ */ ++ if (us <= 0) ++ us = 1; ++ index -= g.bias; ++ if (index < 0) ++ index = 0; ++ } ++ ++ /* Too big the jitter; put into the last bucket */ ++ if (index >= g.bucket_size) { ++ /* Keep the extra bit (in us) */ ++ extra = index - g.bucket_size; ++ if (t->overflow_sum + extra < t->overflow_sum) { ++ /* The uint64_t even overflowed itself; bail out */ ++ printf("Accumulated overflow too much!\n"); ++ exit(1); ++ } ++ t->overflow_sum += extra; ++ index = g.bucket_size - 1; ++ } ++ ++ t->buckets[index]++; ++ if (t->buckets[index] == 0) { ++ printf("Bucket %d overflowed\n", index); ++ exit(1); ++ } + } + +-static void doit(struct thread* t) ++static void doit(struct thread *t) + { +- stamp_t ts1, ts2; +- workload_fn workload_fn = g.workload->w_fn; +- +- frc(&ts2); +- do { +- workload_fn(t->dst_buf, t->src_buf, g.workload_mem_size); +- frc(&ts1); +- insert_bucket(t, ts1 - ts2); +- ts2 = ts1; +- } while (g.cmd == GO); ++ stamp_t ts1, ts2; ++ workload_fn workload_fn = g.workload->w_fn; ++ ++ frc(&ts2); ++ do { ++ workload_fn(t->dst_buf, t->src_buf, g.workload_mem_size); ++ frc(&ts1); ++ insert_bucket(t, ts1 - ts2); ++ ts2 = ts1; ++ } while (g.cmd == GO); + } + + static int set_fifo_prio(int prio) + { +- struct sched_param param; ++ struct sched_param param; + +- memset(¶m, 0, sizeof(param)); +- param.sched_priority = prio; +- return sched_setscheduler(0, SCHED_FIFO, ¶m); ++ memset(¶m, 0, sizeof(param)); ++ param.sched_priority = prio; ++ return sched_setscheduler(0, SCHED_FIFO, ¶m); + } + +-static void* thread_main(void* arg) ++static void *thread_main(void *arg) + { +- /* Important thing to note here is that once we start bashing the CPU, we +- * need to keep doing so to prevent the core from changing frequency or +- * dropping into a low power state. +- */ +- struct thread* t = arg; +- +- /* Alloc memory in the thread itself after setting affinity to get the +- * best chance of getting numa-local memory. Doesn't matter so much for +- * the "struct thread" since we expect that to stay cache resident. +- */ +- TEST(move_to_core(t->core_i) == 0); +- if (g.rtprio) +- TEST(set_fifo_prio(g.rtprio) == 0); +- +- /* Don't bash the cpu until all threads have got going. */ +- atomic_inc(&g.n_threads_started); +- while( g.cmd == WAIT ) +- usleep(1000); +- +- thread_init(t); +- +- /* Ensure we all start at the same time. */ +- atomic_inc(&g.n_threads_running); +- while( g.n_threads_running != g.n_threads ) +- relax(); +- +- frc(&t->frc_start); +- doit(t); +- frc(&t->frc_stop); +- +- t->runtime = t->frc_stop - t->frc_start; +- +- /* Wait for everyone to finish so we don't disturb them by exiting and +- * waking the main thread. +- */ +- atomic_inc(&g.n_threads_finished); +- while( g.n_threads_finished != g.n_threads ) +- relax(); +- +- return NULL; ++ /* Important thing to note here is that once we start bashing the CPU, we ++ * need to keep doing so to prevent the core from changing frequency or ++ * dropping into a low power state. ++ */ ++ struct thread *t = arg; ++ ++ /* Alloc memory in the thread itself after setting affinity to get the ++ * best chance of getting numa-local memory. Doesn't matter so much for ++ * the "struct thread" since we expect that to stay cache resident. ++ */ ++ TEST(move_to_core(t->core_i) == 0); ++ if (g.rtprio) ++ TEST(set_fifo_prio(g.rtprio) == 0); ++ ++ /* Don't bash the cpu until all threads have got going. */ ++ atomic_inc(&g.n_threads_started); ++ while (g.cmd == WAIT) ++ usleep(1000); ++ ++ thread_init(t); ++ ++ /* Ensure we all start at the same time. */ ++ atomic_inc(&g.n_threads_running); ++ while (g.n_threads_running != g.n_threads) ++ relax(); ++ ++ frc(&t->frc_start); ++ doit(t); ++ frc(&t->frc_stop); ++ ++ t->runtime = t->frc_stop - t->frc_start; ++ ++ /* Wait for everyone to finish so we don't disturb them by exiting and ++ * waking the main thread. ++ */ ++ atomic_inc(&g.n_threads_finished); ++ while (g.n_threads_finished != g.n_threads) ++ relax(); ++ ++ return NULL; + } + +-#define putfield(label, val, fmt, end) do { \ +- printf("%12s:\t", label); \ +- for (i = 0; i < g.n_threads; ++i) \ +- printf(" %"fmt, val); \ +- printf("%s\n", end); \ +- } while (0) ++#define putfield(label, val, fmt, end) do { \ ++ printf("%12s:\t", label); \ ++ for (i = 0; i < g.n_threads; ++i) \ ++ printf(" %"fmt, val); \ ++ printf("%s\n", end); \ ++ } while (0) + + void calculate(struct thread *t) + { +- int i, j; +- double sum; +- uint64_t count; +- +- for (i = 0; i < g.n_threads; ++i) { +- /* Calculate average */ +- sum = count = 0; +- for (j = 0; j < g.bucket_size; j++) { +- sum += 1.0 * t[i].buckets[j] * (g.bias+j+1); +- count += t[i].buckets[j]; +- } +- /* Add the extra amount of huge spikes in */ +- sum += t->overflow_sum; +- t[i].average = sum / count; +- } ++ int i, j; ++ double sum; ++ uint64_t count; ++ ++ for (i = 0; i < g.n_threads; ++i) { ++ /* Calculate average */ ++ sum = count = 0; ++ for (j = 0; j < g.bucket_size; j++) { ++ sum += 1.0 * t[i].buckets[j] * (g.bias+j+1); ++ count += t[i].buckets[j]; ++ } ++ /* Add the extra amount of huge spikes in */ ++ sum += t->overflow_sum; ++ t[i].average = sum / count; ++ } + } + +-static void write_summary(struct thread* t) ++static void write_summary(struct thread *t) + { +- int i, j, k, print_dotdotdot = 0; +- char bucket_name[64]; +- +- calculate(t); +- +- putfield("Core", t[i].core_i, "d", ""); +- putfield("CPU Freq", t[i].cpu_mhz, "u", " (Mhz)"); +- +- for (j = 0; j < g.bucket_size; j++) { +- if (j < g.bucket_size-1 && g.output_omit_zero_buckets) { +- for (k = 0; k < g.n_threads; k++) { +- if (t[k].buckets[j] != 0) +- break; +- } +- if (k == g.n_threads) { +- print_dotdotdot = 1; +- continue; +- } +- } +- +- if (print_dotdotdot) { +- printf(" ...\n"); +- print_dotdotdot = 0; +- } +- +- snprintf(bucket_name, sizeof(bucket_name), "%03"PRIu64 +- " (us)", g.bias+j+1); +- putfield(bucket_name, t[i].buckets[j], PRIu64, +- (j==g.bucket_size-1) ? " (including overflows)" : ""); +- } +- +- putfield("Minimum", t[i].minlat, PRIu64, " (us)"); +- putfield("Average", t[i].average, ".3lf", " (us)"); +- putfield("Maximum", t[i].maxlat, PRIu64, " (us)"); +- putfield("Max-Min", t[i].maxlat - t[i].minlat, PRIu64, " (us)"); +- putfield("Duration", cycles_to_sec(&(t[i]), t[i].runtime), +- ".3f", " (sec)"); +- printf("\n"); ++ int i, j, k, print_dotdotdot = 0; ++ char bucket_name[64]; ++ ++ calculate(t); ++ ++ putfield("Core", t[i].core_i, "d", ""); ++ putfield("CPU Freq", t[i].cpu_mhz, "u", " (Mhz)"); ++ ++ for (j = 0; j < g.bucket_size; j++) { ++ if (j < g.bucket_size-1 && g.output_omit_zero_buckets) { ++ for (k = 0; k < g.n_threads; k++) { ++ if (t[k].buckets[j] != 0) ++ break; ++ } ++ if (k == g.n_threads) { ++ print_dotdotdot = 1; ++ continue; ++ } ++ } ++ ++ if (print_dotdotdot) { ++ printf(" ...\n"); ++ print_dotdotdot = 0; ++ } ++ ++ snprintf(bucket_name, sizeof(bucket_name), "%03"PRIu64 ++ " (us)", g.bias+j+1); ++ putfield(bucket_name, t[i].buckets[j], PRIu64, ++ (j == g.bucket_size - 1) ? " (including overflows)" : ""); ++ } ++ ++ putfield("Minimum", t[i].minlat, PRIu64, " (us)"); ++ putfield("Average", t[i].average, ".3lf", " (us)"); ++ putfield("Maximum", t[i].maxlat, PRIu64, " (us)"); ++ putfield("Max-Min", t[i].maxlat - t[i].minlat, PRIu64, " (us)"); ++ putfield("Duration", cycles_to_sec(&(t[i]), t[i].runtime), ++ ".3f", " (sec)"); ++ printf("\n"); + } + +-static void run_expt(struct thread* threads, int runtime_secs) ++static void run_expt(struct thread *threads, int runtime_secs) + { +- int i; +- +- g.runtime_secs = runtime_secs; +- g.n_threads_started = 0; +- g.n_threads_ready = 0; +- g.n_threads_running = 0; +- g.n_threads_finished = 0; +- g.cmd = WAIT; +- +- for( i = 0; i < g.n_threads; ++i ) { +- TEST0(pthread_create(&(threads[i].thread_id), NULL, +- thread_main, &(threads[i]))); +- } +- while( g.n_threads_started != g.n_threads ) { +- usleep(1000); +- } +- +- gettimeofday(&g.tv_start, NULL); +- g.cmd = GO; +- +- alarm(runtime_secs); +- +- /* Go to sleep until the threads have done their stuff. */ +- for( i = 0; i < g.n_threads; ++i ) { +- pthread_join(threads[i].thread_id, NULL); +- } ++ int i; ++ ++ g.runtime_secs = runtime_secs; ++ g.n_threads_started = 0; ++ g.n_threads_running = 0; ++ g.n_threads_finished = 0; ++ g.cmd = WAIT; ++ ++ for (i = 0; i < g.n_threads; ++i) ++ TEST0(pthread_create(&(threads[i].thread_id), NULL, ++ thread_main, &(threads[i]))); ++ while (g.n_threads_started != g.n_threads) ++ usleep(1000); ++ ++ gettimeofday(&g.tv_start, NULL); ++ g.cmd = GO; ++ ++ alarm(runtime_secs); ++ ++ /* Go to sleep until the threads have done their stuff. */ ++ for (i = 0; i < g.n_threads; ++i) ++ pthread_join(threads[i].thread_id, NULL); + } + + static void handle_alarm(int code) + { +- g.cmd = STOP; ++ g.cmd = STOP; + } + + const char *helpmsg = +- "Usage: %s [options]\n" +- "\n" +- "This is an OS latency detector by running busy loops on specified cores.\n" +- "Please run this tool using root.\n" +- "\n" +- "Available options:\n" +- "\n" +- " -b, --bucket-size Specify the number of the buckets (4-1024)\n" +- " -B, --bias Add a bias to all the buckets using the estimated mininum\n" +- " -c, --cpu-list Specify CPUs to run on, e.g. '1,3,5,7-15'\n" +- " -C, --cpu-main-thread Specify which CPU the main thread runs on. Default is cpu0.\n" +- " -f, --rtprio Using SCHED_FIFO priority (1-99)\n" +- " -m, --workload-mem Size of the memory to use for the workload (e.g., 4K, 1M).\n" +- " 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" +- " -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" +- " to lock the freq then please don't use this parameter.\n" +- " -t, --runtime Specify test duration, e.g., 60, 20m, 2H\n" +- " (m/M: minutes, h/H: hours, d/D: days)\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" +- " -w, --workload Specify a kind of workload, default is no workload\n" +- " (options: no, memmove)\n" +- " -z, --zero-omit Don't display buckets in the output histogram if all zeros.\n" +- "\n" +- ; ++"Usage: %s [options]\n" ++"\n" ++"This is an OS latency detector by running busy loops on specified cores.\n" ++"Please run this tool using root.\n" ++"\n" ++"Available options:\n" ++"\n" ++" -b, --bucket-size Specify the number of the buckets (4-1024)\n" ++" -B, --bias Add a bias to all the buckets using the estimated mininum\n" ++" -c, --cpu-list Specify CPUs to run on, e.g. '1,3,5,7-15'\n" ++" -C, --cpu-main-thread Specify which CPU the main thread runs on. Default is cpu0.\n" ++" -f, --rtprio Using SCHED_FIFO priority (1-99)\n" ++" -m, --workload-mem Size of the memory to use for the workload (e.g., 4K, 1M).\n" ++" 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" ++" -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" ++" to lock the freq then please don't use this parameter.\n" ++" -t, --runtime Specify test duration, e.g., 60, 20m, 2H\n" ++" (m/M: minutes, h/H: hours, d/D: days)\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" ++" -w, --workload Specify a kind of workload, default is no workload\n" ++" (options: no, memmove)\n" ++" -z, --zero-omit Don't display buckets in the output histogram if all zeros.\n" ++"\n" ++; + + static void usage(void) + { +- printf(helpmsg, g.app_name); +- exit(1); ++ printf(helpmsg, g.app_name); ++ exit(1); + } + + /* TODO: use libnuma? */ + static int parse_cpu_list(char *cpu_list, cpu_set_t *cpu_set) + { +- struct bitmask *cpu_mask; +- int i, n_cores; +- +- n_cores = sysconf(_SC_NPROCESSORS_CONF); +- +- if (!cpu_list) { +- for (i = 0; i < n_cores; i++) +- CPU_SET(i, cpu_set); +- return n_cores; +- } +- +- cpu_mask = numa_parse_cpustring_all(cpu_list); +- if (cpu_mask) { +- for (i = 0; i < n_cores; i++) { +- if (numa_bitmask_isbitset(cpu_mask, i)) { +- CPU_SET(i, cpu_set); +- } +- } +- numa_bitmask_free(cpu_mask); +- } else { +- warn("Unknown cpu-list: %s, using all available cpus\n", cpu_list); +- for (i = 0; i < n_cores; i++) +- CPU_SET(i, cpu_set); +- } +- +- return n_cores; ++ struct bitmask *cpu_mask; ++ int i, n_cores; ++ ++ n_cores = sysconf(_SC_NPROCESSORS_CONF); ++ ++ if (!cpu_list) { ++ for (i = 0; i < n_cores; i++) ++ CPU_SET(i, cpu_set); ++ return n_cores; ++ } ++ ++ cpu_mask = numa_parse_cpustring_all(cpu_list); ++ if (cpu_mask) { ++ for (i = 0; i < n_cores; i++) { ++ if (numa_bitmask_isbitset(cpu_mask, i)) ++ CPU_SET(i, cpu_set); ++ } ++ numa_bitmask_free(cpu_mask); ++ } else { ++ warn("Unknown cpu-list: %s, using all available cpus\n", cpu_list); ++ for (i = 0; i < n_cores; i++) ++ CPU_SET(i, cpu_set); ++ } ++ ++ return n_cores; + } + + static int parse_runtime(const char *str) + { +- char *endptr; +- int v = strtol(str, &endptr, 10); +- +- if (!*endptr) { +- return v; +- } +- +- switch (*endptr) { +- case 'd': +- case 'D': +- /* Days */ +- v *= 24; +- case 'h': +- case 'H': +- /* Hours */ +- v *= 60; +- case 'm': +- case 'M': +- /* Minutes */ +- v *= 60; +- case 's': +- case 'S': +- /* Seconds */ +- break; +- default: +- printf("Unknown runtime suffix: %s\n", endptr); +- v = 0; +- break; +- } +- +- return v; ++ char *endptr; ++ int v = strtol(str, &endptr, 10); ++ ++ if (!*endptr) ++ return v; ++ ++ switch (*endptr) { ++ case 'd': ++ case 'D': ++ /* Days */ ++ v *= 24; ++ case 'h': ++ case 'H': ++ /* Hours */ ++ v *= 60; ++ case 'm': ++ case 'M': ++ /* Minutes */ ++ v *= 60; ++ case 's': ++ case 'S': ++ /* Seconds */ ++ break; ++ default: ++ printf("Unknown runtime suffix: %s\n", endptr); ++ v = 0; ++ break; ++ } ++ ++ return v; + } + + static int parse_mem_size(char *str, uint64_t *val) + { +- char *endptr; +- int v = strtol(str, &endptr, 10); +- +- if (!*endptr) { +- return v; +- } +- +- switch (*endptr) { +- case 'g': +- case 'G': +- v *= 1024; +- case 'm': +- case 'M': +- v *= 1024; +- case 'k': +- case 'K': +- v *= 1024; +- case 'b': +- case 'B': +- break; +- default: +- return -1; +- } +- +- *val = v; +- +- return 0; ++ char *endptr; ++ int v = strtol(str, &endptr, 10); ++ ++ if (!*endptr) ++ return v; ++ ++ switch (*endptr) { ++ case 'g': ++ case 'G': ++ v *= 1024; ++ case 'm': ++ case 'M': ++ v *= 1024; ++ case 'k': ++ case 'K': ++ v *= 1024; ++ case 'b': ++ case 'B': ++ break; ++ default: ++ return -1; ++ } ++ ++ *val = v; ++ ++ return 0; + } + + static int workload_select(char *name) + { +- int i = 0; ++ int i = 0; + +- for (i = 0; i < WORKLOAD_NUM; i++) { +- if (!strcmp(name, workload_list[i].w_name)) { +- g.workload = &workload_list[i]; +- return 0; +- } +- } ++ for (i = 0; i < WORKLOAD_NUM; i++) { ++ if (!strcmp(name, workload_list[i].w_name)) { ++ g.workload = &workload_list[i]; ++ return 0; ++ } ++ } + +- return -1; ++ return -1; + } + + /* Process commandline options */ + static void parse_options(int argc, char *argv[]) + { +- while (1) { +- static struct option options[] = { +- { "bucket-size", required_argument, NULL, 'b' }, +- { "cpu-list", required_argument, NULL, 'c' }, +- { "cpu-main-thread", required_argument, NULL, 'C'}, +- { "runtime", required_argument, NULL, 't' }, +- { "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'}, +- { NULL, 0, NULL, 0 }, +- }; +- int i, c = getopt_long(argc, argv, "b:Bc:C:f:hm:st:w:T:vz", +- options, NULL); +- long ncores; +- +- if (c == -1) +- break; +- +- switch (c) { +- case 'b': +- g.bucket_size = strtol(optarg, NULL, 10); +- if (g.bucket_size > 1024 || g.bucket_size <= 4) { +- printf("Illegal bucket size: %s (should be: 4-1024)\n", +- optarg); +- exit(1); +- } +- break; +- case 'B': +- g.enable_bias = 1; +- break; +- case 'c': +- g.cpu_list = strdup(optarg); +- break; +- case 'C': +- ncores = sysconf(_SC_NPROCESSORS_CONF); +- g.cpu_main_thread = strtol(optarg, NULL, 10); +- if (g.cpu_main_thread < 0 || g.cpu_main_thread > ncores) { +- printf("Illegal core for main thread: %s (should be: 0-%ld)\n", +- optarg, ncores); +- exit(1); +- } +- break; +- case 't': +- g.runtime = parse_runtime(optarg); +- if (!g.runtime) { +- printf("Illegal runtime: %s\n", optarg); +- exit(1); +- } +- break; +- case 'f': +- g.rtprio = strtol(optarg, NULL, 10); +- if (g.rtprio < 1 || g.rtprio > 99) { +- printf("Illegal RT priority: %s (should be: 1-99)\n", optarg); +- exit(1); +- } +- break; +- case 'T': +- g.trace_threshold = strtol(optarg, NULL, 10); +- if (g.trace_threshold <= 0) { +- printf("Parameter --trace-threshold needs to be positive\n"); +- exit(1); +- } +- enable_trace_mark(); +- break; +- case 'w': +- if (workload_select(optarg)) { +- printf("Unknown workload '%s'. Please choose from: ", optarg); +- for (i = 0; i < WORKLOAD_NUM; i++) { +- printf("'%s'", workload_list[i].w_name); +- if (i != WORKLOAD_NUM - 1) { +- printf(", "); +- } +- } +- printf("\n\n"); +- exit(1); +- } +- break; +- case 'm': +- if (parse_mem_size(optarg, &g.workload_mem_size)) { +- printf("Unknown workload memory size '%s'.\n\n", optarg); +- exit(1); +- } +- break; +- case 's': +- /* +- * Only use one core for pre-heat. Then if --bias is used, the +- * bias will be exactly the min value of the pre-heat core. +- */ +- g.single_preheat_thread = true; +- break; +- case 'v': +- /* +- * Because we always dump the version even before parsing options, +- * what we need to do is to quit.. +- */ +- exit(0); +- break; +- case 'z': +- g.output_omit_zero_buckets = 1; +- break; +- default: +- usage(); +- break; +- } +- } ++ while (1) { ++ static struct option options[] = { ++ { "bucket-size", required_argument, NULL, 'b' }, ++ { "cpu-list", required_argument, NULL, 'c' }, ++ { "cpu-main-thread", required_argument, NULL, 'C'}, ++ { "runtime", required_argument, NULL, 't' }, ++ { "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'}, ++ { NULL, 0, NULL, 0 }, ++ }; ++ int i, c = getopt_long(argc, argv, "b:Bc:C:f:hm:st:w:T:vz", ++ options, NULL); ++ long ncores; ++ ++ if (c == -1) ++ break; ++ ++ switch (c) { ++ case 'b': ++ g.bucket_size = strtol(optarg, NULL, 10); ++ if (g.bucket_size > 1024 || g.bucket_size <= 4) { ++ printf("Illegal bucket size: %s (should be: 4-1024)\n", ++ optarg); ++ exit(1); ++ } ++ break; ++ case 'B': ++ g.enable_bias = 1; ++ break; ++ case 'c': ++ g.cpu_list = strdup(optarg); ++ break; ++ case 'C': ++ ncores = sysconf(_SC_NPROCESSORS_CONF); ++ g.cpu_main_thread = strtol(optarg, NULL, 10); ++ if (g.cpu_main_thread < 0 || g.cpu_main_thread > ncores) { ++ printf("Illegal core for main thread: %s (should be: 0-%ld)\n", ++ optarg, ncores); ++ exit(1); ++ } ++ break; ++ case 't': ++ g.runtime = parse_runtime(optarg); ++ if (!g.runtime) { ++ printf("Illegal runtime: %s\n", optarg); ++ exit(1); ++ } ++ break; ++ case 'f': ++ g.rtprio = strtol(optarg, NULL, 10); ++ if (g.rtprio < 1 || g.rtprio > 99) { ++ printf("Illegal RT priority: %s (should be: 1-99)\n", optarg); ++ exit(1); ++ } ++ break; ++ case 'T': ++ g.trace_threshold = strtol(optarg, NULL, 10); ++ if (g.trace_threshold <= 0) { ++ printf("Parameter --trace-threshold needs to be positive\n"); ++ exit(1); ++ } ++ enable_trace_mark(); ++ break; ++ case 'w': ++ if (workload_select(optarg)) { ++ printf("Unknown workload '%s'. Please choose from: ", optarg); ++ for (i = 0; i < WORKLOAD_NUM; i++) { ++ printf("'%s'", workload_list[i].w_name); ++ if (i != WORKLOAD_NUM - 1) ++ printf(", "); ++ } ++ printf("\n\n"); ++ exit(1); ++ } ++ break; ++ case 'm': ++ if (parse_mem_size(optarg, &g.workload_mem_size)) { ++ printf("Unknown workload memory size '%s'.\n\n", optarg); ++ exit(1); ++ } ++ break; ++ case 's': ++ /* ++ * Only use one core for pre-heat. Then if --bias is used, the ++ * bias will be exactly the min value of the pre-heat core. ++ */ ++ g.single_preheat_thread = true; ++ break; ++ case 'v': ++ /* ++ * Because we always dump the version even before parsing options, ++ * what we need to do is to quit.. ++ */ ++ exit(0); ++ break; ++ case 'z': ++ g.output_omit_zero_buckets = 1; ++ break; ++ default: ++ usage(); ++ break; ++ } ++ } + } + + void dump_globals(void) + { +- printf("Total runtime: \t\t%d seconds\n", g.runtime); +- printf("Thread priority: \t"); +- if (g.rtprio) { +- printf("SCHED_FIFO:%d\n", g.rtprio); +- } else { +- printf("default\n"); +- } +- printf("CPU list: \t\t%s\n", g.cpu_list ?: "(all cores)"); +- printf("CPU for main thread: \t%d\n", g.cpu_main_thread); +- printf("Workload: \t\t%s\n", g.workload->w_name); +- printf("Workload mem: \t\t%"PRIu64" (KiB)\n", +- (g.workload->w_flags & WORK_NEED_MEM) ? +- (g.workload_mem_size / 1024) : 0); +- printf("Preheat cores: \t\t%d\n", g.single_preheat_thread ? +- 1 : g.n_threads_total); +- printf("\n"); ++ printf("Total runtime: \t\t%d seconds\n", g.runtime); ++ printf("Thread priority: \t"); ++ if (g.rtprio) ++ printf("SCHED_FIFO:%d\n", g.rtprio); ++ else ++ printf("default\n"); ++ printf("CPU list: \t\t%s\n", g.cpu_list ?: "(all cores)"); ++ printf("CPU for main thread: \t%d\n", g.cpu_main_thread); ++ printf("Workload: \t\t%s\n", g.workload->w_name); ++ printf("Workload mem: \t\t%"PRIu64" (KiB)\n", ++ (g.workload->w_flags & WORK_NEED_MEM) ? ++ (g.workload_mem_size / 1024) : 0); ++ printf("Preheat cores: \t\t%d\n", g.single_preheat_thread ? ++ 1 : g.n_threads_total); ++ printf("\n"); + } + + static void record_bias(struct thread *t) + { +- int i; +- uint64_t bias = (uint64_t)-1; +- +- if (!g.enable_bias) { +- return; +- } +- +- /* Record the min value of minlat on all the threads */ +- for( i = 0; i < g.n_threads; ++i ) { +- if (t[i].minlat < bias) { +- bias = t[i].minlat; +- } +- } +- g.bias = bias; +- printf("Global bias set to %" PRId64 " (us)\n", bias); ++ int i; ++ uint64_t bias = (uint64_t)-1; ++ ++ if (!g.enable_bias) ++ return; ++ ++ /* Record the min value of minlat on all the threads */ ++ for (i = 0; i < g.n_threads; ++i) { ++ if (t[i].minlat < bias) ++ bias = t[i].minlat; ++ } ++ g.bias = bias; ++ printf("Global bias set to %" PRId64 " (us)\n", bias); + } + +-int main(int argc, char* argv[]) ++int main(int argc, char *argv[]) + { +- struct thread* threads; +- int i, n_cores; +- cpu_set_t cpu_set; ++ struct thread *threads; ++ int i, n_cores; ++ cpu_set_t cpu_set; + +- CPU_ZERO(&cpu_set); ++ CPU_ZERO(&cpu_set); + +- g.app_name = argv[0]; +- g.rtprio = 0; +- g.bucket_size = BUCKET_SIZE; +- g.runtime = 1; +- g.workload = &workload_list[WORKLOAD_DEFUALT]; +- g.workload_mem_size = WORKLOAD_MEM_SIZE; +- /* Run the main thread on cpu0 by default */ +- g.cpu_main_thread = 0; ++ g.app_name = argv[0]; ++ g.rtprio = 0; ++ g.bucket_size = BUCKET_SIZE; ++ g.runtime = 1; ++ g.workload = &workload_list[WORKLOAD_DEFAULT]; ++ g.workload_mem_size = WORKLOAD_MEM_SIZE; ++ /* Run the main thread on cpu0 by default */ ++ g.cpu_main_thread = 0; + +- printf("\nVersion: %1.2f\n\n", VERSION); ++ printf("\nVersion: %1.2f\n\n", VERSION); + +- parse_options(argc, argv); ++ parse_options(argc, argv); + +- TEST(mlockall(MCL_CURRENT | MCL_FUTURE) == 0); ++ TEST(mlockall(MCL_CURRENT | MCL_FUTURE) == 0); + +- n_cores = parse_cpu_list(g.cpu_list, &cpu_set); ++ n_cores = parse_cpu_list(g.cpu_list, &cpu_set); + +- TEST( threads = calloc(1, CPU_COUNT(&cpu_set) * sizeof(threads[0])) ); +- for( i = 0; i < n_cores; ++i ) +- if (CPU_ISSET(i, &cpu_set) && move_to_core(i) == 0) +- threads[g.n_threads_total++].core_i = i; ++ TEST(threads = calloc(1, CPU_COUNT(&cpu_set) * sizeof(threads[0]))); ++ for (i = 0; i < n_cores; ++i) ++ if (CPU_ISSET(i, &cpu_set) && move_to_core(i) == 0) ++ threads[g.n_threads_total++].core_i = i; + +- if (CPU_ISSET(0, &cpu_set) && g.rtprio) { +- printf("WARNING: Running SCHED_FIFO workload on CPU 0 " +- "may hang the main thread\n"); +- } ++ if (CPU_ISSET(0, &cpu_set) && g.rtprio) ++ printf("WARNING: Running SCHED_FIFO workload on CPU 0 may hang the thread\n"); + +- TEST(move_to_core(g.cpu_main_thread) == 0); ++ TEST(move_to_core(g.cpu_main_thread) == 0); + +- signal(SIGALRM, handle_alarm); +- signal(SIGINT, handle_alarm); +- signal(SIGTERM, handle_alarm); ++ signal(SIGALRM, handle_alarm); ++ signal(SIGINT, handle_alarm); ++ signal(SIGTERM, handle_alarm); + +- dump_globals(); ++ dump_globals(); + +- printf("Pre-heat for 1 seconds...\n"); +- if (g.single_preheat_thread) { +- g.n_threads = 1; +- } else { +- g.n_threads = g.n_threads_total; +- } +- run_expt(threads, 1); +- record_bias(threads); ++ printf("Pre-heat for 1 seconds...\n"); ++ if (g.single_preheat_thread) ++ g.n_threads = 1; ++ else ++ g.n_threads = g.n_threads_total; ++ run_expt(threads, 1); ++ record_bias(threads); + +- 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 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"); ++ printf("Test completed.\n\n"); + +- write_summary(threads); ++ write_summary(threads); + +- if (g.cpu_list) { +- free(g.cpu_list); +- g.cpu_list = NULL; +- } ++ if (g.cpu_list) { ++ free(g.cpu_list); ++ g.cpu_list = NULL; ++ } + +- return 0; ++ return 0; + } +-- +2.26.2 + diff --git a/SOURCES/rt-tests-pi_stress-Add-short-options-to-usage-msg.patch b/SOURCES/rt-tests-pi_stress-Add-short-options-to-usage-msg.patch deleted file mode 100644 index b37eca0..0000000 --- a/SOURCES/rt-tests-pi_stress-Add-short-options-to-usage-msg.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 7a2ce964eaaa4de96fb81d7fea72350d1c82b3ba Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 16 Jan 2020 21:51:40 +0100 -Subject: [PATCH 2/8] rt-tests: pi_stress: Add short options to usage message - -Add short options to usage message. Note, the options all ready exist, -they simply were not documented in the usage message. - -Signed-off-by: John Kacur ---- - src/pi_tests/pi_stress.c | 34 +++++++++++++++------------------- - 1 file changed, 15 insertions(+), 19 deletions(-) - -diff --git a/src/pi_tests/pi_stress.c b/src/pi_tests/pi_stress.c -index 7fa98dfb9ad4..0ed844c636cd 100644 ---- a/src/pi_tests/pi_stress.c -+++ b/src/pi_tests/pi_stress.c -@@ -1008,29 +1008,25 @@ void *high_priority(void *arg) - - void usage(void) - { -- printf("usage: pi_stress \n"); -- printf(" options:\n"); -- printf("\t--verbose\t- lots of output\n"); -- printf("\t--quiet\t\t- suppress running output\n"); -- printf -- ("\t--duration=\t- length of the test run in seconds [infinite]\n"); -- printf("\t\t\t Append 'm', 'h', or 'd' to specify minutes, hours or days.\n"); -- printf("\t--groups=\t- set the number of inversion groups [%d]\n", -+ printf("usage: pi_stress \n\n"); -+ printf("-v\t--verbose\t- lots of output\n"); -+ printf("-q\t--quiet\t\t- suppress running output\n"); -+ printf ("-D TIME\t--duration=TIME\n\t\t\t- length of test run in seconds (default is infinite)\n"); -+ printf("\t\t\t Append 'm', 'h', or 'd'\n\t\t\t to specify minutes, hours or days.\n"); -+ printf("-g\t--groups=\t- set the number of inversion groups [%d]\n", - ngroups); -- printf -- ("\t--inversions=- number of inversions per group [infinite]\n"); -- printf("\t--rr\t\t- use SCHED_RR for test threads [SCHED_FIFO]\n"); -- printf("\t--sched\t\t- scheduling options per thread type:\n"); -+ printf ("-i INVERSIONS\t\t--inversions=INVERSIONS\n\t\t\t number of inversions per group (default is infinite)\n"); -+ printf("-r\t--rr\t\t- use SCHED_RR for test threads [SCHED_FIFO]\n"); -+ printf("-s SCHED_OPTS\t--sched\t\t- scheduling options per thread type:\n"); - printf("\t\tid=[high|med|low]\t\t\t- select thread\n"); - printf("\t\t,policy=[fifo,rr],priority=\t\t- SCHED_FIFO or SCHED_RR\n"); - printf("\t\t,policy=deadline,runtime=,deadline=,period=\t- SCHED_DEADLINE\n"); -- printf("\t--prompt\t- prompt before starting the test\n"); -- printf -- ("\t--uniprocessor\t- force all threads to run on one processor\n"); -- printf("\t--mlockall\t- lock current and future memory\n"); -- printf("\t--debug\t\t- turn on debug prints\n"); -- printf("\t--version\t- print version number on output\n"); -- printf("\t--help\t\t- print this message\n"); -+ printf("-p\t--prompt\t- prompt before starting the test\n"); -+ printf ("-u\t--uniprocessor\t- force all threads to run on one processor\n"); -+ printf("-m\t--mlockall\t- lock current and future memory\n"); -+ printf("-d\t--debug\t\t- turn on debug prints\n"); -+ printf("-V\t--version\t- print version number on output\n"); -+ printf("-h\t--help\t\t- print this message\n"); - } - - /* block all signals (called from main) */ --- -2.20.1 - diff --git a/SOURCES/rt-tests-pi_stress.8-Remove-unused-t-n-from-the-manp.patch b/SOURCES/rt-tests-pi_stress.8-Remove-unused-t-n-from-the-manp.patch new file mode 100644 index 0000000..17aba2f --- /dev/null +++ b/SOURCES/rt-tests-pi_stress.8-Remove-unused-t-n-from-the-manp.patch @@ -0,0 +1,41 @@ +From 868ee948b626dced91bb98207ebd6b3a52f9fcfc Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Fri, 3 Jul 2020 13:28:39 -0400 +Subject: [PATCH 2/7] rt-tests: pi_stress.8: Remove unused -t n from the + manpage + +The -t option was replaced with the -D, --duration=TIME option +Remove it from the manpage as well. + +Signed-off-by: John Kacur +--- + src/pi_tests/pi_stress.8 | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/src/pi_tests/pi_stress.8 b/src/pi_tests/pi_stress.8 +index 5e2af6189ca1..ed03ad6187e7 100644 +--- a/src/pi_tests/pi_stress.8 ++++ b/src/pi_tests/pi_stress.8 +@@ -15,8 +15,6 @@ pi_stress \- a stress test for POSIX Priority Inheritance mutexes + .B pi_stress + .RB [ \-i|\-\-inversions + .IR inversions ] +-.RB [ \-t|\-\-duration +-.IR seconds ] + .RB [ \-g|\-\-groups + .IR groups + .RB [ \-d|\-\-debug ] +@@ -50,10 +48,6 @@ Run for + .I n + number of inversion conditions. This is the total number of inversions + for all inversion groups. Default is \-1 for infinite. +-.IP "\-t n|\-\-duration=n" +-Run the test for +-.I n +-seconds and then terminate. + .IP "\-g n|\-\-groups=n" + The number of inversion groups to run. Defaults to 10. + .IP \-d|\-\-debug +-- +2.21.3 + diff --git a/SOURCES/rt-tests-ptsematest-Update-man-page-and-add-h-option.patch b/SOURCES/rt-tests-ptsematest-Update-man-page-and-add-h-option.patch deleted file mode 100644 index e3274b8..0000000 --- a/SOURCES/rt-tests-ptsematest-Update-man-page-and-add-h-option.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 68cba61ce524c40163d5f76ef09f738b69f0c331 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 23 Jan 2020 18:19:34 +0100 -Subject: [PATCH 6/8] rt-tests: ptsematest: Update man page and add -h option - -- Update the man page with the -s or --smp option -- Reorder the program help to match the man page -- Make the -h option work correctly - -Signed-off-by: John Kacur ---- - src/ptsematest/ptsematest.8 | 3 +++ - src/ptsematest/ptsematest.c | 10 ++++++---- - 2 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/src/ptsematest/ptsematest.8 b/src/ptsematest/ptsematest.8 -index 4bb1434babf4..8f76bca4b6a8 100644 ---- a/src/ptsematest/ptsematest.8 -+++ b/src/ptsematest/ptsematest.8 -@@ -35,6 +35,9 @@ Set the number of loops. The default is 0 (endless). This option is useful for a - .B \-p, \-\-prio=PRIO - Set the priority of the process. - .TP -+.B \-s, \-\-smp -+SMP testing: options -a -t and same priority -+.TP - .B \-t, \-\-threads[=NUM] - Set the number of test threads (default is 1, if this option is not given). If NUM is specified, create NUM test threads. If NUM is not specified, NUM is set to the number of available CPUs. - .SH "EXAMPLES" -diff --git a/src/ptsematest/ptsematest.c b/src/ptsematest/ptsematest.c -index 78fa444c5578..485c991ec173 100644 ---- a/src/ptsematest/ptsematest.c -+++ b/src/ptsematest/ptsematest.c -@@ -154,10 +154,10 @@ static void display_help(void) - " with NUM pin all threads to the processor NUM\n" - "-b USEC --breaktrace=USEC send break trace command when latency > USEC\n" - "-d DIST --distance=DIST distance of thread intervals in us default=500\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" - "-D --duration=TIME specify a length for the test run.\n" - " Append 'm', 'h', or 'd' to specify minutes, hours or 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" - "-p PRIO --prio=PRIO priority\n" - "-S --smp SMP testing: options -a -t and same priority\n" - " of all threads\n" -@@ -202,7 +202,7 @@ static void process_options (int argc, char *argv[]) - {"help", no_argument, NULL, '?'}, - {NULL, 0, NULL, 0} - }; -- int c = getopt_long (argc, argv, "a::b:d:i:l:D:p:St::", -+ int c = getopt_long (argc, argv, "a::b:d:i:l:D:p:St::h", - long_options, &option_index); - if (c == -1) - break; -@@ -245,6 +245,8 @@ static void process_options (int argc, char *argv[]) - else - num_threads = max_cpus; - break; -+ case 'h': -+ display_help(); - case '?': error = 1; break; - } - } -@@ -275,7 +277,7 @@ static void process_options (int argc, char *argv[]) - sameprio = 1; - - if (error) -- display_help (); -+ display_help(); - } - - --- -2.20.1 - diff --git a/SOURCES/rt-tests-ptsematest.8-Update-the-ptsematest-man-page.patch b/SOURCES/rt-tests-ptsematest.8-Update-the-ptsematest-man-page.patch new file mode 100644 index 0000000..566d8c7 --- /dev/null +++ b/SOURCES/rt-tests-ptsematest.8-Update-the-ptsematest-man-page.patch @@ -0,0 +1,41 @@ +From e554f3d5d95330ba0b961bc7e7ecf3a19485b1c9 Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Fri, 3 Jul 2020 19:15:41 -0400 +Subject: [PATCH 3/7] rt-tests: ptsematest.8: Update the ptsematest man page + +The smp option should be a capital (-S) +Also fix the update synopsis to include missing and options + +Signed-off-by: John Kacur +--- + src/ptsematest/ptsematest.8 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/ptsematest/ptsematest.8 b/src/ptsematest/ptsematest.8 +index 8f76bca4b6a8..5ee7d694d50d 100644 +--- a/src/ptsematest/ptsematest.8 ++++ b/src/ptsematest/ptsematest.8 +@@ -2,9 +2,9 @@ + .SH "NAME" + .LP + \fBptsematest\fR \- Start two threads and measure the latency of interprocess communication with POSIX mutex. +-.SH "SYNTAX" ++.SH "SYNOPSIS" + .LP +-ptsematest [-a|-a PROC] [-b USEC] [-d DIST] [-i INTV] [-l loops] [-p PRIO] [-t|-t NUM] ++ptsematest [-a|--affinity [PROC]] [-b|--breaktrace USEC] [-d|--distance DIST] [-D|--duration TIME][-i|--interval INTV] [-l|--loops LOOPS] [-p|--prio PRIO] [-S|--smp] [-t|--threads [NUM]] + .br + .SH "DESCRIPTION" + .LP +@@ -35,7 +35,7 @@ Set the number of loops. The default is 0 (endless). This option is useful for a + .B \-p, \-\-prio=PRIO + Set the priority of the process. + .TP +-.B \-s, \-\-smp ++.B \-S, \-\-smp + SMP testing: options -a -t and same priority + .TP + .B \-t, \-\-threads[=NUM] +-- +2.21.3 + diff --git a/SOURCES/rt-tests-queuelat-Assume-queuelat-is-in-the-path.patch b/SOURCES/rt-tests-queuelat-Assume-queuelat-is-in-the-path.patch deleted file mode 100644 index 1d5f082..0000000 --- a/SOURCES/rt-tests-queuelat-Assume-queuelat-is-in-the-path.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 9b3a1e9dcf01fbe8587a1684454a0568b7495504 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Wed, 15 Jan 2020 19:37:29 +0100 -Subject: [PATCH] rt-tests: queuelat: Assume queuelat is in the path - -The script determine_maximum_mpps.sh in queuelat hard codes the path to -queuelat. Assume that it is in the path. - -Signed-off-by: John Kacur ---- - src/queuelat/determine_maximum_mpps.sh | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/queuelat/determine_maximum_mpps.sh b/src/queuelat/determine_maximum_mpps.sh -index 52d54c0f9065..f6cf1dea27cf 100755 ---- a/src/queuelat/determine_maximum_mpps.sh -+++ b/src/queuelat/determine_maximum_mpps.sh -@@ -90,7 +90,7 @@ while [ $queuelat_failure == 1 ]; do - echo "$mpps Mpps" - - for i in `seq 1 10`; do -- $PREAMBLE ./queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - exceeded=`grep exceeded $OUTFILE` - - if [ ! -z "$exceeded" ]; then --- -2.20.1 - diff --git a/SOURCES/rt-tests-queuelat-Fix-some-warnings-in-determine_max.patch b/SOURCES/rt-tests-queuelat-Fix-some-warnings-in-determine_max.patch deleted file mode 100644 index 9a7f78a..0000000 --- a/SOURCES/rt-tests-queuelat-Fix-some-warnings-in-determine_max.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 6a9f1f6d5a19beed45dd81f74a41c18dcd3bd3dc Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Mon, 11 Nov 2019 22:20:23 +0100 -Subject: [PATCH] rt-tests: queuelat: Fix some warnings in - determine_maximum_mpps.sh - -Coverity advises to quote some values to prevent word splitting and to -export variables separately after declaraing them to avoid masking -errors. - -Fix these warnings - -Signed-off-by: John Kacur ---- - src/queuelat/determine_maximum_mpps.sh | 15 ++++++++------- - 1 file changed, 8 insertions(+), 7 deletions(-) - -diff --git a/src/queuelat/determine_maximum_mpps.sh b/src/queuelat/determine_maximum_mpps.sh -index cd45454720f7..3acd6ba2e362 100755 ---- a/src/queuelat/determine_maximum_mpps.sh -+++ b/src/queuelat/determine_maximum_mpps.sh -@@ -18,7 +18,7 @@ for mpps in `seq 3 3 50`; do - echo testing $mpps Mpps - - OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p $mpps -t 30 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - - exceeded=`grep exceeded $OUTFILE` - if [ ! -z "$exceeded" ]; then -@@ -34,7 +34,7 @@ for mpps in `seq $first_mpps -1 3`; do - echo testing $mpps Mpps - - OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p $mpps -t 30 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - - exceeded=`grep exceeded $OUTFILE` - if [ -z "$exceeded" ]; then -@@ -51,7 +51,7 @@ for mpps in `seq $second_mpps 0.3 $first_mpps`; do - echo testing $mpps Mpps - - OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p $mpps -t 30 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - - exceeded=`grep exceeded $OUTFILE` - if [ ! -z "$exceeded" ]; then -@@ -68,7 +68,7 @@ for mpps in `seq $third_mpps -0.1 3`; do - echo testing $mpps Mpps - - OUTFILE=`mktemp` -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p $mpps -t 30 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `sh get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - - exceeded=`grep exceeded $OUTFILE` - if [ -z "$exceeded" ]; then -@@ -87,13 +87,14 @@ while [ $queuelat_failure == 1 ]; do - echo "$mpps Mpps" - - for i in `seq 1 10`; do -- $PREAMBLE ./queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p $mpps -t 30 > $OUTFILE -+ $PREAMBLE ./queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 30 > $OUTFILE - exceeded=`grep exceeded $OUTFILE` - - if [ ! -z "$exceeded" ]; then - echo "mpps failure (run $i) $mpps" - export queuelat_failure=1 -- export mpps=`echo $mpps - 0.1 | bc` -+ mpps=`echo $mpps - 0.1 | bc` -+ export mpps - break - fi - echo "run $i success" -@@ -109,7 +110,7 @@ while [ $queuelat_failure == 1 ]; do - echo -n "Starting 10 minutes run with " - echo "$mpps Mpps" - -- $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p $mpps -t 600 > $OUTFILE -+ $PREAMBLE queuelat -m $MAXLAT -c $CYCLES_PER_PACKET -f `get_cpuinfo_mhz.sh` -p "$mpps" -t 600 > $OUTFILE - exceeded=`grep exceeded $OUTFILE` - - if [ ! -z "$exceeded" ]; then --- -2.20.1 - diff --git a/SOURCES/rt-tests-queuelat-Fix-storing-unsigned-long-long-int.patch b/SOURCES/rt-tests-queuelat-Fix-storing-unsigned-long-long-int.patch new file mode 100644 index 0000000..c3be1d2 --- /dev/null +++ b/SOURCES/rt-tests-queuelat-Fix-storing-unsigned-long-long-int.patch @@ -0,0 +1,111 @@ +From 41a3f9e53920d50b48c04593bfa3eb0e87fcf49f Mon Sep 17 00:00:00 2001 +From: John Kacur +Date: Tue, 12 May 2020 11:02:39 -0400 +Subject: [PATCH] rt-tests: queuelat: Fix storing unsigned long long in int + +queuelat can occassionally hang because of overflow mixing +unsigned long long and int + +Attaching to process 173912 +Reading symbols from /root/rt-tests/queuelat...done. +Reading symbols from /lib64/librt.so.1...Reading symbols from /usr/lib/debug/usr/lib64/librt-2.28.so.debug...done. +done. +Reading symbols from /lib64/libpthread.so.0...Reading symbols from /usr/lib/debug/usr/lib64/libpthread-2.28.so.debug...done. +done. +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib64/libthread_db.so.1". +Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libc-2.28.so.debug...done. +done. +Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/usr/lib64/ld-2.28.so.debug...done. +done. +__memmove_avx_unaligned_erms () + at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:254 +254 rep movsb +(gdb) c +Continuing. + +Program received signal SIGSEGV, Segmentation fault. +0x0000000000400c02 in account (val=18446744071562067968) + at src/queuelat/queuelat.c:93 +93 buckets[bucket_nr]++; +(gdb) bt full + at src/queuelat/queuelat.c:93 + bucket_nr = -193273529 + a = 825932047802952 + b = 825925371232340 + dest = 0xf322b0 + src = 0xf4e3f0 + i = 45749 + delta = -2147483648 + loops = 50000 + time = 6500 + bucket_nr = 65 + n = 115000 + delta = 3500 + at src/queuelat/queuelat.c:671 + tsc_freq_mhz = 2398.5039999999999 + max_queue_len_f = 159.900284 + mvalue = 0x7ffc99d3021c "20000" + cvalue = 0x7ffc99d30225 "300" + pvalue = 0x7ffc99d30238 "6.1" + fvalue = 0x7ffc99d3022c "2398.504" + tvalue = 0x7ffc99d3023f "30" + qvalue = 0x0 + index = 0 + c = -1 + +Fix the above by declaring delta as an unsigned long long + +Signed-off-by: John Kacur +--- + src/queuelat/queuelat.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/src/queuelat/queuelat.c b/src/queuelat/queuelat.c +index 7e5e35768a8b..22b68a84d6ae 100644 +--- a/src/queuelat/queuelat.c ++++ b/src/queuelat/queuelat.c +@@ -354,9 +354,9 @@ static void trace_write(char *buf, int len) + + static void run_n(int n) + { +- u64 a, b; ++ u64 a, b, delta; + void *dest, *src; +- int i, delta, loops = 50000; ++ int i, loops = 50000; + + init_buckets(); + +@@ -445,9 +445,8 @@ static void print_exit_info(void) + + void main_loop(void) + { +- u64 a, b; ++ u64 a, b, delta; + void *dest, *src; +- int delta; + int queue_size = 0; + + trace_open(); +@@ -500,7 +499,7 @@ void main_loop(void) + continue; + + ret = sprintf(buf, "memmove block queue_size=%d queue_dec=%d" +- " queue_inc=%d delta=%d ns\n", queue_size, ++ " queue_inc=%d delta=%llu ns\n", queue_size, + nr_packets_drain_per_block, + nr_packets_fill, delta); + trace_write(buf, ret); +@@ -536,7 +535,7 @@ static void install_signals(void) + + int calculate_nr_packets_drain_per_block(void) + { +- int maxcount; ++ unsigned long long maxcount; + int i, time; + int found = 0; + int bucket_nr = find_highest_count_bucket(); +-- +2.21.3 + diff --git a/SOURCES/rt-tests-queuelat-Fixes-to-man-page-and-display_help.patch b/SOURCES/rt-tests-queuelat-Fixes-to-man-page-and-display_help.patch deleted file mode 100644 index 0a5e2de..0000000 --- a/SOURCES/rt-tests-queuelat-Fixes-to-man-page-and-display_help.patch +++ /dev/null @@ -1,80 +0,0 @@ -From d823298c8b09b9cc406b272ea91cc2b5d697cc08 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 23 Jan 2020 19:17:21 +0100 -Subject: [PATCH 7/8] rt-tests: queuelat: Fixes to man page and display_help - -- Make sure that help is displayed and not just the message -"Unknown option" when the options are incorrect. -- Add -q to the man page and to the print_help() - -Signed-off-by: John Kacur ---- - src/queuelat/queuelat.8 | 4 +++- - src/queuelat/queuelat.c | 22 +++++++++++++--------- - 2 files changed, 16 insertions(+), 10 deletions(-) - -diff --git a/src/queuelat/queuelat.8 b/src/queuelat/queuelat.8 -index d68beb98bff7..f67a0bb7556e 100644 ---- a/src/queuelat/queuelat.8 -+++ b/src/queuelat/queuelat.8 -@@ -52,7 +52,9 @@ TSC frequency in MHz. - .TP - .B \-t timeout - Timeout in seconds to quit the program. -- -+.TP -+.B \-q min_queue_len_to_print_trace -+Minimum queue length to print in the trace - - .SH AUTHOR - queuelat was written by Marcelo Tosatti -diff --git a/src/queuelat/queuelat.c b/src/queuelat/queuelat.c -index 98346f346f82..7e5e35768a8b 100644 ---- a/src/queuelat/queuelat.c -+++ b/src/queuelat/queuelat.c -@@ -571,6 +571,7 @@ void print_help(void) - printf("-p million-packet-per-sec (million packets per second) (float)\n"); - printf("-f tsc-freq-mhz (TSC frequency in MHz) (float)\n"); - printf("-t timeout (timeout, in seconds) (int)\n"); -+ printf("-q min_queue_len_to_print_trace (int)\n"); - } - - int main(int argc, char **argv) -@@ -616,22 +617,25 @@ int main(int argc, char **argv) - return 0; - case '?': - if (optopt == 'm' || optopt == 'c' || optopt == 'p' || -- optopt == 'f' || optopt == 't' || optopt == 'q') -+ optopt == 'f' || optopt == 't' || optopt == 'q') { - printf ("Option -%c requires an argument.\n", optopt); -- else if (isprint (optopt)) -+ } else if (isprint (optopt)) { - printf ("Unknown option `-%c'.\n", optopt); -- else -- printf ( "Unknown option character `\\x%x'.\n", -- --optopt); -+ print_help(); -+ return 1; -+ } else { -+ printf ( "Unknown option character `\\x%x'.\n", optopt); -+ print_help(); - return 1; -- default: -- abort (); -+ } -+ break; -+ default: -+ abort (); - } - - if (mvalue == NULL || cvalue == NULL || pvalue == NULL || - fvalue == NULL) { -- printf("options -m, -c, -p and -f required.\n"); -+ printf("options -m, -c, -p and -f are required.\n"); - printf("usage: %s -m maxlatency -c cycles_per_packet -p mpps(million-packet-per-sec) -f tsc_freq_mhz [-t timeout (in secs)] [-q min_queue_len_to_print_trace]\n", argv[0]); - return 1; - } --- -2.20.1 - diff --git a/SOURCES/rt-tests-queuelat-get_cpuinfo_mhz.sh-highest-value.patch b/SOURCES/rt-tests-queuelat-get_cpuinfo_mhz.sh-highest-value.patch deleted file mode 100644 index 9164ee2..0000000 --- a/SOURCES/rt-tests-queuelat-get_cpuinfo_mhz.sh-highest-value.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 99f69126221ad8e3abd723576e638e270ab9deb3 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Fri, 17 Jan 2020 18:19:19 +0100 -Subject: [PATCH 5/5] rt-tests: queuelat: get_cpuinfo_mhz.sh highest value - -get_cpuinfo_mhz.sh greps for the Mhz from the /proc/cpuinfo file -It assumes that for multiple cpus the value will be the same, and -intends to return one value using uniq as a filter. - -Typically the reported Mhz values can all be slightly different though -It would probably be good enough to simply take the first match as a -heuristic, but to be safe, take the highest number. - -Also replace the legacy backticks with the modern $(...) construct, and -quote the $mhz variable. - -Signed-off-by: John Kacur ---- - src/queuelat/get_cpuinfo_mhz.sh | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/queuelat/get_cpuinfo_mhz.sh b/src/queuelat/get_cpuinfo_mhz.sh -index eafdd9577424..14a2c12c478f 100755 ---- a/src/queuelat/get_cpuinfo_mhz.sh -+++ b/src/queuelat/get_cpuinfo_mhz.sh -@@ -3,6 +3,5 @@ - # SPDX-License-Identifier: GPL-2.0-or-later - # Copyright (C) 2018 Marcelo Tosatti - --mhz=`cat /proc/cpuinfo | grep "cpu MHz" | uniq | cut -f 3 -d " "` --echo $mhz -- -+mhz=$(grep "cpu MHz" /proc/cpuinfo | cut -f 3 -d " " | sort -rn | head -n1) -+echo "$mhz" --- -2.20.1 - diff --git a/SOURCES/rt-tests-ssdd-Add-short-and-long-functions-and-help.patch b/SOURCES/rt-tests-ssdd-Add-short-and-long-functions-and-help.patch deleted file mode 100644 index 0fc561c..0000000 --- a/SOURCES/rt-tests-ssdd-Add-short-and-long-functions-and-help.patch +++ /dev/null @@ -1,123 +0,0 @@ -From a6f1ab221f80e2f2e1d1f184710ab65c35ed5b36 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Tue, 12 Nov 2019 01:21:09 +0100 -Subject: [PATCH] rt-tests: ssdd: Add short and long functions as well as help - -Add short and long functions as well as help to make ssdd consistent -with the rest of the test suite. Add a help function as well - -Signed-off-by: John Kacur ---- - src/ssdd/ssdd.8 | 10 +++++++--- - src/ssdd/ssdd.c | 45 +++++++++++++++++++++++++++++++++++++++------ - 2 files changed, 46 insertions(+), 9 deletions(-) - -diff --git a/src/ssdd/ssdd.8 b/src/ssdd/ssdd.8 -index 44638489f0d1..99f30145d079 100644 ---- a/src/ssdd/ssdd.8 -+++ b/src/ssdd/ssdd.8 -@@ -3,7 +3,7 @@ - ssdd \- have a tracer do a bunch of PTRACE_SINGLESTEPs - .SH SYNOPSIS - .B ssdd --.RI "[nforks] [niters]" -+.RI "" - .SH DESCRIPTION - Have a tracer do a bunch of PTRACE_SINGLESTEPs against - a tracee as fast as possible. Create several of these -@@ -12,15 +12,19 @@ interfere with each other. - The tracer waits on each PTRACE_SINGLESTEP with a waitpid(2) - and checks that waitpid's return values for correctness. - .SH OPTIONS --.B nforks -+.B \-f, \-\-forks - number of tracer/tracee pairs to fork off. - Default is 10. - .br - .TP --.B niters -+.B \-i, \-\-iters - number of PTRACE_SINGLESTEP iterations to - do before declaring success, for each tracer/ - tracee pair set up. Default is 10,000. -+.br -+.TP -+.B \-h, \-\-help -+Display usage - - .SH AUTHOR - ssdd was written by Joe Korty -diff --git a/src/ssdd/ssdd.c b/src/ssdd/ssdd.c -index 2c3a779be9f1..080ed17107a8 100644 ---- a/src/ssdd/ssdd.c -+++ b/src/ssdd/ssdd.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -65,6 +66,17 @@ static const char *get_state_name(int state) - - static int got_sigchld; - -+enum option_value { OPT_NFORKS=1, OPT_NITERS, OPT_HELP }; -+ -+static void usage() -+{ -+ printf("ssdd \n"); -+ printf("\t-f --forks=\n"); -+ printf("\t-i --iters=\n"); -+ printf("\t-h --help\n"); -+ exit(0); -+} -+ - static int do_wait(pid_t *wait_pid, int *ret_sig) - { - int status, child_status; -@@ -276,13 +288,34 @@ int main(int argc, char **argv) - - setbuf(stdout, NULL); - -- argc--, argv++; -- if (argc) { -- nforks = atoi(*argv); -- argc--, argv++; -- if (argc) -- nsteps = atoi(*argv); -+ for (;;) { -+ int option_index = 0; -+ -+ static struct option long_options[] = { -+ {"forks", required_argument, NULL, OPT_NFORKS}, -+ {"iters", required_argument, NULL, OPT_NITERS}, -+ {"help", no_argument, NULL, OPT_HELP}, -+ {NULL, 0, NULL, 0}, -+ }; -+ int c = getopt_long(argc, argv, "f:i:h", long_options, &option_index); -+ if (c == -1) -+ break; -+ switch(c) { -+ case 'f': -+ case OPT_NFORKS: -+ nforks = atoi(optarg); -+ break; -+ case 'i': -+ case OPT_NITERS: -+ nsteps = atoi(optarg); -+ break; -+ case 'h': -+ case OPT_HELP: -+ usage(); -+ break; -+ } - } -+ - printf("#main : %d\n", getpid()); - printf("#forks: %d\n", nforks); - printf("#steps: %d\n", nsteps); --- -2.20.1 - diff --git a/SOURCES/rt-tests-svsematest-Display-help-with-an-error-msg.patch b/SOURCES/rt-tests-svsematest-Display-help-with-an-error-msg.patch deleted file mode 100644 index 4fa8492..0000000 --- a/SOURCES/rt-tests-svsematest-Display-help-with-an-error-msg.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 7437ee24d0638a27a5d5ca84389dafe320a7dc5b Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Thu, 23 Jan 2020 19:59:26 +0100 -Subject: [PATCH 8/8] rt-tests: svsematest: Display help with an error message - for -h - -Display help without an error message if the user uses the -h option - -Signed-off-by: John Kacur ---- - src/svsematest/svsematest.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c -index 7c15393fe1be..023a303fd7df 100644 ---- a/src/svsematest/svsematest.c -+++ b/src/svsematest/svsematest.c -@@ -281,7 +281,7 @@ static void process_options (int argc, char *argv[]) - {"help", no_argument, NULL, '?'}, - {NULL, 0, NULL, 0} - }; -- int c = getopt_long (argc, argv, "a::b:d:f::i:l:D:p:St::", -+ int c = getopt_long (argc, argv, "a::b:d:f::i:l:D:p:St::h", - long_options, &option_index); - if (c == -1) - break; -@@ -335,6 +335,7 @@ static void process_options (int argc, char *argv[]) - else - num_threads = max_cpus; - break; -+ case 'h': error = 1; break; - case '?': error = 1; break; - } - } --- -2.20.1 - diff --git a/SOURCES/sigwaittest-Increase-buffer-to-avoid-overflow.patch b/SOURCES/sigwaittest-Increase-buffer-to-avoid-overflow.patch deleted file mode 100644 index a91e436..0000000 --- a/SOURCES/sigwaittest-Increase-buffer-to-avoid-overflow.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 2d101866365ac75e29cfc9800ca569802fee64c7 Mon Sep 17 00:00:00 2001 -From: Daniel Wagner -Date: Mon, 19 Aug 2019 08:43:02 +0200 -Subject: [PATCH 02/10] sigwaittest: Increase buffer to avoid overflow -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Increase the size of the char buffer. gcc 9.1.1 reports: - -src/sigwaittest/sigwaittest.c:494:5: note: ‘sprintf’ output between 5 and 14 bytes into a destination of size 8 - 494 | sprintf(f_opt, "-fr%d", i); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~ -src/sigwaittest/sigwaittest.c:522:24: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 5 [-Wformat-overflow=] - 522 | sprintf(f_opt, "-fs%d", i); - | ^~ - -Signed-off-by: Daniel Wagner -Signed-off-by: John Kacur ---- - src/sigwaittest/sigwaittest.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/sigwaittest/sigwaittest.c b/src/sigwaittest/sigwaittest.c -index 59f28a5babcb..2d0c04132fa7 100644 ---- a/src/sigwaittest/sigwaittest.c -+++ b/src/sigwaittest/sigwaittest.c -@@ -352,7 +352,7 @@ int main(int argc, char *argv[]) - struct params *sender = NULL; - sigset_t sigset; - void *param = NULL; -- char f_opt[8]; -+ char f_opt[14]; - struct timespec launchdelay, maindelay; - - process_options(argc, argv); --- -2.20.1 - diff --git a/SOURCES/svsematest-Add-S-smp-option-to-manpage.patch b/SOURCES/svsematest-Add-S-smp-option-to-manpage.patch deleted file mode 100644 index 40817cc..0000000 --- a/SOURCES/svsematest-Add-S-smp-option-to-manpage.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b8a602c2b94a62811b73ee0249526ba6c3ce4437 Mon Sep 17 00:00:00 2001 -From: John Kacur -Date: Fri, 22 Nov 2019 14:59:05 +0100 -Subject: [PATCH] svsematest: Add -S, --smp option to manpage - -The -S, or --smp option is in the help but missing from the manpage. - -We should really revisit these tests as these options have changed a bit -in cyclictest and they are all modeled after cyclictest. - -Signed-off-by: John Kacur ---- - src/svsematest/svsematest.8 | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/svsematest/svsematest.8 b/src/svsematest/svsematest.8 -index f67ab4c669d3..98322c105803 100644 ---- a/src/svsematest/svsematest.8 -+++ b/src/svsematest/svsematest.8 -@@ -38,6 +38,9 @@ Set the number of loops. The default is 0 (endless). This option is useful for a - .B \-p, \-\-prio=PRIO - Set the priority of the process. - .TP -+.B \-S, \-\-smp -+SMP testing: options -a -t and same priority of all threads -+.TP - .B \-t, \-\-threads[=NUM] - Set the number of test threads (default is 1, if this option is not given). If NUM is specified, create NUM test threads. If NUM is not specified, NUM is set to the number of available CPUs. - .SH "EXAMPLES" --- -2.20.1 - diff --git a/SOURCES/svsematest-Increase-buffer-to-avoid-overflow.patch b/SOURCES/svsematest-Increase-buffer-to-avoid-overflow.patch deleted file mode 100644 index 93dee7d..0000000 --- a/SOURCES/svsematest-Increase-buffer-to-avoid-overflow.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 06519443224b7da5b336040f07bff8f929148426 Mon Sep 17 00:00:00 2001 -From: Daniel Wagner -Date: Mon, 19 Aug 2019 08:43:03 +0200 -Subject: [PATCH 03/10] svsematest: Increase buffer to avoid overflow -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Increase the size of the char buffer. gcc 9.1.1 reports: - -rc/svsematest/svsematest.c:578:24: warning: ‘%d’ directive writing between 1 and 10 bytes into a region of size 5 [-Wformat-overflow=] - 578 | sprintf(f_opt, "-fr%d", i); - | ^~ -src/svsematest/svsematest.c:606:5: note: ‘sprintf’ output between 5 and 14 bytes into a destination of size 8 - 606 | sprintf(f_opt, "-fs%d", i); - | ^~~~~~~~~~~~~~~~~~~~~~~~~~ - -Signed-off-by: Daniel Wagner -Signed-off-by: John Kacur ---- - src/svsematest/svsematest.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/svsematest/svsematest.c b/src/svsematest/svsematest.c -index 8f880786ec0f..15e36af76288 100644 ---- a/src/svsematest/svsematest.c -+++ b/src/svsematest/svsematest.c -@@ -401,7 +401,7 @@ int main(int argc, char *argv[]) - struct params *sender = NULL; - sigset_t sigset; - void *param = NULL; -- char f_opt[8]; -+ char f_opt[14]; - struct timespec launchdelay, maindelay; - - myfile = getenv("_"); --- -2.20.1 - diff --git a/SPECS/rt-tests.spec b/SPECS/rt-tests.spec index 612ed74..c5c45e3 100644 --- a/SPECS/rt-tests.spec +++ b/SPECS/rt-tests.spec @@ -5,47 +5,34 @@ Name: rt-tests # BuildRequires: numactl-devel # Numa argument to make: NUMA=1 # -Version: 1.5 -Release: 18%{?dist} +Version: 1.8 +Release: 11%{?dist} License: GPLv2 Group: Development/Tools URL: git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git Source0: https://www.kernel.org/pub/linux/utils/rt-tests/%{name}-%{version}.tar.xz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root -Obsoletes: cyclictest signaltest pi_tests ExclusiveArch: x86_64 BuildRequires: numactl-devel python3-devel %{?__python3:Requires: %{__python3}} Requires: bash bc #Patches -Patch1: rt-tests-cyclictest-Make-tracemark-work-correctly-ag.patch -Patch2: rt-tests-cyclictest.8-Remove-invalid-tracing-options.patch -Patch3: pmqtest-Increase-buffer-to-avoid-overflow.patch -Patch4: sigwaittest-Increase-buffer-to-avoid-overflow.patch -Patch5: svsematest-Increase-buffer-to-avoid-overflow.patch -Patch6: deadline_test-Increase-buffer-to-avoid-overflow.patch -Patch7: rt-tests-Set-affinity-before-applying-numa.patch -Patch8: rt-tests-cyclictest-Don-t-allow-OPT_SYSTEM-with-OPT_POSIX_TIMERS.patch -Patch9: rt-tests-cyclictest-Fix-warning-cpu-may-be-used-uninitialized.patch -Patch10: rt-tests-cyclictest-Assume-libnuma-version-2-by-defa.patch -Patch11: rt-tests-cyclictest-Just-use-LIBNUMA_API_VERSION-2.patch -Patch12: rt-tests-queuelat-Fix-some-warnings-in-determine_max.patch -Patch13: rt-tests-ssdd-Add-short-and-long-functions-and-help.patch -Patch14: rt-tests-cyclictest-Get-a-snapshot-of-cyclictest.patch -Patch15: rt-tests-Add-SPDX-tags.patch -Patch16: rt-tests-queuelat-Assume-queuelat-is-in-the-path.patch -Patch17: rt-tests-determine_maximum_mpps.sh-Fix-quoting-and-o.patch -Patch18: rt-tests-queuelat-get_cpuinfo_mhz.sh-highest-value.patch -Patch19: rt-tests-cyclicdeadline-Add-a-simple-manpage.patch -Patch20: cyclictest-Sync-manpage-with-the-help-option.patch -Patch21: pi_stress-Sync-man-page-with-help.patch -Patch22: rt-tests-pi_stress-Add-short-options-to-usage-msg.patch -Patch23: svsematest-Add-S-smp-option-to-manpage.patch -Patch24: rt-tests-ptsematest-Update-man-page-and-add-h-option.patch -Patch25: rt-tests-queuelat-Fixes-to-man-page-and-display_help.patch -Patch26: rt-tests-svsematest-Display-help-with-an-error-msg.patch +Patch1: cyclictest-Fix-setaffinity-error-on-large-NUMA-machines.patch +Patch2: rt-tests-queuelat-Fix-storing-unsigned-long-long-int.patch +Patch3: rt-tests-cyclictest-remove-the-debug-log-pid-xxx-in-.patch +Patch4: rt-tests-improvements-to-the-python-style-in-get_cyc.patch +Patch5: rt-tests-pi_stress.8-Remove-unused-t-n-from-the-manp.patch +Patch6: rt-tests-ptsematest.8-Update-the-ptsematest-man-page.patch +Patch7: rt-tests-Add-a-man-page-for-get_cyclictest_snapshot.patch +Patch8: rt-tests-Tweak-the-cyclictest-man-page.patch +Patch9: rt-tests-get_cyclictest_snapshot-Warn-if-no-cyclicte.patch +Patch10: rt-tests-Install-new-man-page-get_cyclictest_snapshot.patch +Patch11: pi_stress-limit-the-number-of-inversion-groups-to-th.patch +Patch12: rt-tests-cyclictest-Move-ftrace-helpers-into-rt-util.patch +Patch13: rt-tests-oslat-Init-commit.patch +Patch14: rt-tests-oslat-Proper-reformat-of-code.patch %description rt-tests is a set of programs that test and measure various components of @@ -68,18 +55,6 @@ latency. It also tests the functioning of priority-inheritance mutexes. %patch12 -p1 %patch13 -p1 %patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 %build make NUMA=1 HAVE_PARSE_CPUSTRING_ALL=1 @@ -112,8 +87,12 @@ rm -rf $RPM_BUILD_ROOT /usr/bin/deadline_test /usr/bin/queuelat /usr/bin/ssdd +/usr/bin/oslat /usr/bin/determine_maximum_mpps.sh /usr/bin/get_cpuinfo_mhz.sh +/usr/bin/get_cyclictest_snapshot +%{python3_sitelib}/get_cyclictest_snapshot.py* +%{python3_sitelib}/__pycache__/get_cyclictest_snapshot* %doc /usr/share/man/man8/cyclictest.8.gz /usr/share/man/man8/hackbench.8.gz @@ -130,8 +109,55 @@ rm -rf $RPM_BUILD_ROOT /usr/share/man/man8/deadline_test.8.gz /usr/share/man/man8/cyclicdeadline.8.gz /usr/share/man/man8/ssdd.8.gz +/usr/share/man/man8/oslat.8.gz +/usr/share/man/man8/get_cyclictest_snapshot.8.gz %changelog +* Thu Aug 20 2020 John Kacur - 1.8.11 +- Add SPDX license to oslat, and reformat source code to match suite +Resolves: rhbz#1870666 + +* Wed Aug 19 2020 John Kacur - 1.8.10 +- Remove undated Obsoletes from the specfile +Resolves: rhbz#1870212 + +* Wed Aug 19 2020 John Kacur - 1.8-9 +- Add the oslat program to the rt-tests suite +Resolves: rhbz#1869882 + +* Wed Jul 22 2020 John Kacur - 1.8-8 +- Change the conversion format to %ld for the num_processors in pi_stress +Resolves: rhbz#1859397 + +* Wed Jul 22 2020 John Kacur - 1.8-7 +- Limit the number of inversion groups in pi_stress +Resolves: rhbz#1859397 + +* Mon Jul 06 2020 John Kacur - 1.8-6 +- Install new man page get_cyclictest_snapshot +Resolves: rhbz#1826777 + +* Mon Jul 06 2020 John Kacur - 1.8-5 +- get_cyclictest_snapshot: print a warning message if there are no + running cyclictest instances +Resolves: rhbz#1826783 + +* Mon Jul 06 2020 John Kacur - 1.8-4 +- Add a get_cyclictest_snapshot man page and various small fixes +Resolves: rhbz#1826777 + +* Tue May 12 2020 John Kacur - 1.8-3 +- Fix integer overflow in queuelat +Resolves: rhbz#1803862 + +* Mon May 04 2020 John Kacur - 1.8-2 +- Fix setaffinity error on large numa machines +Resolves: rhbz#1831269 + +* Mon Apr 20 2020 John Kacur - 1.8-1 +- Update to upstream rt-tests-1.8 +Resolves: rhbz#1816370 + * Thu Jan 23 2020 John Kacur - 1.5-18 - Add a man page for cyclicdeadline - Sync cyclictest man page with the help option