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