[corosync] [PATCH] Support for monotime timer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch solves problems with aisexec and big time changes, by using
clock_gettime where it make sense.

On systems without clock_gettime, availability and value of
_POSIX_MONOTONIC_CLOCK is tested, and non supported systems
uses old behaviour of gettimeofday.

Signed-off-by: Jan Friesse <jfriesse@xxxxxxxxxx>
---
 branches/whitetank/Makefile.inc |    9 ++++
 branches/whitetank/exec/timer.h |    2 +-
 branches/whitetank/exec/tlist.h |   80 +++++++++++++++++++++++++++++++++------
 3 files changed, 78 insertions(+), 13 deletions(-)

diff --git a/branches/whitetank/Makefile.inc b/branches/whitetank/Makefile.inc
index c94e820..8d4f976 100644
--- a/branches/whitetank/Makefile.inc
+++ b/branches/whitetank/Makefile.inc
@@ -62,6 +62,11 @@ ifndef OPENAIS_BUILD
 	OPENAIS_BUILD=RELEASE
 endif
 
+# OPENAIS_RT can be defined to 1 to build with librt
+ifndef LINK_WITH_RT
+	LINK_WITH_RT=1
+endif
+
 # OPENAIS_PROFILE
 
 # default CFLAGS, LDFLAGS
@@ -95,6 +100,10 @@ ifdef OPENAIS_PROFILE
 	LDFLAGS += -pg
 endif
 
+ifeq (${LINK_WITH_RT}, 1)
+	LDFLAGS += -lrt
+endif
+
 # platform specific CFLAGS, LDFLAGS
 #
 ifeq (${OPENAIS_COMPAT}, LINUX) 
diff --git a/branches/whitetank/exec/timer.h b/branches/whitetank/exec/timer.h
index 45dd74f..6ddf159 100644
--- a/branches/whitetank/exec/timer.h
+++ b/branches/whitetank/exec/timer.h
@@ -42,7 +42,7 @@ extern void openais_timer_init (
         void (*serialize_unlock) (void));
 
 extern int openais_timer_add_duration (
-	unsigned long long nanoseconds_in_future,
+	unsigned long long nanosec_duration,
 	void *data,
 	void (*timer_fn) (void *data),
 	openais_timer_handle *handle);
diff --git a/branches/whitetank/exec/tlist.h b/branches/whitetank/exec/tlist.h
index 6143e22..b549247 100644
--- a/branches/whitetank/exec/tlist.h
+++ b/branches/whitetank/exec/tlist.h
@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/param.h>
+#include <unistd.h>
 
 #include "../include/list.h"
 
@@ -51,6 +52,13 @@
 
 typedef void * timer_handle;
 
+#define TIMERLIST_MS_IN_SEC   1000ULL
+#define TIMERLIST_US_IN_SEC   1000000ULL
+#define TIMERLIST_NS_IN_SEC   1000000000ULL
+#define TIMERLIST_US_IN_MSEC  1000ULL
+#define TIMERLIST_NS_IN_MSEC  1000000ULL
+#define TIMERLIST_NS_IN_USEC  1000ULL
+
 struct timerlist {
 	struct list_head timer_head;
 	struct list_head *timer_iter;
@@ -58,7 +66,8 @@ struct timerlist {
 
 struct timerlist_timer {
 	struct list_head list;
-	unsigned long long nano_from_epoch;
+	unsigned long long expire_time;
+	int is_absolute_timer;
 	void (*timer_fn)(void *data);
 	void *data;
 	timer_handle handle_addr;
@@ -75,10 +84,46 @@ static inline unsigned long long timerlist_nano_from_epoch (void)
 	struct timeval time_from_epoch;
 	gettimeofday (&time_from_epoch, 0);
 
-	nano_from_epoch = ((time_from_epoch.tv_sec * 1000000000ULL) + (time_from_epoch.tv_usec * 1000ULL));
+	nano_from_epoch = ((time_from_epoch.tv_sec * TIMERLIST_NS_IN_SEC) +
+		(time_from_epoch.tv_usec * TIMERLIST_NS_IN_USEC));
+
 	return (nano_from_epoch);
 }
 
+#if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+static inline unsigned long long timerlist_nano_current_get (void)
+{
+	unsigned long long nano_monotonic;
+	struct timespec ts;
+
+	clock_gettime (CLOCK_MONOTONIC, &ts);
+
+	nano_monotonic = (ts.tv_sec * TIMERLIST_NS_IN_SEC) + (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 = TIMERLIST_NS_IN_SEC / ((ts.tv_sec * TIMERLIST_NS_IN_SEC) + ts.tv_nsec);
+
+	return (nano_monotonic_hz);
+}
+#else
+#warning "Your system doesn't support monotonic timer. gettimeofday will be used"
+static inline unsigned long long timerlist_nano_current_get (void)
+{
+	return (timerlist_nano_from_epoch ());
+}
+
+static inline unsigned long long timerlist_nano_monotonic_hz (void) {
+	return HZ;
+}
+#endif
+
 static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_timer *timer)
 {
 	struct list_head *timer_list = 0;
@@ -92,7 +137,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 */
@@ -117,7 +162,8 @@ static inline int timerlist_add_absolute (struct timerlist *timerlist,
 		return (-1);
 	}
 	
-	timer->nano_from_epoch = nano_from_epoch;
+	timer->expire_time = nano_from_epoch;
+	timer->is_absolute_timer = 1;
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
@@ -141,7 +187,8 @@ static inline int timerlist_add_duration (struct timerlist *timerlist,
 		return (-1);
 	}
 	
-	timer->nano_from_epoch = timerlist_nano_from_epoch() + nano_duration;
+	timer->expire_time = timerlist_nano_current_get () + nano_duration;
+	timer->is_absolute_timer = 0;
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
@@ -191,7 +238,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;
 
 	/*
@@ -204,17 +251,21 @@ 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();
+	if (timer_from_list->is_absolute_timer) {
+		current_time = timerlist_nano_from_epoch ();
+	} else {
+		current_time = timerlist_nano_current_get ();
+	}
 
 	/*
 	 * 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) / TIMERLIST_NS_IN_MSEC) +
 		(1000 / HZ);
 	return (msec_duration_to_expire);
 }
@@ -225,9 +276,12 @@ 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_from_epoch;
+	unsigned long long current_monotonic_time;
+	unsigned long long current_time;
 
-	nano_from_epoch = timerlist_nano_from_epoch();
+	current_monotonic_time = timerlist_nano_current_get ();
+	current_time_from_epoch = current_time = timerlist_nano_from_epoch ();
 
 	for (timerlist->timer_iter = timerlist->timer_head.next;
 		timerlist->timer_iter != &timerlist->timer_head;) {
@@ -235,7 +289,9 @@ 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) {
+		current_time = (timer_from_list->is_absolute_timer ? current_time_from_epoch : current_monotonic_time);
+
+		if (timer_from_list->expire_time < current_time) {
 			timerlist->timer_iter = timerlist->timer_iter->next;
 
 			timerlist_pre_dispatch (timerlist, timer_from_list);
-- 
1.7.4.1

_______________________________________________
discuss mailing list
discuss@xxxxxxxxxxxx
http://lists.corosync.org/mailman/listinfo/discuss


[Index of Archives]     [Linux Clusters]     [Corosync Project]     [Linux USB Devel]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Linux Kernel]     [Linux SCSI]     [X.Org]

  Powered by Linux