Replace gettimeofday() by clock_gettime().
authorAndre Noll <maan@systemlinux.org>
Sun, 31 Mar 2013 02:03:04 +0000 (02:03 +0000)
committerAndre Noll <maan@systemlinux.org>
Tue, 30 Apr 2013 12:12:45 +0000 (14:12 +0200)
POSIX.1-2008 marks gettimeofday() as obsolete, so let's switch to
clock_gettime().

clock_gettime() operates on timespecs rather than on timevals like
gettimeofday() does. Since timevals are extensively used in all
parts of paraslash, and select() takes a timeval pointer as the
timeout parameter, it seems to be easiest to add a new wrapper,
clock_get_realtime(). It calls clock_gettime(), performs error
checking (all errors are treated fatal and abort the program), and
converts the result to a timeval.

Another difference between gettimeofday() and clock_gettime()
is that sys/time.h needs to be included for gettimeofday(), while
clock_gettime() is declared in time.h which gets included from para.h.
Hence we can remove the include statement for sys/time.h everywhere.

Programs which call clock_gettime need to be linked against librt on
glibc versions before 2.17 while BSD and newer glibc-based systems
have no such requirement. To make matters more interesting,
MacOS lacks clock_gettime() completely although this function conforms
to SUSv2 and POSIX.1-2001.

We'd like to avoid the unnecessary dependence on librt on systems that
have clock_gettime() in -lc, and we must fall back to gettimeofday()
on MacOS. Hence this commit also introduces a check in configure.ac
which determines whether clock_gettime() is available and, if it is,
whether -lrt is needed. Executables are only linked with -lrt if
configure found that this is necessary.

17 files changed:
Makefile.in
afh.c
afh_common.c
alsa_write.c
command.c
configure.ac
daemon.c
file_write.c
para.h
play.c
sched.c
sched.h
server.c
string.c
time.c
udp_send.c
wmadec_filter.c

index d577ce2..7ccd970 100644 (file)
@@ -79,6 +79,8 @@ CPPFLAGS += -I/usr/local/include
 CPPFLAGS += -I$(cmdline_dir)
 CPPFLAGS += @osl_cppflags@
 
 CPPFLAGS += -I$(cmdline_dir)
 CPPFLAGS += @osl_cppflags@
 
+LDFLAGS += @clock_gettime_ldflags@
+
 man_pages := $(patsubst %, $(man_dir)/%.1, @executables@)
 
 autocrap := config.h.in configure
 man_pages := $(patsubst %, $(man_dir)/%.1, @executables@)
 
 autocrap := config.h.in configure
diff --git a/afh.c b/afh.c
index aab664c..4c65d7c 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -7,7 +7,6 @@
 /** \file afh.c Paraslash's standalone audio format handler tool. */
 
 #include <regex.h>
 /** \file afh.c Paraslash's standalone audio format handler tool. */
 
 #include <regex.h>
-#include <sys/time.h>
 
 #include "para.h"
 #include "string.h"
 
 #include "para.h"
 #include "string.h"
index 5c866c1..6c161a7 100644 (file)
@@ -7,7 +7,6 @@
 /** \file afh_common.c Common audio format handler functions. */
 
 #include <sys/mman.h> /* mmap */
 /** \file afh_common.c Common audio format handler functions. */
 
 #include <sys/mman.h> /* mmap */
-#include <sys/time.h> /* gettimeofday */
 #include <sys/types.h>
 #include <regex.h>
 
 #include <sys/types.h>
 #include <regex.h>
 
index ba844db..43f0811 100644 (file)
@@ -15,7 +15,6 @@
 #include <regex.h>
 #include <sys/types.h>
 #include <alsa/asoundlib.h>
 #include <regex.h>
 #include <sys/types.h>
 #include <alsa/asoundlib.h>
-#include <sys/time.h>
 
 #include "para.h"
 #include "fd.h"
 
 #include "para.h"
 #include "fd.h"
index aaaaaec..ec822c8 100644 (file)
--- a/command.c
+++ b/command.c
@@ -8,7 +8,6 @@
 
 #include <regex.h>
 #include <signal.h>
 
 #include <regex.h>
 #include <signal.h>
-#include <sys/time.h>
 #include <sys/types.h>
 #include <osl.h>
 
 #include <sys/types.h>
 #include <osl.h>
 
@@ -124,7 +123,7 @@ static unsigned get_status(struct misc_meta_data *nmmd, int parser_friendly,
                localtime_r(&nmmd->mtime, &mtime_tm);
                strftime(mtime, 29, "%b %d %Y", &mtime_tm);
        }
                localtime_r(&nmmd->mtime, &mtime_tm);
                strftime(mtime, 29, "%b %d %Y", &mtime_tm);
        }
-       gettimeofday(&current_time, NULL);
+       clock_get_realtime(&current_time);
        /*
         * The calls to WRITE_STATUS_ITEM() below never fail because
         * b->max_size is zero (unlimited), see para_printf(). However, clang
        /*
         * The calls to WRITE_STATUS_ITEM() below never fail because
         * b->max_size is zero (unlimited), see para_printf(). However, clang
index 4512c6f..6f0fbc0 100644 (file)
@@ -247,6 +247,18 @@ if test x$ac_cv_have_working_snprintf$ac_cv_have_working_vsnprintf != "xyesyes";
 AC_MSG_ERROR([fatal: buggy snprintf() detected])
 fi])
 AX_FUNC_SNPRINTF()
 AC_MSG_ERROR([fatal: buggy snprintf() detected])
 fi])
 AX_FUNC_SNPRINTF()
+################################################################## clock_gettime
+clock_gettime_lib=
+AC_CHECK_LIB([c], [clock_gettime], [clock_gettime_lib=c], [
+       AC_CHECK_LIB([rt], [clock_gettime], [clock_gettime_lib=rt], [], [])
+])
+if test -n "$clock_gettime_lib"; then
+       AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [
+               define to 1 if clock_gettime() is supported])
+fi
+if test "$clock_gettime_lib" = "rt"; then
+       AC_SUBST(clock_gettime_ldflags, -lrt)
+fi
 ########################################################################### osl
 have_osl=yes
 OLD_CPPFLAGS="$CPPFLAGS"
 ########################################################################### osl
 have_osl=yes
 OLD_CPPFLAGS="$CPPFLAGS"
index 29b00ed..18ad156 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -10,7 +10,6 @@
 #include <pwd.h>
 #include <sys/types.h> /* getgrnam() */
 #include <grp.h>
 #include <pwd.h>
 #include <sys/types.h> /* getgrnam() */
 #include <grp.h>
-#include <sys/time.h>
 #include <signal.h>
 
 #include "para.h"
 #include <signal.h>
 
 #include "para.h"
@@ -374,7 +373,7 @@ __printf_2_3 void daemon_log(int ll, const char* fmt,...)
                fprintf(fp, "%s", color);
        if (log_time || log_timing) {
                struct timeval tv;
                fprintf(fp, "%s", color);
        if (log_time || log_timing) {
                struct timeval tv;
-               gettimeofday(&tv, NULL);
+               clock_get_realtime(&tv);
                if (daemon_test_flag(DF_LOG_TIME)) { /* print date and time */
                        time_t t1 = tv.tv_sec;
                        char str[100];
                if (daemon_test_flag(DF_LOG_TIME)) { /* print date and time */
                        time_t t1 = tv.tv_sec;
                        char str[100];
index a12867d..3f76476 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <regex.h>
 #include <sys/types.h>
 
 #include <regex.h>
 #include <sys/types.h>
-#include <sys/time.h>
 
 #include "para.h"
 #include "list.h"
 
 #include "para.h"
 #include "list.h"
@@ -38,10 +37,8 @@ struct private_file_write_data {
 __must_check __malloc static char *random_filename(void)
 {
        char *result, *home = para_homedir();
 __must_check __malloc static char *random_filename(void)
 {
        char *result, *home = para_homedir();
-       struct timeval tv;
 
 
-       gettimeofday(&tv, NULL);
-       srandom(tv.tv_usec);
+       srandom(clock_get_realtime(NULL)->tv_usec);
        result = make_message("%s/.paraslash/%08lu", home,
                para_random(99999999));
        free(home);
        result = make_message("%s/.paraslash/%08lu", home,
                para_random(99999999));
        free(home);
diff --git a/para.h b/para.h
index 4208ae6..edab487 100644 (file)
--- a/para.h
+++ b/para.h
@@ -109,6 +109,7 @@ void ms2tv(const long unsigned n, struct timeval *tv);
 void compute_chunk_time(long unsigned chunk_num,
                struct timeval *chunk_tv, struct timeval *stream_start,
                struct timeval *result);
 void compute_chunk_time(long unsigned chunk_num,
                struct timeval *chunk_tv, struct timeval *stream_start,
                struct timeval *result);
+struct timeval *clock_get_realtime(struct timeval *tv);
 
 /** The enum of all status items. */
 enum status_items {STATUS_ITEM_ENUM NUM_STAT_ITEMS};
 
 /** The enum of all status items. */
 enum status_items {STATUS_ITEM_ENUM NUM_STAT_ITEMS};
diff --git a/play.c b/play.c
index cca203b..fb72bae 100644 (file)
--- a/play.c
+++ b/play.c
@@ -7,7 +7,6 @@
 /** \file play.c Paraslash's standalone player. */
 
 #include <regex.h>
 /** \file play.c Paraslash's standalone player. */
 
 #include <regex.h>
-#include <sys/time.h>
 #include <fnmatch.h>
 #include <signal.h>
 
 #include <fnmatch.h>
 #include <signal.h>
 
@@ -1255,7 +1254,7 @@ int main(int argc, char *argv[])
        filter_init();
        writer_init();
 
        filter_init();
        writer_init();
 
-       gettimeofday(now, NULL);
+       clock_get_realtime(now);
        sched.default_timeout.tv_sec = 5;
 
        parse_config_or_die(argc, argv);
        sched.default_timeout.tv_sec = 5;
 
        parse_config_or_die(argc, argv);
diff --git a/sched.c b/sched.c
index 0585162..95a07d2 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -8,7 +8,6 @@
 
 #include <regex.h>
 #include <assert.h>
 
 #include <regex.h>
 #include <assert.h>
-#include <sys/time.h>
 
 #include "para.h"
 #include "ipc.h"
 
 #include "para.h"
 #include "ipc.h"
@@ -68,9 +67,9 @@ static inline void call_post_select(struct sched *s, struct task *t)
        struct timeval t1, t2, diff;
        unsigned long pst;
 
        struct timeval t1, t2, diff;
        unsigned long pst;
 
-       gettimeofday(&t1, NULL);
+       clock_get_realtime(&t1);
        t->post_select(s, t);
        t->post_select(s, t);
-       gettimeofday(&t2, NULL);
+       clock_get_realtime(&t2);
        tv_diff(&t1, &t2, &diff);
        pst = tv2ms(&diff);
        if (pst > 50)
        tv_diff(&t1, &t2, &diff);
        pst = tv2ms(&diff);
        if (pst > 50)
@@ -120,7 +119,7 @@ again:
        FD_ZERO(&s->wfds);
        s->select_timeout = s->default_timeout;
        s->max_fileno = -1;
        FD_ZERO(&s->wfds);
        s->select_timeout = s->default_timeout;
        s->max_fileno = -1;
-       gettimeofday(now, NULL);
+       clock_get_realtime(now);
        sched_preselect(s);
        ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
                &s->select_timeout);
        sched_preselect(s);
        ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
                &s->select_timeout);
@@ -136,7 +135,7 @@ again:
                FD_ZERO(&s->rfds);
                FD_ZERO(&s->wfds);
        }
                FD_ZERO(&s->rfds);
                FD_ZERO(&s->wfds);
        }
-       gettimeofday(now, NULL);
+       clock_get_realtime(now);
        sched_post_select(s);
        if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
                return 0;
        sched_post_select(s);
        if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
                return 0;
diff --git a/sched.h b/sched.h
index 7a5a4f8..021474a 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -76,7 +76,7 @@ struct task {
  * This is set by the scheduler at the beginning of its main loop.  It may be
  * used (read-only) from everywhere. As none of the functions called by the
  * scheduler are allowed to block, this value should be accurate enough so that
  * This is set by the scheduler at the beginning of its main loop.  It may be
  * used (read-only) from everywhere. As none of the functions called by the
  * scheduler are allowed to block, this value should be accurate enough so that
- * there is no need to call gettimeofday() directly.
+ * there is no need to call clock_gettime() directly.
  */
 extern struct timeval *now;
 
  */
 extern struct timeval *now;
 
index 2595d9c..57f0c26 100644 (file)
--- a/server.c
+++ b/server.c
@@ -67,7 +67,6 @@
  */
 
 #include <signal.h>
  */
 
 #include <signal.h>
-#include <sys/time.h>
 #include <regex.h>
 #include <osl.h>
 
 #include <regex.h>
 #include <osl.h>
 
@@ -493,7 +492,7 @@ static void server_init(int argc, char **argv)
        log_welcome("para_server");
        init_ipc_or_die(); /* init mmd struct and mmd->lock */
        /* make sure, the global now pointer is uptodate */
        log_welcome("para_server");
        init_ipc_or_die(); /* init mmd struct and mmd->lock */
        /* make sure, the global now pointer is uptodate */
-       gettimeofday(now, NULL);
+       clock_get_realtime(now);
        set_server_start_time(now);
        init_user_list(user_list_file);
        /* become daemon */
        set_server_start_time(now);
        init_user_list(user_list_file);
        /* become daemon */
index c001b15..e5de147 100644 (file)
--- a/string.c
+++ b/string.c
@@ -6,7 +6,6 @@
 
 /** \file string.c Memory allocation and string handling functions. */
 
 
 /** \file string.c Memory allocation and string handling functions. */
 
-#include <sys/time.h> /* gettimeofday */
 #include <pwd.h>
 #include <sys/utsname.h> /* uname() */
 #include <string.h>
 #include <pwd.h>
 #include <sys/utsname.h> /* uname() */
 #include <string.h>
diff --git a/time.c b/time.c
index 18b5a35..6f6dd49 100644 (file)
--- a/time.c
+++ b/time.c
@@ -191,3 +191,40 @@ void compute_chunk_time(long unsigned chunk_num,
        tv_scale(chunk_num, chunk_tv, &tmp);
        tv_add(&tmp, stream_start, result);
 }
        tv_scale(chunk_num, chunk_tv, &tmp);
        tv_add(&tmp, stream_start, result);
 }
+
+/**
+ * Retrieve the time of the realtime clock.
+ *
+ * \param tv Where to store the result.
+ *
+ * Gets the current value of the system-wide real-time clock (identified by id
+ * \p CLOCK_REALTIME). If \a tv is \p NULL, the value is stored in a static
+ * buffer, otherwise it is stored at the location given by \a tv.
+ *
+ * \return This function aborts on errors. On success it returns a pointer to
+ * memory containing the current time.
+ *
+ * \sa clock_gettime(2), gettimeofday(2).
+ */
+struct timeval *clock_get_realtime(struct timeval *tv)
+{
+       static struct timeval user_friendly;
+
+       if (!tv)
+               tv = &user_friendly;
+#ifdef HAVE_CLOCK_GETTIME
+       {
+               struct timespec t;
+               int ret;
+
+               ret = clock_gettime(CLOCK_REALTIME, &t);
+               assert(ret == 0);
+               tv->tv_sec = t.tv_sec;
+               tv->tv_usec = t.tv_nsec / 1000;
+       }
+#else
+       #include <sys/time.h>
+       gettimeofday(tv, NULL);
+#endif /* HAVE_CLOCK_GETTIME */
+       return tv;
+}
index b41c0eb..b1da316 100644 (file)
@@ -8,7 +8,6 @@
 
 
 #include <regex.h>
 
 
 #include <regex.h>
-#include <sys/time.h>
 #include <sys/socket.h>
 #include <netinet/udp.h>
 #include <net/if.h>
 #include <sys/socket.h>
 #include <netinet/udp.h>
 #include <net/if.h>
index 20f9df4..ce8d7e8 100644 (file)
@@ -17,7 +17,6 @@
 
 #define _XOPEN_SOURCE 600
 
 
 #define _XOPEN_SOURCE 600
 
-#include <sys/time.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>