* [PATCH 0/5] cyclictest: Little tweaks here and there
@ 2026-08-26 13:21 Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows' Sebastian Andrzej Siewior
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior
I was debugging something and was wondering about the high latencies
that did happen from time to time. Turns out it is due to the -M switch
if multiple threads try to wake the printing thread at the same time.
#2 is the actual fix, #5 was debug code which turned out to be useful.
Sebastian Andrzej Siewior (5):
rt-tests: cyclicdeadline: Remove unused `alloverflows'
cyclictest: Acquire a lock before invoking pthread_cond_signal()
cyclictest: Make break_thread_id_lock a PI lock
cyclictest: Make trigger_lock a PI lock
cyclictest: Add a timestamp of the last update
src/cyclictest/cyclictest.c | 38 ++++++++++++++++++++++++++---
src/sched_deadline/cyclicdeadline.c | 4 +--
2 files changed, 35 insertions(+), 7 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows'
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
@ 2026-08-26 13:21 ` Sebastian Andrzej Siewior
2026-08-31 16:40 ` John Kacur
2026-08-26 13:21 ` [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal() Sebastian Andrzej Siewior
` (3 subsequent siblings)
4 siblings, 1 reply; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior, Crystal Wood
alloverflows has been added in commit 9894227feebf2 ("rt-tests:
cyclicdeadline: Add histogram support") and not used ever since.
The compiler complains in a "set but not used" way.
Remove unused `alloverflows' variable.
Cc: Crystal Wood <crwood@redhat.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
src/sched_deadline/cyclicdeadline.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/sched_deadline/cyclicdeadline.c b/src/sched_deadline/cyclicdeadline.c
index 0c6c969760101..f97344035ca3c 100644
--- a/src/sched_deadline/cyclicdeadline.c
+++ b/src/sched_deadline/cyclicdeadline.c
@@ -633,7 +633,7 @@ static u64 get_time_us(void)
static void print_hist(FILE *fp, struct sched_data *sd, int nthreads)
{
int i;
- unsigned long maxmax, alloverflows;
+ unsigned long maxmax;
fprintf(fp, "# Histogram\n");
for (i = 0; i < histogram; i++) {
@@ -661,10 +661,8 @@ static void print_hist(FILE *fp, struct sched_data *sd, int nthreads)
}
fprintf(fp, "\n");
fprintf(fp, "# Histogram Overflows:");
- alloverflows = 0;
for (i = 0; i < nthreads; i++) {
fprintf(fp, " %05lu", sd[i].stat.hist->oflow_count);
- alloverflows += sd[i].stat.hist->oflow_count;
}
fprintf(fp, "\n");
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal()
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows' Sebastian Andrzej Siewior
@ 2026-08-26 13:21 ` Sebastian Andrzej Siewior
2026-08-31 16:41 ` John Kacur
2026-09-01 8:19 ` D, Suneeth
2026-08-26 13:21 ` [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock Sebastian Andrzej Siewior
` (2 subsequent siblings)
4 siblings, 2 replies; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior
With the -M option the output is updated once there is a new max value.
On system with many threads (say 64) and aligned wake up (all threads
wake at the same time) it is possible that all of them have a new
maximal latency and all of them invoke pthread_cond_signal()
simultaneously. They all will block in the kernel in the futex syscall
on the same lock. And each of them will wake the printing thread one by
one. This is not *that* visible with just a few threads and a quick
CPU. But with many CPUs on a slower system this gets worse.
Acquire refresh_on_max_lock with a trylock before invoking
pthread_cond_signal(). This ensures that only one thread will send a
waking request at a time. Should the lock be contained then delay the
signalling until the next iteration.
Make refresh_on_max_lock a PI lock. This shouldn't make much of a
difference here given the try_lock usage in the RT thread but the
unconditional locking will lead to complains by the RV-monitor.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
src/cyclictest/cyclictest.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 960c905606684..29ddf2d98bbe1 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -198,7 +198,7 @@ static int smi = 0;
#endif
static pthread_cond_t refresh_on_max_cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t refresh_on_max_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t refresh_on_max_lock;
static pthread_mutex_t break_thread_id_lock = PTHREAD_MUTEX_INITIALIZER;
static pid_t break_thread_id = 0;
@@ -640,6 +640,7 @@ static void *timerthread(void *param)
struct itimerval itimer;
struct itimerspec tspec;
struct thread_stat *stat = par->stats;
+ bool need_refresh_max = false;
int stopped = 0;
cpu_set_t mask;
pthread_t thread;
@@ -834,7 +835,14 @@ static void *timerthread(void *param)
if (diff > stat->max) {
stat->max = diff;
if (refresh_on_max)
+ need_refresh_max = true;
+ }
+ if (need_refresh_max) {
+ if (!pthread_mutex_trylock(&refresh_on_max_lock)) {
pthread_cond_signal(&refresh_on_max_cond);
+ pthread_mutex_unlock(&refresh_on_max_lock);
+ need_refresh_max = false;
+ }
}
stat->avg += (double) diff;
@@ -1910,6 +1918,7 @@ static void set_main_thread_affinity(struct bitmask *cpumask)
int main(int argc, char **argv)
{
+ pthread_mutexattr_t mattr;
sigset_t sigset;
int signum = SIGALRM;
int mode;
@@ -1946,6 +1955,10 @@ int main(int argc, char **argv)
}
}
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
+ pthread_mutex_init(&refresh_on_max_lock, &mattr);
+
/* lock all memory (prevent swapping) */
if (lockall)
if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows' Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal() Sebastian Andrzej Siewior
@ 2026-08-26 13:21 ` Sebastian Andrzej Siewior
2026-08-31 16:42 ` John Kacur
2026-08-26 13:21 ` [PATCH 4/5] cyclictest: Make trigger_lock " Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 5/5] cyclictest: Add a timestamp of the last update Sebastian Andrzej Siewior
4 siblings, 1 reply; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior
break_thread_id_lock is acquired at the end once the application is
about to terminate and the lock ensures that only the first thread
writes/ updates the termination reason.
Given its usage there is no requirement to have it as PI lock but having
it as PI will keep the RV-monitor quiet so let's do it.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
src/cyclictest/cyclictest.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 29ddf2d98bbe1..257b6f1b70cf6 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -200,7 +200,7 @@ static int smi = 0;
static pthread_cond_t refresh_on_max_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t refresh_on_max_lock;
-static pthread_mutex_t break_thread_id_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t break_thread_id_lock;
static pid_t break_thread_id = 0;
static uint64_t break_thread_value = 0;
@@ -1958,6 +1958,7 @@ int main(int argc, char **argv)
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutex_init(&refresh_on_max_lock, &mattr);
+ pthread_mutex_init(&break_thread_id_lock, &mattr);
/* lock all memory (prevent swapping) */
if (lockall)
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 4/5] cyclictest: Make trigger_lock a PI lock
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
` (2 preceding siblings ...)
2026-08-26 13:21 ` [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock Sebastian Andrzej Siewior
@ 2026-08-26 13:21 ` Sebastian Andrzej Siewior
2026-08-31 16:43 ` John Kacur
2026-08-26 13:21 ` [PATCH 5/5] cyclictest: Add a timestamp of the last update Sebastian Andrzej Siewior
4 siblings, 1 reply; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior
trigger_lock is acquired by the timer thread. Given its usage it
probably makes no difference if it is PI or not but having it as PI will
keep the RV-monitor quiet so let's do it.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
src/cyclictest/cyclictest.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 257b6f1b70cf6..1cad1bf6b929e 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -147,7 +147,7 @@ struct thread_stat {
unsigned long smi_count;
};
-static pthread_mutex_t trigger_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t trigger_lock;
static int trigger = 0; /* Record spikes > trigger, 0 means don't record */
static int trigger_list_size = 1024; /* Number of list nodes */
@@ -1959,6 +1959,7 @@ int main(int argc, char **argv)
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
pthread_mutex_init(&refresh_on_max_lock, &mattr);
pthread_mutex_init(&break_thread_id_lock, &mattr);
+ pthread_mutex_init(&trigger_lock, &mattr);
/* lock all memory (prevent swapping) */
if (lockall)
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 5/5] cyclictest: Add a timestamp of the last update
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
` (3 preceding siblings ...)
2026-08-26 13:21 ` [PATCH 4/5] cyclictest: Make trigger_lock " Sebastian Andrzej Siewior
@ 2026-08-26 13:21 ` Sebastian Andrzej Siewior
2026-08-28 14:26 ` John Kacur
4 siblings, 1 reply; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-26 13:21 UTC (permalink / raw)
To: linux-rt-users; +Cc: John Kacur, Sebastian Andrzej Siewior
Add a timestamp once the the MAX value is updated. This is useful to
figure out when a certain value was updated and if an update occurred on
multiple CPUs at same. The output is seconds accurate, the ns are
stripped for now.
I'm limiting this to the the -M switch, which I am using, but there
should be nothing wrong with using it unconditionally.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
src/cyclictest/cyclictest.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 1cad1bf6b929e..1c14d13b7cd80 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -145,6 +145,7 @@ struct thread_stat {
long redmax;
long cycleofmax;
unsigned long smi_count;
+ struct timespec max_update_ts;
};
static pthread_mutex_t trigger_lock;
@@ -834,8 +835,10 @@ static void *timerthread(void *param)
stat->min = diff;
if (diff > stat->max) {
stat->max = diff;
- if (refresh_on_max)
+ if (refresh_on_max) {
need_refresh_max = true;
+ clock_gettime(CLOCK_REALTIME, &stat->max_update_ts);
+ }
}
if (need_refresh_max) {
if (!pthread_mutex_trylock(&refresh_on_max_lock)) {
@@ -1599,6 +1602,18 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
stat->act, stat->cycles ?
(long)(stat->avg/stat->cycles) : 0, stat->max);
+ if (refresh_on_max) {
+ char ts_str[64];
+ struct tm tm;
+ time_t ts;
+
+ ts = stat->max_update_ts.tv_sec;
+ localtime_r(&ts, &tm);
+ /* RFC 2822-compliant date format */
+ strftime(ts_str, sizeof(ts_str), "%a, %d %b %Y %T %z", &tm);
+ fprintf(fp, " %s", ts_str);
+ }
+
if (smi)
fprintf(fp, " SMI:%8ld", stat->smi_count);
--
2.55.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 5/5] cyclictest: Add a timestamp of the last update
2026-08-26 13:21 ` [PATCH 5/5] cyclictest: Add a timestamp of the last update Sebastian Andrzej Siewior
@ 2026-08-28 14:26 ` John Kacur
2026-08-28 16:10 ` Sebastian Andrzej Siewior
0 siblings, 1 reply; 15+ messages in thread
From: John Kacur @ 2026-08-28 14:26 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linux-rt-users, John Kacur
On Wed, 26 Aug 2026, Sebastian Andrzej Siewior wrote:
> Add a timestamp once the the MAX value is updated. This is useful to
> figure out when a certain value was updated and if an update occurred on
> multiple CPUs at same. The output is seconds accurate, the ns are
> stripped for now.
>
> I'm limiting this to the the -M switch, which I am using, but there
> should be nothing wrong with using it unconditionally.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> src/cyclictest/cyclictest.c | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
> index 1cad1bf6b929e..1c14d13b7cd80 100644
> --- a/src/cyclictest/cyclictest.c
> +++ b/src/cyclictest/cyclictest.c
> @@ -145,6 +145,7 @@ struct thread_stat {
> long redmax;
> long cycleofmax;
> unsigned long smi_count;
> + struct timespec max_update_ts;
> };
>
> static pthread_mutex_t trigger_lock;
> @@ -834,8 +835,10 @@ static void *timerthread(void *param)
> stat->min = diff;
> if (diff > stat->max) {
> stat->max = diff;
> - if (refresh_on_max)
> + if (refresh_on_max) {
> need_refresh_max = true;
> + clock_gettime(CLOCK_REALTIME, &stat->max_update_ts);
> + }
> }
> if (need_refresh_max) {
> if (!pthread_mutex_trylock(&refresh_on_max_lock)) {
> @@ -1599,6 +1602,18 @@ static void print_stat(FILE *fp, struct thread_param *par, int index, int verbos
> stat->act, stat->cycles ?
> (long)(stat->avg/stat->cycles) : 0, stat->max);
>
> + if (refresh_on_max) {
> + char ts_str[64];
> + struct tm tm;
> + time_t ts;
> +
> + ts = stat->max_update_ts.tv_sec;
> + localtime_r(&ts, &tm);
> + /* RFC 2822-compliant date format */
> + strftime(ts_str, sizeof(ts_str), "%a, %d %b %Y %T %z", &tm);
This creates a really long line with redundant information, for example
T: 0 (36716) P: 0 I:1000 C: 1331 Min: 1 Act: 2 Avg: 12 Max:
71 Fri, 28 Aug 2026 10:18:32 -0400
T: 1 (36717) P: 0 I:1500 C: 887 Min: 1 Act: 2 Avg: 10 Max:
62 Fri, 28 Aug 2026 10:18:32 -0400
T: 2 (36718) P: 0 I:2000 C: 665 Min: 1 Act: 2 Avg: 28 Max:
56 Fri, 28 Aug 2026 10:18:32 -0400
T: 3 (36719) P: 0 I:2500 C: 532 Min: 1 Act: 52 Avg: 36 Max:
57 Fri, 28 Aug 2026 10:18:32 -0400
T: 4 (36720) P: 0 I:3000 C: 443 Min: 1 Act: 51 Avg: 21 Max:
55 Fri, 28 Aug 2026 10:18:32 -0400
T: 5 (36721) P: 0 I:3500 C: 380 Min: 1 Act: 2 Avg: 1 Max:
12 Fri, 28 Aug 2026 10:18:32 -0400
T: 6 (36722) P: 0 I:4000 C: 332 Min: 1 Act: 52 Avg: 49 Max:
62 Fri, 28 Aug 2026 10:18:32 -0400
Why not strftime(ts_str, sizeof(ts_str), "%T", &tm);
This will still go over 80 char, but it's more succinct.
T: 0 (40468) P: 0 I:1000 C: 282 Min: 1 Act: 52 Avg: 17 Max:
65 10:25:32
T: 1 (40469) P: 0 I:1500 C: 188 Min: 1 Act: 51 Avg: 22 Max:
56 10:25:31
T: 2 (40470) P: 0 I:2000 C: 141 Min: 1 Act: 2 Avg: 7 Max:
55 10:25:31
T: 3 (40471) P: 0 I:2500 C: 113 Min: 1 Act: 63 Avg: 19 Max:
63 10:25:32
T: 4 (40472) P: 0 I:3000 C: 94 Min: 1 Act: 52 Avg: 27 Max:
54 10:25:31
T: 5 (40473) P: 0 I:3500 C: 80 Min: 1 Act: 5 Avg: 43 Max:
56 10:25:32
T: 6 (40474) P: 0 I:4000 C: 70 Min: 1 Act: 51 Avg: 27 Max:
55 10:25:32
The other patches in this series look fine.
John
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 5/5] cyclictest: Add a timestamp of the last update
2026-08-28 14:26 ` John Kacur
@ 2026-08-28 16:10 ` Sebastian Andrzej Siewior
0 siblings, 0 replies; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-08-28 16:10 UTC (permalink / raw)
To: John Kacur; +Cc: linux-rt-users, John Kacur
On 2026-08-28 10:26:59 [-0400], John Kacur wrote:
> This creates a really long line with redundant information, for example
>
> T: 0 (36716) P: 0 I:1000 C: 1331 Min: 1 Act: 2 Avg: 12 Max:
> 71 Fri, 28 Aug 2026 10:18:32 -0400
> T: 1 (36717) P: 0 I:1500 C: 887 Min: 1 Act: 2 Avg: 10 Max:
> 62 Fri, 28 Aug 2026 10:18:32 -0400
> T: 2 (36718) P: 0 I:2000 C: 665 Min: 1 Act: 2 Avg: 28 Max:
> 56 Fri, 28 Aug 2026 10:18:32 -0400
> T: 3 (36719) P: 0 I:2500 C: 532 Min: 1 Act: 52 Avg: 36 Max:
> 57 Fri, 28 Aug 2026 10:18:32 -0400
> T: 4 (36720) P: 0 I:3000 C: 443 Min: 1 Act: 51 Avg: 21 Max:
> 55 Fri, 28 Aug 2026 10:18:32 -0400
> T: 5 (36721) P: 0 I:3500 C: 380 Min: 1 Act: 2 Avg: 1 Max:
> 12 Fri, 28 Aug 2026 10:18:32 -0400
> T: 6 (36722) P: 0 I:4000 C: 332 Min: 1 Act: 52 Avg: 49 Max:
> 62 Fri, 28 Aug 2026 10:18:32 -0400
>
> Why not strftime(ts_str, sizeof(ts_str), "%T", &tm);
> This will still go over 80 char, but it's more succinct.
I have do this wide screen here now. And I was using it on a test box
over network in tmux running for some time so I figured having a date is
helpful.
> T: 0 (40468) P: 0 I:1000 C: 282 Min: 1 Act: 52 Avg: 17 Max:
> 65 10:25:32
> T: 1 (40469) P: 0 I:1500 C: 188 Min: 1 Act: 51 Avg: 22 Max:
> 56 10:25:31
> T: 2 (40470) P: 0 I:2000 C: 141 Min: 1 Act: 2 Avg: 7 Max:
> 55 10:25:31
> T: 3 (40471) P: 0 I:2500 C: 113 Min: 1 Act: 63 Avg: 19 Max:
> 63 10:25:32
> T: 4 (40472) P: 0 I:3000 C: 94 Min: 1 Act: 52 Avg: 27 Max:
> 54 10:25:31
> T: 5 (40473) P: 0 I:3500 C: 80 Min: 1 Act: 5 Avg: 43 Max:
> 56 10:25:32
> T: 6 (40474) P: 0 I:4000 C: 70 Min: 1 Act: 51 Avg: 27 Max:
> 55 10:25:32
>
> The other patches in this series look fine.
Drop just 5/5 and I think of something once it bothers me again. If the
first four are good then the actual problem is gone. Thank you.
> John
Sebastian
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows'
2026-08-26 13:21 ` [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows' Sebastian Andrzej Siewior
@ 2026-08-31 16:40 ` John Kacur
0 siblings, 0 replies; 15+ messages in thread
From: John Kacur @ 2026-08-31 16:40 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linux-rt-users, John Kacur, Crystal Wood
[snip]
Signed-off-by: John Kacur <jkacur@redhat.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal()
2026-08-26 13:21 ` [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal() Sebastian Andrzej Siewior
@ 2026-08-31 16:41 ` John Kacur
2026-09-01 8:19 ` D, Suneeth
1 sibling, 0 replies; 15+ messages in thread
From: John Kacur @ 2026-08-31 16:41 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linux-rt-users, John Kacur
On Wed, 26 Aug 2026, Sebastian Andrzej Siewior wrote:
> With the -M option the output is updated once there is a new max value.
> On system with many threads (say 64) and aligned wake up (all threads
> wake at the same time) it is possible that all of them have a new
> maximal latency and all of them invoke pthread_cond_signal()
> simultaneously. They all will block in the kernel in the futex syscall
> on the same lock. And each of them will wake the printing thread one by
> one. This is not *that* visible with just a few threads and a quick
> CPU. But with many CPUs on a slower system this gets worse.
>
> Acquire refresh_on_max_lock with a trylock before invoking
> pthread_cond_signal(). This ensures that only one thread will send a
> waking request at a time. Should the lock be contained then delay the
> signalling until the next iteration.
>
> Make refresh_on_max_lock a PI lock. This shouldn't make much of a
> difference here given the try_lock usage in the RT thread but the
> unconditional locking will lead to complains by the RV-monitor.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: John Kacur <jkacur@redhat.com>
[snip]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock
2026-08-26 13:21 ` [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock Sebastian Andrzej Siewior
@ 2026-08-31 16:42 ` John Kacur
0 siblings, 0 replies; 15+ messages in thread
From: John Kacur @ 2026-08-31 16:42 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linux-rt-users, John Kacur
On Wed, 26 Aug 2026, Sebastian Andrzej Siewior wrote:
> break_thread_id_lock is acquired at the end once the application is
> about to terminate and the lock ensures that only the first thread
> writes/ updates the termination reason.
>
> Given its usage there is no requirement to have it as PI lock but having
> it as PI will keep the RV-monitor quiet so let's do it.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: John Kacur <jkacur@redhat.com>
[snip]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 4/5] cyclictest: Make trigger_lock a PI lock
2026-08-26 13:21 ` [PATCH 4/5] cyclictest: Make trigger_lock " Sebastian Andrzej Siewior
@ 2026-08-31 16:43 ` John Kacur
0 siblings, 0 replies; 15+ messages in thread
From: John Kacur @ 2026-08-31 16:43 UTC (permalink / raw)
To: Sebastian Andrzej Siewior; +Cc: linux-rt-users, John Kacur
On Wed, 26 Aug 2026, Sebastian Andrzej Siewior wrote:
> trigger_lock is acquired by the timer thread. Given its usage it
> probably makes no difference if it is PI or not but having it as PI will
> keep the RV-monitor quiet so let's do it.
>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: John Kacur <jkacur@redhat.com>
[snip]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal()
2026-08-26 13:21 ` [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal() Sebastian Andrzej Siewior
2026-08-31 16:41 ` John Kacur
@ 2026-09-01 8:19 ` D, Suneeth
2026-09-01 8:34 ` Tomas Glozar
2026-09-01 8:39 ` Sebastian Andrzej Siewior
1 sibling, 2 replies; 15+ messages in thread
From: D, Suneeth @ 2026-09-01 8:19 UTC (permalink / raw)
To: Sebastian Andrzej Siewior, linux-rt-users; +Cc: John Kacur
Hi Sebastian,
On 8/26/2026 6:51 PM, Sebastian Andrzej Siewior wrote:
> With the -M option the output is updated once there is a new max value.
> On system with many threads (say 64) and aligned wake up (all threads
> wake at the same time) it is possible that all of them have a new
> maximal latency and all of them invoke pthread_cond_signal()
> simultaneously. They all will block in the kernel in the futex syscall
> on the same lock. And each of them will wake the printing thread one by
> one. This is not *that* visible with just a few threads and a quick
> CPU. But with many CPUs on a slower system this gets worse.
>
> Acquire refresh_on_max_lock with a trylock before invoking
> pthread_cond_signal(). This ensures that only one thread will send a
> waking request at a time. Should the lock be contained then delay the
> signalling until the next iteration.
>
> Make refresh_on_max_lock a PI lock. This shouldn't make much of a
> difference here given the try_lock usage in the RT thread but the
> unconditional locking will lead to complains by the RV-monitor.
>
We use rt-tests/src/hackbench for Kernel Performance Regression testing
and with the latest HEAD on rt-tests/main, fd45df830803 (cyclicdeadline:
Fix potential path truncation in open_cpuset()) I'm observing build
failure with the below mentioned error message[1]. The caveat with this
build failure is that it happens only when compiled gcc_version < 14.
# make install
Makefile:48: libcpupower is missing, building without
--deepest-idle-state support.
Makefile:49: Please install libcpupower-dev/kernel-tools-libs-devel
Makefile:48: libcpupower is missing, building without
--deepest-idle-state support.
Makefile:49: Please install libcpupower-dev/kernel-tools-libs-devel
gcc -D VERSION=2.10 -c src/cyclictest/cyclictest.c -Wall -Werror
-Wno-nonnull -Wextra -Wno-sign-compare -Wno-unused-parameter
-Wno-error=format-truncation= -Wno-error=unused-result -O2 -g
-D_GNU_SOURCE -Isrc/include -o bld/cyclictest.o
src/cyclictest/cyclictest.c: In function ‘timerthread’:
src/cyclictest/cyclictest.c:653:9: error: unknown type name ‘bool’
653 | bool need_refresh_max = false;
| ^~~~
src/cyclictest/cyclictest.c:580:1: note: ‘bool’ is defined in header
‘<stdbool.h>’; did you forget to ‘#include <stdbool.h>’?
579 | #include <cpuid.h>
+++ |+#include <stdbool.h>
580 |
src/cyclictest/cyclictest.c:653:33: error: ‘false’ undeclared (first use
in this function)
653 | bool need_refresh_max = false;
| ^~~~~
src/cyclictest/cyclictest.c:653:33: note: ‘false’ is defined in header
‘<stdbool.h>’; did you forget to ‘#include <stdbool.h>’?
src/cyclictest/cyclictest.c:653:33: note: each undeclared identifier is
reported only once for each function it appears in
src/cyclictest/cyclictest.c:850:52: error: ‘true’ undeclared (first use
in this function)
850 | need_refresh_max = true;
| ^~~~
src/cyclictest/cyclictest.c:850:52: note: ‘true’ is defined in header
‘<stdbool.h>’; did you forget to ‘#include <stdbool.h>’?
make: *** [Makefile:122: bld/cyclictest.o] Error 1
STEPS TO REPRODUCE:
-------------------
1) cd rt-tests/
2) make install
FIX:
----
diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
index 99194378f946..58b56bcede0f 100644
--- a/src/cyclictest/cyclictest.c
+++ b/src/cyclictest/cyclictest.c
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <getopt.h>
I shall send the fix as a neatly formatted patch if the proposed fix LGTY.
Thanks and Regards,
Suneeth D
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
> src/cyclictest/cyclictest.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/src/cyclictest/cyclictest.c b/src/cyclictest/cyclictest.c
> index 960c905606684..29ddf2d98bbe1 100644
> --- a/src/cyclictest/cyclictest.c
> +++ b/src/cyclictest/cyclictest.c
> @@ -198,7 +198,7 @@ static int smi = 0;
> #endif
>
> static pthread_cond_t refresh_on_max_cond = PTHREAD_COND_INITIALIZER;
> -static pthread_mutex_t refresh_on_max_lock = PTHREAD_MUTEX_INITIALIZER;
> +static pthread_mutex_t refresh_on_max_lock;
>
> static pthread_mutex_t break_thread_id_lock = PTHREAD_MUTEX_INITIALIZER;
> static pid_t break_thread_id = 0;
> @@ -640,6 +640,7 @@ static void *timerthread(void *param)
> struct itimerval itimer;
> struct itimerspec tspec;
> struct thread_stat *stat = par->stats;
> + bool need_refresh_max = false;
> int stopped = 0;
> cpu_set_t mask;
> pthread_t thread;
> @@ -834,7 +835,14 @@ static void *timerthread(void *param)
> if (diff > stat->max) {
> stat->max = diff;
> if (refresh_on_max)
> + need_refresh_max = true;
> + }
> + if (need_refresh_max) {
> + if (!pthread_mutex_trylock(&refresh_on_max_lock)) {
> pthread_cond_signal(&refresh_on_max_cond);
> + pthread_mutex_unlock(&refresh_on_max_lock);
> + need_refresh_max = false;
> + }
> }
> stat->avg += (double) diff;
>
> @@ -1910,6 +1918,7 @@ static void set_main_thread_affinity(struct bitmask *cpumask)
>
> int main(int argc, char **argv)
> {
> + pthread_mutexattr_t mattr;
> sigset_t sigset;
> int signum = SIGALRM;
> int mode;
> @@ -1946,6 +1955,10 @@ int main(int argc, char **argv)
> }
> }
>
> + pthread_mutexattr_init(&mattr);
> + pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
> + pthread_mutex_init(&refresh_on_max_lock, &mattr);
> +
> /* lock all memory (prevent swapping) */
> if (lockall)
> if (mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal()
2026-09-01 8:19 ` D, Suneeth
@ 2026-09-01 8:34 ` Tomas Glozar
2026-09-01 8:39 ` Sebastian Andrzej Siewior
1 sibling, 0 replies; 15+ messages in thread
From: Tomas Glozar @ 2026-09-01 8:34 UTC (permalink / raw)
To: D, Suneeth; +Cc: Sebastian Andrzej Siewior, linux-rt-users, John Kacur
On Tue, Sep 1, 2026 at 10:20 AM D, Suneeth <suneethd@amd.com> wrote:
>
> We use rt-tests/src/hackbench for Kernel Performance Regression testing
> and with the latest HEAD on rt-tests/main, fd45df830803 (cyclicdeadline:
> Fix potential path truncation in open_cpuset()) I'm observing build
> failure with the below mentioned error message[1]. The caveat with this
> build failure is that it happens only when compiled gcc_version < 14.
>
>...
> src/cyclictest/cyclictest.c: In function ‘timerthread’:
> src/cyclictest/cyclictest.c:653:9: error: unknown type name ‘bool’
> 653 | bool need_refresh_max = false;
> | ^~~~
> src/cyclictest/cyclictest.c:580:1: note: ‘bool’ is defined in header
> ‘<stdbool.h>’; did you forget to ‘#include <stdbool.h>’?
> ...
GCC 15 switched to C23 as default [1]. The patch appears to be using
C23-only bool type, see [2]:
[1] https://gcc.gnu.org/gcc-15/changes.html ("C23 by default")
[2] https://en.cppreference.com/c/language/bool_constant
Doing #include <stdbool.h> should be an easy fix.
Tomas
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal()
2026-09-01 8:19 ` D, Suneeth
2026-09-01 8:34 ` Tomas Glozar
@ 2026-09-01 8:39 ` Sebastian Andrzej Siewior
1 sibling, 0 replies; 15+ messages in thread
From: Sebastian Andrzej Siewior @ 2026-09-01 8:39 UTC (permalink / raw)
To: D, Suneeth; +Cc: linux-rt-users, John Kacur
On 2026-09-01 13:49:33 [+0530], D, Suneeth wrote:
> I shall send the fix as a neatly formatted patch if the proposed fix LGTY.
Yes, please do.
Sebastian
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-09-01 8:39 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-26 13:21 [PATCH 0/5] cyclictest: Little tweaks here and there Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 1/5] rt-tests: cyclicdeadline: Remove unused `alloverflows' Sebastian Andrzej Siewior
2026-08-31 16:40 ` John Kacur
2026-08-26 13:21 ` [PATCH 2/5] cyclictest: Acquire a lock before invoking pthread_cond_signal() Sebastian Andrzej Siewior
2026-08-31 16:41 ` John Kacur
2026-09-01 8:19 ` D, Suneeth
2026-09-01 8:34 ` Tomas Glozar
2026-09-01 8:39 ` Sebastian Andrzej Siewior
2026-08-26 13:21 ` [PATCH 3/5] cyclictest: Make break_thread_id_lock a PI lock Sebastian Andrzej Siewior
2026-08-31 16:42 ` John Kacur
2026-08-26 13:21 ` [PATCH 4/5] cyclictest: Make trigger_lock " Sebastian Andrzej Siewior
2026-08-31 16:43 ` John Kacur
2026-08-26 13:21 ` [PATCH 5/5] cyclictest: Add a timestamp of the last update Sebastian Andrzej Siewior
2026-08-28 14:26 ` John Kacur
2026-08-28 16:10 ` Sebastian Andrzej Siewior
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.