[LTP] [PATCH v1] Correctly handle user time in setitimer01

Andrea Cervesato andrea.cervesato@suse.com
Fri Nov 4 10:24:11 CET 2022


Since ITIMER_VIRTUAL and ITIMER_PROF are counting down in user time, we
need to take in consideration CLOCK_MONOTONIC_COARSE resolution. This is
requested by the syscall, since it's considering context switch from
user to kernel mode by using a higher clock resolution.

Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com>
---
 .../kernel/syscalls/setitimer/setitimer01.c   | 54 +++++++++++--------
 1 file changed, 33 insertions(+), 21 deletions(-)

diff --git a/testcases/kernel/syscalls/setitimer/setitimer01.c b/testcases/kernel/syscalls/setitimer/setitimer01.c
index eb62f02c6..5fcae53e8 100644
--- a/testcases/kernel/syscalls/setitimer/setitimer01.c
+++ b/testcases/kernel/syscalls/setitimer/setitimer01.c
@@ -8,9 +8,16 @@
 /*\
  * [Description]
  *
- * Spawn a child and verify that setitimer() syscall passes, and it ends up
+ * Spawn a child, verify that setitimer() syscall passes and it ends up
  * counting inside expected boundaries. Then verify from the parent that our
  * syscall sent the correct signal to the child.
+ *
+ * Boundaries are choosen accordingly with system clock. In particular, when
+ * timer counts down in real time, CLOCK_MONOTONIC resolution has taken into
+ * account as our time step. When timer counts down in user time,
+ * CLOCK_MONOTONIC_COARSE is used. The reason is that CLOCK_MONOTONIC_COARSE
+ * is our system resolution in user space, since it's taking in consideration
+ * context switches from user to kernel space.
  */
 
 #include <time.h>
@@ -22,7 +29,6 @@
 #include "tst_safe_clocks.h"
 
 static struct itimerval *value, *ovalue;
-static unsigned long time_step;
 
 static struct tcase {
 	int which;
@@ -55,9 +61,31 @@ static void set_setitimer_value(int usec, int o_usec)
 static void verify_setitimer(unsigned int i)
 {
 	pid_t pid;
-	int status;
-	int usec = 3 * time_step;
+	struct timespec res;
 	struct tcase *tc = &tcases[i];
+	int status, usec, time_step, error;
+
+	if (tc->which == ITIMER_REAL)
+		SAFE_CLOCK_GETRES(CLOCK_MONOTONIC, &res);
+	else
+		SAFE_CLOCK_GETRES(CLOCK_MONOTONIC_COARSE, &res);
+
+	time_step = res.tv_nsec / 1000;
+	error = time_step;
+
+	if (time_step <= 0) {
+		time_step = 1000;
+		error = 0;
+	}
+
+	usec = 3 * time_step;
+
+	tst_res(TINFO, "clock resolution: %luns, "
+		"time step: %ius, "
+		"counter time: %ius",
+		res.tv_nsec,
+		time_step,
+		usec);
 
 	pid = SAFE_FORK();
 
@@ -76,7 +104,7 @@ static void verify_setitimer(unsigned int i)
 			ovalue->it_value.tv_sec,
 			ovalue->it_value.tv_usec);
 
-		if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_usec > usec)
+		if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_usec > usec + error)
 			tst_res(TFAIL, "Ending counters are out of range");
 
 		for (;;)
@@ -91,26 +119,10 @@ static void verify_setitimer(unsigned int i)
 		tst_res(TFAIL, "Child: %s", tst_strstatus(status));
 }
 
-static void setup(void)
-{
-	struct timespec res;
-
-	SAFE_CLOCK_GETRES(CLOCK_MONOTONIC, &res);
-
-	time_step = res.tv_nsec / 1000;
-	if (time_step < 10000)
-		time_step = 10000;
-
-	tst_res(TINFO, "clock resolution: %luns, time step: %luus",
-		res.tv_nsec,
-		time_step);
-}
-
 static struct tst_test test = {
 	.tcnt = ARRAY_SIZE(tcases),
 	.forks_child = 1,
 	.test = verify_setitimer,
-	.setup = setup,
 	.bufs = (struct tst_buffers[]) {
 		{&value,  .size = sizeof(struct itimerval)},
 		{&ovalue, .size = sizeof(struct itimerval)},
-- 
2.35.3



More information about the ltp mailing list