Skip to content

Commit 2854c5b

Browse files
committed
pselect01: Tune thresholds
The testcase was failing frequenty on virtual machines where the thresholds were too tight and also on hardware without specialized timer units so I've revisited the threshold computation and came with this model: The threshold per one syscall is computed as a sum of: 250 us - accomodates for context switches, etc. 2 * CLOCK_MONOTONIC resolution - accomodates for granurality of the CLOCK_MONOTONIC 0.1% of the sleep capped on 100ms - which is slack allowed in kernel Then it's multiplied by the number of iterations. For hardware without specialized timer units (TSC, HPET and such) the threshold is dominated by the CLOCK_MONOTONIC precision which is, depending on CONFIG_HZ, something between 100ms and 10ms. If hardware has high resolution timers, short sleeps are dominated by context switches while longer sleeps are much more dominated by the slack. And finally this all works only if the number of iterations is high enough, we can still hit outliners otherwise so we add 1500us to the threshold to compensate for them in a case that number of iterations is small. Signed-off-by: Cyril Hrubis <[email protected]> Acked-by: Jan Stancek <[email protected]>
1 parent eac3375 commit 2854c5b

File tree

1 file changed

+60
-7
lines changed

1 file changed

+60
-7
lines changed

testcases/kernel/syscalls/pselect/pselect01.c

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,38 @@ struct tcase {
4141
unsigned int iterations;
4242
};
4343

44+
static unsigned int monotonic_resolution;
45+
4446
static struct tcase tcases[] = {
45-
{{1, 0}, 1},
46-
{{0, 1000000}, 100},
47-
{{0, 2000000}, 100},
48-
{{0, 10000000}, 10},
49-
{{0, 100000000}, 1},
47+
{{0, 1000000}, 500},
48+
{{0, 2000000}, 500},
49+
{{0, 10000000}, 300},
50+
{{0, 100000000}, 1},
51+
{{1, 0}, 1},
5052
};
5153

54+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
55+
56+
/*
57+
* The threshold per one syscall is computed as a sum of:
58+
*
59+
* 250 us - accomodates for context switches, etc.
60+
* 2*monotonic_resolution - accomodates for granurality of the CLOCK_MONOTONIC
61+
* slack_per_scall - 0.1% of the sleep capped on 100ms
62+
* which is slack allowed in kernel
63+
*
64+
* We also allow for outliners, i.e. add some number to the threshold in case
65+
* that the number of iteration is small. For large enoung number of iterations
66+
* outliners are averaged out.
67+
*/
68+
static int compute_threshold(long long requested_us, unsigned int iterations)
69+
{
70+
unsigned int slack_per_scall = MIN(100000, requested_us / 1000);
71+
72+
return (250 + 2 * monotonic_resolution + slack_per_scall) * iterations
73+
+ (iterations > 1 ? 0 : 1500);
74+
}
75+
5276
static void verify_pselect(unsigned int n)
5377
{
5478
fd_set readfds;
@@ -62,6 +86,8 @@ static void verify_pselect(unsigned int n)
6286
t->tv.tv_sec, t->tv.tv_nsec, t->iterations);
6387

6488
for (i = 0; i < t->iterations; i++) {
89+
long long elapsed_us;
90+
6591
FD_ZERO(&readfds);
6692
FD_SET(0, &readfds);
6793

@@ -71,11 +97,26 @@ static void verify_pselect(unsigned int n)
7197
pselect(0, &readfds, NULL, NULL, &tv, NULL);
7298
tst_timer_stop();
7399

74-
slept_us += tst_timer_elapsed_us();
100+
elapsed_us = tst_timer_elapsed_us();
101+
102+
if (elapsed_us >= 10 * tst_timespec_to_us(t->tv)
103+
&& elapsed_us > 3 * monotonic_resolution) {
104+
tst_res(TINFO,
105+
"Found outliner took %lli us, expected %lli us",
106+
elapsed_us, tst_timespec_to_us(t->tv));
107+
}
108+
109+
slept_us += elapsed_us;
75110
}
76111

77112
requested_us = tst_timespec_to_us(t->tv) * t->iterations;
78-
threshold = requested_us / 100 + 200 * t->iterations;
113+
threshold = compute_threshold(tst_timespec_to_us(t->tv), t->iterations);
114+
115+
if (t->iterations > 1) {
116+
tst_res(TINFO, "Mean sleep time %.2f us, expected %lli us, threshold %.2f",
117+
1.00 * slept_us / t->iterations,
118+
tst_timespec_to_us(t->tv), 1.00 * threshold / t->iterations);
119+
}
79120

80121
if (slept_us < requested_us) {
81122
tst_res(TFAIL,
@@ -95,8 +136,20 @@ static void verify_pselect(unsigned int n)
95136
slept_us, requested_us, threshold);
96137
}
97138

139+
static void setup(void)
140+
{
141+
struct timespec t;
142+
143+
clock_getres(CLOCK_MONOTONIC, &t);
144+
145+
tst_res(TINFO, "CLOCK_MONOTONIC resolution %li ns", (long)t.tv_nsec);
146+
147+
monotonic_resolution = t.tv_nsec / 1000;
148+
}
149+
98150
static struct tst_test test = {
99151
.tid = "pselect01",
100152
.test = verify_pselect,
153+
.setup = setup,
101154
.tcnt = ARRAY_SIZE(tcases),
102155
};

0 commit comments

Comments
 (0)