Patch should solve problem with ntp and corosync (what it really does)
by using clock_gettime.

I tried to find EVERY appearance of gettimeofday and where it makes
sense (so basically, where this value is used as timer) convert to call
clock_gettime.

Patch modifies configure.ac to detect if clock_gettime and
CLOCK_MONOTONIC exists on system. If not, gettimeofday will be used (so
you will get old behavior).

Comments are welcomed.

Regards,
  Honza
commit 5d2bd8a98f378452a0a7737b7bc990a0c22a2b2f
Author: Jan Friesse <jfrie...@redhat.com>
Date:   Tue Jul 21 15:33:52 2009 +0200

    Support for monotime timer
    
    This patch should solve problems with corosync and ntp, by using
    clock_gettime where is available (this is why configure.ac is modified),
    and when using this functions make sense.

diff --git a/trunk/configure.ac b/trunk/configure.ac
index bff779a..2d5b5bc 100644
--- a/trunk/configure.ac
+++ b/trunk/configure.ac
@@ -107,6 +107,26 @@ AC_CHECK_FUNCS([alarm alphasort atexit bzero dup2 endgrent endpwent fcntl \
 		pthread_spin_unlock pthread_setschedparam \
 		sched_get_priority_max sched_setscheduler])
 
+# Check for time souce to use (monotonic in function clock_gettime, or gettimeofday)
+if test "x$USE_GETTIMEOFDAY" = "x"
+then
+    AC_CHECK_FUNCS([clock_gettime],
+	dnl clock_gettime() found
+	[AC_CHECK_DECLS([CLOCK_MONOTONIC],AC_DEFINE([USE_CLOCK_MONOTONIC],,[Clock type to use]),
+	    dnl no CLOCK_MONOTONIC
+	    [AC_CHECK_FUNCS([gettimeofday],AC_DEFINE([USE_GETTIMEOFDAY],,[Clock type to use]),AC_MSG_ERROR([No suitable clock found]))],
+	dnl for CLOCK_MONOTONIC
+	[#include <time.h>])],
+	dnl clock_gettime() not found
+	[AC_CHECK_FUNCS([gettimeofday],AC_DEFINE([USE_GETTIMEOFDAY],,[Clock type to use]),AC_MSG_ERROR([No suitable clock found]))]
+    )
+else
+    AC_MSG_NOTICE([Forced to use gettimeofday()])
+    AC_CHECK_FUNCS([gettimeofday],AC_DEFINE([USE_GETTIMEOFDAY],,[Clock type to use]),AC_MSG_ERROR([No suitable clock found]))
+    AC_CHECK_FUNCS([clock_gettime])
+    AC_CHECK_TYPES([clockid_t])
+fi
+
 AC_CONFIG_FILES([Makefile
 		 exec/Makefile
 		 include/Makefile
diff --git a/trunk/exec/timer.c b/trunk/exec/timer.c
index 69f9a95..e5a419a 100644
--- a/trunk/exec/timer.c
+++ b/trunk/exec/timer.c
@@ -174,7 +174,7 @@ int corosync_timer_init (
 }
 
 int corosync_timer_add_absolute (
-	unsigned long long nanosec_from_epoch,
+	unsigned long long expire_time,
 	void *data,
 	void (*timer_fn) (void *data),
 	timer_handle *handle)
@@ -193,7 +193,7 @@ int corosync_timer_add_absolute (
 		&timers_timerlist,
 		timer_fn,
 		data,
-		nanosec_from_epoch,
+		expire_time,
 		handle);
 
 	if (unlock) {
diff --git a/trunk/exec/timer.h b/trunk/exec/timer.h
index 3df9d36..9f13170 100644
--- a/trunk/exec/timer.h
+++ b/trunk/exec/timer.h
@@ -49,7 +49,7 @@ extern int corosync_timer_add_duration (
 	corosync_timer_handle *handle);
 
 extern int corosync_timer_add_absolute (
-	unsigned long long nanoseconds_from_epoch,
+	unsigned long long expire_time,
 	void *data,
 	void (*timer_fn) (void *data),
 	corosync_timer_handle *handle);
diff --git a/trunk/exec/tlist.h b/trunk/exec/tlist.h
index 263c8d7..1a08398 100644
--- a/trunk/exec/tlist.h
+++ b/trunk/exec/tlist.h
@@ -61,7 +61,7 @@ struct timerlist {
 
 struct timerlist_timer {
 	struct list_head list;
-	unsigned long long nano_from_epoch;
+	unsigned long long expire_time;
 	void (*timer_fn)(void *data);
 	void *data;
 	timer_handle handle_addr;
@@ -82,6 +82,30 @@ static inline unsigned long long timerlist_nano_from_epoch (void)
 	return (nano_from_epoch);
 }
 
+#ifdef USE_CLOCK_MONOTONIC
+static inline unsigned long long timerlist_nano_monotonic_time (void)
+{
+	unsigned long long nano_monotonic;
+	struct timespec ts;
+
+	clock_gettime (CLOCK_MONOTONIC, &ts);
+
+	nano_monotonic = (ts.tv_sec * 1000000000ULL) + (unsigned long long )ts.tv_nsec;
+	return (nano_monotonic);
+}
+
+static inline unsigned long long timerlist_nano_monotonic_hz (void) {
+	unsigned long long nano_monotonic_hz;
+	struct timespec ts;
+
+	clock_getres (CLOCK_MONOTONIC, &ts);
+
+	nano_monotonic_hz = ts.tv_sec + 1000000000ULL / (unsigned long long )ts.tv_nsec;
+
+	return (nano_monotonic_hz);
+}
+#endif
+
 static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_timer *timer)
 {
 	struct list_head *timer_list = 0;
@@ -95,7 +119,7 @@ static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_
 		timer_from_list = list_entry (timer_list,
 			struct timerlist_timer, list);
 
-		if (timer_from_list->nano_from_epoch > timer->nano_from_epoch) {
+		if (timer_from_list->expire_time > timer->expire_time) {
 			list_add (&timer->list, timer_list->prev);
 			found = 1;
 			break; /* for timer iteration */
@@ -109,7 +133,7 @@ static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_
 static inline int timerlist_add_absolute (struct timerlist *timerlist,
 	void (*timer_fn) (void *data),
 	void *data,
-	unsigned long long nano_from_epoch,
+	unsigned long long expire_time,
 	timer_handle *handle)
 {
 	struct timerlist_timer *timer;
@@ -120,7 +144,7 @@ static inline int timerlist_add_absolute (struct timerlist *timerlist,
 		return (-1);
 	}
 
-	timer->nano_from_epoch = nano_from_epoch;
+	timer->expire_time = expire_time;
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
@@ -144,7 +168,11 @@ static inline int timerlist_add_duration (struct timerlist *timerlist,
 		return (-1);
 	}
 
-	timer->nano_from_epoch = timerlist_nano_from_epoch() + nano_duration;
+#ifdef USE_CLOCK_MONOTONIC
+	timer->expire_time= timerlist_nano_monotonic_time() + nano_duration;
+#else
+	timer->expire_time = timerlist_nano_from_epoch() + nano_duration;
+#endif
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
@@ -177,7 +205,7 @@ static inline unsigned long long timerlist_expire_time (struct timerlist *timerl
 {
 	struct timerlist_timer *timer = (struct timerlist_timer *)_timer_handle;
 
-	return (timer->nano_from_epoch);
+	return (timer->expire_time);
 }
 
 static inline void timerlist_pre_dispatch (struct timerlist *timerlist, timer_handle _timer_handle)
@@ -202,7 +230,7 @@ static inline void timerlist_post_dispatch (struct timerlist *timerlist, timer_h
 static inline unsigned long long timerlist_msec_duration_to_expire (struct timerlist *timerlist)
 {
 	struct timerlist_timer *timer_from_list;
-	volatile unsigned long long nano_from_epoch;
+	volatile unsigned long long current_time;
 	volatile unsigned long long msec_duration_to_expire;
 
 	/*
@@ -215,16 +243,19 @@ static inline unsigned long long timerlist_msec_duration_to_expire (struct timer
 	timer_from_list = list_entry (timerlist->timer_head.next,
 		struct timerlist_timer, list);
 
-	nano_from_epoch = timerlist_nano_from_epoch();
-
+#ifdef USE_CLOCK_MONOTONIC
+	current_time = timerlist_nano_monotonic_time();
+#else
+	current_time = timerlist_nano_from_epoch();
+#endif
 	/*
 	 * timer at head of list is expired, zero msecs required
 	 */
-	if (timer_from_list->nano_from_epoch < nano_from_epoch) {
+	if (timer_from_list->expire_time < current_time) {
 		return (0);
 	}
 
-	msec_duration_to_expire = ((timer_from_list->nano_from_epoch - nano_from_epoch) / 1000000ULL) +
+	msec_duration_to_expire = ((timer_from_list->expire_time - current_time) / 1000000ULL) +
 		(1000 / HZ);
 	return (msec_duration_to_expire);
 }
@@ -235,9 +266,13 @@ static inline unsigned long long timerlist_msec_duration_to_expire (struct timer
 static inline void timerlist_expire (struct timerlist *timerlist)
 {
 	struct timerlist_timer *timer_from_list;
-	unsigned long long nano_from_epoch;
+	unsigned long long current_time;
 
-	nano_from_epoch = timerlist_nano_from_epoch();
+#ifdef USE_CLOCK_MONOTONIC
+	current_time = timerlist_nano_monotonic_time();
+#else
+	current_time = timerlist_nano_from_epoch();
+#endif
 
 	for (timerlist->timer_iter = timerlist->timer_head.next;
 		timerlist->timer_iter != &timerlist->timer_head;) {
@@ -245,7 +280,7 @@ static inline void timerlist_expire (struct timerlist *timerlist)
 		timer_from_list = list_entry (timerlist->timer_iter,
 			struct timerlist_timer, list);
 
-		if (timer_from_list->nano_from_epoch < nano_from_epoch) {
+		if (timer_from_list->expire_time < current_time) {
 			timerlist->timer_iter = timerlist->timer_iter->next;
 
 			timerlist_pre_dispatch (timerlist, timer_from_list);
diff --git a/trunk/exec/totemsrp.c b/trunk/exec/totemsrp.c
index c5b5235..a03bd55 100644
--- a/trunk/exec/totemsrp.c
+++ b/trunk/exec/totemsrp.c
@@ -689,6 +689,19 @@ static unsigned int main_msgs_missing (void)
 	return (0);
 }
 
+static inline void get_monotonic_timeofday (struct timeval *tv)
+{
+#ifdef USE_CLOCK_MONOTONIC
+	struct timespec ts;
+	clock_gettime (CLOCK_MONOTONIC, &ts);
+
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec / 1000ULL;
+#else
+	gettimeofday (&tv, NULL);
+#endif
+}
+
 static int pause_flush (struct totemsrp_instance *instance)
 {
 	struct timeval now;
@@ -696,7 +709,8 @@ static int pause_flush (struct totemsrp_instance *instance)
 	uint64_t timestamp_msec;
 	int res = 0;
 
-	gettimeofday (&now, NULL);
+	get_monotonic_timeofday (&now);
+
         now_msec = ((now.tv_sec * 1000ULL) + (now.tv_usec / 1000ULL));
         timestamp_msec = ((instance->pause_timestamp.tv_sec * 1000ULL) + (instance->pause_timestamp.tv_usec/1000ULL));
 
@@ -845,7 +859,7 @@ int totemsrp_initialize (
 	instance->totemsrp_confchg_fn = confchg_fn;
 	instance->use_heartbeat = 1;
 
-	gettimeofday (&instance->pause_timestamp, NULL);
+	get_monotonic_timeofday (&instance->pause_timestamp);
 
 	if ( totem_config->heartbeat_failures_allowed == 0 ) {
 		log_printf (instance->totemsrp_log_level_debug,
@@ -1524,7 +1538,7 @@ static void timer_function_pause_timeout (void *data)
 {
 	struct totemsrp_instance *instance = data;
 
-	gettimeofday (&instance->pause_timestamp, NULL);
+	get_monotonic_timeofday (&instance->pause_timestamp);
 	reset_pause_timeout (instance);
 }
 
@@ -3311,7 +3325,7 @@ static int message_handler_orf_token (
 	struct timeval tv_current;
 	struct timeval tv_diff;
 
-	gettimeofday (&tv_current, NULL);
+	get_monotonic_timeofday (&tv_current);
 	timersub (&tv_current, &tv_old, &tv_diff);
 	memcpy (&tv_old, &tv_current, sizeof (struct timeval));
 
@@ -3555,7 +3569,7 @@ static int message_handler_orf_token (
 			token_send (instance, token, forward_token);
 
 #ifdef GIVEINFO
-			gettimeofday (&tv_current, NULL);
+			get_monotonic_timeofday (&tv_current);
 			timersub (&tv_current, &tv_old, &tv_diff);
 			memcpy (&tv_old, &tv_current, sizeof (struct timeval));
 			log_printf (instance->totemsrp_log_level_debug,
diff --git a/trunk/services/pload.c b/trunk/services/pload.c
index cf82bbc..0e6e4b5 100644
--- a/trunk/services/pload.c
+++ b/trunk/services/pload.c
@@ -349,6 +349,19 @@ struct timeval tv2;
 struct timeval tv_elapsed;
 int last_msg_no = 0;
 
+static inline void get_monotonic_timeofday (struct timeval *tv)
+{
+#ifdef USE_CLOCK_MONOTONIC
+	struct timespec ts;
+	clock_gettime (CLOCK_MONOTONIC, &ts);
+
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec / 1000ULL;
+#else
+	gettimeofday (&tv, NULL);
+#endif
+}
+
 static void message_handler_req_exec_pload_mcast (
 	const void *msg,
 	unsigned int nodeid)
@@ -357,11 +370,11 @@ static void message_handler_req_exec_pload_mcast (
 
 	last_msg_no = pload_mcast->msg_code;
 	if (msgs_delivered == 0) {
-		gettimeofday (&tv1, NULL);
+		get_monotonic_timeofday (&tv1);
 	}
 	msgs_delivered += 1;
 	if (msgs_delivered == msgs_wanted) {
-		gettimeofday (&tv2, NULL);
+		get_monotonic_timeofday (&tv2);
 		timersub (&tv2, &tv1, &tv_elapsed);
 	        printf ("%5d Writes ", msgs_delivered);
 		printf ("%5d bytes per write ", msg_size);
diff --git a/trunk/services/votequorum.c b/trunk/services/votequorum.c
index 79855bf..b5d82b6 100644
--- a/trunk/services/votequorum.c
+++ b/trunk/services/votequorum.c
@@ -1305,6 +1305,19 @@ static void message_handler_req_lib_votequorum_leaving (void *conn, const void *
 	LEAVE();
 }
 
+static inline void get_monotonic_timeofday (struct timeval *tv)
+{
+#ifdef USE_CLOCK_MONOTONIC
+	struct timespec ts;
+	clock_gettime (CLOCK_MONOTONIC, &ts);
+
+	tv->tv_sec = ts.tv_sec;
+	tv->tv_usec = ts.tv_nsec / 1000ULL;
+#else
+	gettimeofday (&tv, NULL);
+#endif
+}
+
 static void quorum_device_timer_fn(void *arg)
 {
 	struct timeval now;
@@ -1312,7 +1325,7 @@ static void quorum_device_timer_fn(void *arg)
 	ENTER();
 	if (!quorum_device || quorum_device->state == NODESTATE_DEAD)
 		return;
-	gettimeofday(&now, NULL);
+	get_monotonic_timeofday (&now);
 	if (quorum_device->last_hello.tv_sec + quorumdev_poll/1000 < now.tv_sec) {
 		quorum_device->state = NODESTATE_DEAD;
 		log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device\n");
@@ -1395,7 +1408,7 @@ static void message_handler_req_lib_votequorum_qdisk_poll (void *conn,
 
 	if (quorum_device) {
 		if (req_lib_votequorum_qdisk_poll->state) {
-			gettimeofday(&quorum_device->last_hello, NULL);
+			get_monotonic_timeofday (&quorum_device->last_hello);
 			if (quorum_device->state == NODESTATE_DEAD) {
 				quorum_device->state = NODESTATE_MEMBER;
 				recalculate_quorum(0, 0);
_______________________________________________
Openais mailing list
Openais@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to