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 d577ce295c540ecc91ce8134a33a4d62db070168..7ccd970d7232bca1d4828057cc3dbb367ec8b7f8 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 aab664c260340efb1663c872d3e13387274ea88e..4c65d7c1f76bdc4b054461127d14b9547881d6f7 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 5c866c1fdef07baf87c3cd6148619b8e8c13cb83..6c161a7c7ea2a30c0abb6a87c91ef5075d5dbf06 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 ba844db2b2b419363b01d1d1d21e28411ae92b37..43f0811a58be4c5835a5109ffe8ff34f15df1e2d 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 aaaaaecf02084c188482214bebd3df433c54e72b..ec822c82978d78649b6641d2206f41db44ab3bd7 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 4512c6fd38f7209aad203c14cfe31dc66d4e1d56..6f0fbc0c0423190acc9600dd4507afd9ccac5e23 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 29b00ed2aefd4e94201d8ce87f2fb1e429e24f12..18ad1568fbb5074bbddd60bc99835bb49967d24e 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 a12867d5d24830e0b9b2050aff957a42eff3cbf0..3f764766c39964a2f2736415a27cf56c4bad74ec 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 4208ae6a9083a0e2e3a956c163808db1b72a761f..edab4871a03441dc1756054bfe0850b2a4e10c22 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 cca203b5d393aa95dc50d0e7df1ffcceb0180420..fb72bae43e3a921f8acc6d85082e29d0ed19f20f 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 0585162142be5238a7fa463a64f05fa192a6713d..95a07d29a0876c1ba1f737c29e36be63bc0074f1 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 7a5a4f867b41fd1e661da8cf4b11032d8506fddc..021474a21a5303d405d91b985a0a70de1d198801 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 2595d9c4edaf649e9843150697855cbfe0c8d555..57f0c26ee36e046e4390157f49352bb0e7fccf70 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 c001b15d7dc8eca43d50af650a3dadf1693ed7ab..e5de147c65975c21018b3e0b6d30eb932e52edf1 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 18b5a35ffb678d80635887a14b88ba6fdaa12af9..6f6dd49e330df2f4d85565aa65ab1e02615abebd 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 b41c0ebf919ca902a6cafe55dd93471fe42aef46..b1da3167880c63895fd7d2d0f94a01feed620a1f 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 20f9df44b92b35061980d857f86c9ccee40b4bcd..ce8d7e87501211031c8d0d056ae48e0c05665338 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>