From 24758c5f17064273786e704b84ceff56c234e347 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 31 Mar 2013 02:03:04 +0000 Subject: [PATCH] Replace gettimeofday() by clock_gettime(). 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. --- Makefile.in | 2 ++ afh.c | 1 - afh_common.c | 1 - alsa_write.c | 1 - command.c | 3 +-- configure.ac | 12 ++++++++++++ daemon.c | 3 +-- file_write.c | 5 +---- para.h | 1 + play.c | 3 +-- sched.c | 9 ++++----- sched.h | 2 +- server.c | 3 +-- string.c | 1 - time.c | 37 +++++++++++++++++++++++++++++++++++++ udp_send.c | 1 - wmadec_filter.c | 1 - 17 files changed, 62 insertions(+), 24 deletions(-) diff --git a/Makefile.in b/Makefile.in index d577ce29..7ccd970d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -79,6 +79,8 @@ CPPFLAGS += -I/usr/local/include CPPFLAGS += -I$(cmdline_dir) CPPFLAGS += @osl_cppflags@ +LDFLAGS += @clock_gettime_ldflags@ + man_pages := $(patsubst %, $(man_dir)/%.1, @executables@) autocrap := config.h.in configure diff --git a/afh.c b/afh.c index aab664c2..4c65d7c1 100644 --- a/afh.c +++ b/afh.c @@ -7,7 +7,6 @@ /** \file afh.c Paraslash's standalone audio format handler tool. */ #include -#include #include "para.h" #include "string.h" diff --git a/afh_common.c b/afh_common.c index 5c866c1f..6c161a7c 100644 --- a/afh_common.c +++ b/afh_common.c @@ -7,7 +7,6 @@ /** \file afh_common.c Common audio format handler functions. */ #include /* mmap */ -#include /* gettimeofday */ #include #include diff --git a/alsa_write.c b/alsa_write.c index ba844db2..43f0811a 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "para.h" #include "fd.h" diff --git a/command.c b/command.c index aaaaaecf..ec822c82 100644 --- a/command.c +++ b/command.c @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -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); } - gettimeofday(¤t_time, NULL); + clock_get_realtime(¤t_time); /* * The calls to WRITE_STATUS_ITEM() below never fail because * b->max_size is zero (unlimited), see para_printf(). However, clang diff --git a/configure.ac b/configure.ac index 4512c6fd..6f0fbc0c 100644 --- a/configure.ac +++ b/configure.ac @@ -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() +################################################################## 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" diff --git a/daemon.c b/daemon.c index 29b00ed2..18ad1568 100644 --- a/daemon.c +++ b/daemon.c @@ -10,7 +10,6 @@ #include #include /* getgrnam() */ #include -#include #include #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; - 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]; diff --git a/file_write.c b/file_write.c index a12867d5..3f764766 100644 --- a/file_write.c +++ b/file_write.c @@ -8,7 +8,6 @@ #include #include -#include #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(); - 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); diff --git a/para.h b/para.h index 4208ae6a..edab4871 100644 --- 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); +struct timeval *clock_get_realtime(struct timeval *tv); /** The enum of all status items. */ enum status_items {STATUS_ITEM_ENUM NUM_STAT_ITEMS}; diff --git a/play.c b/play.c index cca203b5..fb72bae4 100644 --- a/play.c +++ b/play.c @@ -7,7 +7,6 @@ /** \file play.c Paraslash's standalone player. */ #include -#include #include #include @@ -1255,7 +1254,7 @@ int main(int argc, char *argv[]) filter_init(); writer_init(); - gettimeofday(now, NULL); + clock_get_realtime(now); sched.default_timeout.tv_sec = 5; parse_config_or_die(argc, argv); diff --git a/sched.c b/sched.c index 05851621..95a07d29 100644 --- a/sched.c +++ b/sched.c @@ -8,7 +8,6 @@ #include #include -#include #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; - gettimeofday(&t1, NULL); + clock_get_realtime(&t1); t->post_select(s, t); - gettimeofday(&t2, NULL); + clock_get_realtime(&t2); 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; - 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); @@ -136,7 +135,7 @@ again: 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; diff --git a/sched.h b/sched.h index 7a5a4f86..021474a2 100644 --- 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 - * there is no need to call gettimeofday() directly. + * there is no need to call clock_gettime() directly. */ extern struct timeval *now; diff --git a/server.c b/server.c index 2595d9c4..57f0c26e 100644 --- a/server.c +++ b/server.c @@ -67,7 +67,6 @@ */ #include -#include #include #include @@ -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 */ - gettimeofday(now, NULL); + clock_get_realtime(now); set_server_start_time(now); init_user_list(user_list_file); /* become daemon */ diff --git a/string.c b/string.c index c001b15d..e5de147c 100644 --- a/string.c +++ b/string.c @@ -6,7 +6,6 @@ /** \file string.c Memory allocation and string handling functions. */ -#include /* gettimeofday */ #include #include /* uname() */ #include diff --git a/time.c b/time.c index 18b5a35f..6f6dd49e 100644 --- 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); } + +/** + * 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 + gettimeofday(tv, NULL); +#endif /* HAVE_CLOCK_GETTIME */ + return tv; +} diff --git a/udp_send.c b/udp_send.c index b41c0ebf..b1da3167 100644 --- a/udp_send.c +++ b/udp_send.c @@ -8,7 +8,6 @@ #include -#include #include #include #include diff --git a/wmadec_filter.c b/wmadec_filter.c index 20f9df44..ce8d7e87 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -17,7 +17,6 @@ #define _XOPEN_SOURCE 600 -#include #include #include #include -- 2.39.5