git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 9/9] Use timer_settime for new platforms

From
Jacob Keller <jacob.e.keller@intel.com>
Date
Aug 29, 2014, 16:42 UTC
Message-ID
<1409330561-11806-9-git-send-email-jacob.e.keller@intel.com>
In-Reply-To
<1409330561-11806-1-git-send-email-jacob.e.keller@intel.com>
From: Jonas 'Sortie' Termansen <sortie@maxsi.org>

setitimer() is an obsolescent XSI interface and may be removed in a future standard. Applications should use the core POSIX timer_settime() instead.

It's important that code doesn't simply check if timer_settime is available as it can give false positives. Some systems like contemporary OpenBSD provides the function, but it unconditionally fails with ENOSYS at runtime.

Clean up the progress reporting and change it to use timer_settime, which will fall back to setitimer automatically if timer_settime is not supported. (see git-compat-util.h for how it does this). If both functions are not present, then git-compat-util.h provides replacements which will always fail with ENOSYS.

The approach used here enables us to use a single API (timer_settime) without having to worry about checking for #ifdefs or if blocks which make it an unreadable nightmare. The major downside is for systems without timer_settime support, they may fall back on a wrapped implementation which could have subtle differences. This should be a minor issue as almost all modern systems provide timer_settime support.

Note that this change means that git should never use setitimer on its own now, as the fallback implementation of timer_settime assumes that it is the sole user of ITIMER_REAL, and timer_delete will reset the ITIMER_REAL.

Signed-off-by: Jonas 'Sortie' Termansen <sortie@maxsi.org>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
---
 builtin/log.c | 27 ++++++++++++++++++++-------
 progress.c    | 20 +++++++++++++-------
 2 files changed, 33 insertions(+), 14 deletions(-)
diff --git a/builtin/log.c b/builtin/log.c
index 4389722b4b1e..a39e82d67eb3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -229,7 +229,7 @@ static void show_early_header(struct rev_info *rev, const char *stage, int nr)
 	printf(_("Final output: %d %s\n"), nr, stage);
 }
 
-static struct itimerval early_output_timer;
+static timer_t early_output_timer;
 
 static void log_show_early(struct rev_info *revs, struct commit_list *list)
 {
@@ -271,9 +271,12 @@ static void log_show_early(struct rev_info *revs, struct commit_list *list)
 	 * trigger every second even if we're blocked on a
 	 * reader!
 	 */
-	early_output_timer.it_value.tv_sec = 0;
-	early_output_timer.it_value.tv_usec = 500000;
-	setitimer(ITIMER_REAL, &early_output_timer, NULL);
+	struct itimerspec value;
+	value.it_value.tv_sec = 0;
+	value.it_value.tv_nsec = 500000L * 1000L;
+	value.it_interval.tv_sec = 0;
+	value.it_interval.tv_nsec = 0;
+	timer_settime(early_output_timer, 0, &value, NULL);
 }
 
 static void early_output(int signal)
@@ -284,6 +287,7 @@ static void early_output(int signal)
 static void setup_early_output(struct rev_info *rev)
 {
 	struct sigaction sa;
+	struct sigevent sev;
 
 	/*
 	 * Set up the signal handler, minimally intrusively:
@@ -305,14 +309,23 @@ static void setup_early_output(struct rev_info *rev)
 	 *
 	 * This is a one-time-only trigger.
 	 */
-	early_output_timer.it_value.tv_sec = 0;
-	early_output_timer.it_value.tv_usec = 100000;
-	setitimer(ITIMER_REAL, &early_output_timer, NULL);
+	memset(&sev, 0, sizeof(sev));
+	sev.sigev_notify = SIGEV_SIGNAL;
+	sev.sigev_signo = SIGALRM;
+	timer_create(CLOCK_MONOTONIC, &sev, &early_output_timer);
+
+	struct itimerspec value;
+	value.it_value.tv_sec = 0;
+	value.it_value.tv_nsec = 100000L * 1000L;
+	value.it_interval.tv_sec = 0;
+	value.it_interval.tv_nsec = 0;
+	timer_settime(early_output_timer, 0, &value, NULL);
 }
 
 static void finish_early_output(struct rev_info *rev)
 {
 	int n = estimate_commit_count(rev, rev->commits);
+	timer_delete(early_output_timer);
 	signal(SIGALRM, SIG_IGN);
 	show_early_header(rev, "done", n);
 }
diff --git a/progress.c b/progress.c
index 412e6b1ecc36..7fe73df35625 100644
--- a/progress.c
+++ b/progress.c
@@ -38,6 +38,7 @@ struct progress {
 	struct throughput *throughput;
 };
 
+static timer_t progress_timer;
 static volatile sig_atomic_t progress_update;
 
 static void progress_interval(int signum)
@@ -48,7 +49,7 @@ static void progress_interval(int signum)
 static void set_progress_signal(void)
 {
 	struct sigaction sa;
-	struct itimerval v;
+	struct sigevent sev;
 
 	progress_update = 0;
 
@@ -58,16 +59,21 @@ static void set_progress_signal(void)
 	sa.sa_flags = SA_RESTART;
 	sigaction(SIGALRM, &sa, NULL);
 
-	v.it_interval.tv_sec = 1;
-	v.it_interval.tv_usec = 0;
-	v.it_value = v.it_interval;
-	setitimer(ITIMER_REAL, &v, NULL);
+	memset(&sev, 0, sizeof(sev));
+	sev.sigev_notify = SIGEV_SIGNAL;
+	sev.sigev_signo = SIGALRM;
+	timer_create(CLOCK_MONOTONIC, &sev, &progress_timer);
+
+	struct itimerspec value;
+	value.it_interval.tv_sec = 1;
+	value.it_interval.tv_nsec = 0;
+	value.it_value = value.it_interval;
+	timer_settime(progress_timer, 0, &value, NULL);
 }
 
 static void clear_progress_signal(void)
 {
-	struct itimerval v = {{0,},};
-	setitimer(ITIMER_REAL, &v, NULL);
+	timer_delete(progress_timer);
 	signal(SIGALRM, SIG_IGN);
 	progress_update = 0;
 }
-- 
2.0.1.475.g9b8d714
Previous: Keller, Jacob ENext: Junio C Hamano
Message 15 of 23 in “git-compat-util.h: Add missing semicolon after struct itimerval”
  1. 1/9 git-compat-util.h: Add missing semicolon after struct itimervalJacob Keller, Aug 29, 2014
  2. 2/9 autoconf: Check for struct itimervalJacob Keller, Aug 29, 2014
  3. 3/9 autoconf: Check for setitimerJacob Keller, Aug 29, 2014
  4. 4/9 autoconf: Check for timer_tJacob Keller, Aug 29, 2014
  5. Jonas 'Sortie' TermansenAug 29, 2014
  6. 5/9 autoconf: Check for struct timespecJacob Keller, Aug 29, 2014
  7. 6/9 autoconf: Check for struct sigeventJacob Keller, Aug 29, 2014
  8. 7/9 autoconf: Check for struct itimerspecJacob Keller, Aug 29, 2014
  9. 8/9 autoconf: Check for timer_settimeJacob Keller, Aug 29, 2014
  10. Johannes SixtAug 29, 2014
  11. Keller, Jacob EAug 29, 2014
  12. Karsten BleesSep 10, 2014
  13. Junio C HamanoSep 10, 2014
  14. Keller, Jacob ESep 10, 2014
  15. 9/9 Use timer_settime for new platformsJacob Keller, Aug 29, 2014
  16. Junio C HamanoAug 29, 2014
  17. Keller, Jacob EAug 29, 2014
  18. Junio C HamanoAug 29, 2014
  19. Keller, Jacob EAug 29, 2014
  20. Jonas 'Sortie' TermansenAug 29, 2014
  21. Junio C HamanoAug 29, 2014
  22. Jonas 'Sortie' TermansenAug 29, 2014
  23. Keller, Jacob ESep 3, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.