Re: [PATCH] alarm: use common implementation calling setitimer()

Bela Lubkin <[email protected]> Sun, 20 Feb 2011 15:36:34 -0800
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
Enrico,

All of todays patchsets look reasonable to me.

I made some (I think) improvements in test/alarm.c:

- Check for early as well as late delivery of alarm
- Report a sample of difference between requested & actual alarm length
- Report whether alarm() & setitimer(ITIMER_REAL) share a single timer
  (another system I tried had a strange result that I also check for)
- Collapse `rc = whatever(); assert(rc == 0)' to give better diagnostics
- Changes to also build clean w/glibc (for testing the test)

Diff against Enrico's version attached.

[trivia]  The following lib/__alarm.c code (moved from alpha/__alarm.c)
uses tabs to line up assignments: looks wrong in diffs, and isn't even
successful (interval.tv_usec is off).  Either remove the extra spacing,
or convert to spaces & make all 4 align:

> +  new.it_interval.tv_usec=0;
> +  new.it_interval.tv_sec=0;
> +  new.it_value.tv_usec	=0;
> +  new.it_value.tv_sec	=(long)seconds;

>Bela<

--- test/alarm.c.orig	2011-02-20 13:02:00.000000000 -0800
+++ test/alarm.c	2011-02-20 15:26:24.000000000 -0800
@@ -1,64 +1,98 @@
+#include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 
+#include <sys/time.h>
 #include <time.h>
 #include <unistd.h>
 #include <signal.h>
 
-static volatile int	alrm_triggered;
+typedef my_sighandler_t (void(*)(int));
+
+static volatile int		alrm_triggered;
+static volatile struct timeval	atv[8];
+struct itimerval		itv, oitv;
 
 static void sig_alrm(int s)
 {
-	alrm_triggered = 1;
+	/* preinc to reduce time between inc & struct use -- wastes atv[0] */
+	gettimeofday((struct timeval *)&atv[++alrm_triggered], 0);
+	assert(alrm_triggered + 1 < sizeof(atv) / sizeof(atv[0]));
 }
 
-int main()
+int main(int argc, char *argv[])
 {
 	int		rc;
 	time_t		end;
-	sighandler_t	old_sig;
+	my_sighandler_t	*old_sig;
+	struct timeval	stv;
+	float		delta_tm, old_tm;
+	char 		*me = argv[0];
 
 	alarm(50);
 
-	old_sig = signal(SIGALRM, &sig_alrm);
-	assert(old_sig != SIG_ERR);
+	old_sig = (my_sighandler_t *)signal(SIGALRM, &sig_alrm);
+	assert(old_sig != (my_sighandler_t *)SIG_ERR);
 
 	/* check whether alarm() returns correct number of remaining
 	 * seconds */
-	rc = alarm(2);
-	assert(rc > 40 && rc <= 50);
+	gettimeofday(&stv, 0);
+	assert((rc = alarm(2)) > 40 && rc <= 50);
 
 	/* check whether SIGALRM is triggered within the set time */
 	end = time(NULL) + 5;
 	while (!alrm_triggered && time(NULL) < end) {
 		/* noop */
 	}
-	assert(alrm_triggered);
+	assert(alrm_triggered == 1);
+	delta_tm = atv[1].tv_sec - stv.tv_sec +
+                   (atv[1].tv_usec - stv.tv_usec) / 1000000.0;
+	printf("info: %s: alarm(2) took %.6fs (%.6fs difference).\n",
+               me, delta_tm, delta_tm - 2.0);
+	assert(delta_tm >= 2.0 && delta_tm <= 3.0);
 
 	/* there should be no pending alarm */
-	rc = alarm(0);
-	assert(rc == 0);
+	assert(alarm(0) == 0);
 
 	alrm_triggered = 0;
 
 	/* test whether alarm can be canceled */
-	rc = alarm(2);
-	assert(rc == 0);
+	assert(alarm(2) == 0);
 
-	rc = alarm(0);
-	assert(rc > 0 && rc < 4);
+	assert((rc = alarm(0)) > 0 && rc < 4);
 	assert(!alrm_triggered);
 
 	/* there should not happen an alarm */
 	end = time(NULL) + 5;
 	while (!alrm_triggered && time(NULL) < end) {
 		/* noop */
 	}
 	assert(!alrm_triggered);
 
 	/* there should be no pending alarm */
-	rc = alarm(0);
-	assert(rc == 0);
+	assert(alarm(0) == 0);
+
+	/* check if alarm() & setitimer(ITIMER_REAL) are shared */
+	itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
+	assert(setitimer(ITIMER_REAL, &itv, &oitv) == 0);
+	assert(alarm(10) == 0);
+	itv.it_value.tv_sec = 20;
+	assert(setitimer(ITIMER_REAL, &itv, &oitv) == 0);
+	old_tm = oitv.it_value.tv_sec + oitv.it_value.tv_usec / 1000000.0;
+	printf("info: %s: after setitimer(ITIMER_REAL = 0), alarm(10),\n"
+	       "info: %s: setitimer(ITIMER_REAL = 20) old timer was %.6fs.\n",
+	       me, me, old_tm);
+	printf("info: %s: alarm() & setitimer(ITIMER_REAL) timers are:", me);
+	if (old_tm == 0.0) {
+		printf(" disjoint.\n");
+	} else if (old_tm > 9.9 && old_tm <= 10.1) {
+		printf(" shared.\n");
+	} else if (old_tm > 8.9 && old_tm <= 9.1) {
+		printf("\nwarning: %s: shared in a strange manner.\n", me);
+	} else {
+		printf("\n");
+		assert(old_tm == 0.0 || (old_tm > 9.9 && old_tm <= 10.1));
+	}
 
 	return EXIT_SUCCESS;
 }