Re: [corosync] [PATCH] Support for monotime timer

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

 



On 09/21/2011 08:51 AM, Jan Friesse wrote:
> 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>

Reviewed-by: Steven Dake <sdake@xxxxxxxxxx>

great work Honza
-steve

> ---
>  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);

_______________________________________________
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