Browse Source

Change timers to add duration and absolute timers. Use nanoseconds since
epoch to track timers.


git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1378 fd59a12c-fef9-0310-b244-a6a79926bd2f

Steven Dake 18 years ago
parent
commit
64fb1d1c18
8 changed files with 141 additions and 262 deletions
  1. 10 31
      exec/aispoll.c
  2. 0 4
      exec/aispoll.h
  3. 26 40
      exec/ckpt.c
  4. 14 23
      exec/evt.c
  5. 0 38
      exec/ipc.c
  6. 29 16
      exec/timer.c
  7. 5 8
      exec/timer.h
  8. 57 102
      exec/tlist.h

+ 10 - 31
exec/aispoll.c

@@ -284,7 +284,7 @@ error_exit:
 
 
 int poll_timer_add (
 int poll_timer_add (
 	poll_handle handle,
 	poll_handle handle,
-	int msec_in_future, void *data,
+	int msec_duration, void *data,
 	void (*timer_fn) (void *data),
 	void (*timer_fn) (void *data),
 	poll_timer_handle *timer_handle_out)
 	poll_timer_handle *timer_handle_out)
 {
 {
@@ -303,8 +303,8 @@ int poll_timer_add (
 		res = -ENOENT;
 		res = -ENOENT;
 	}
 	}
 
 
-	timerlist_add_future (&poll_instance->timerlist,
-		timer_fn, data, msec_in_future, timer_handle_out);
+	timerlist_add_duration (&poll_instance->timerlist,
+		timer_fn, data, ((unsigned long long)msec_duration) * 1000000ULL, timer_handle_out);
 
 
 	hdb_handle_put (&poll_instance_database, handle);
 	hdb_handle_put (&poll_instance_database, handle);
 error_exit:
 error_exit:
@@ -336,37 +336,12 @@ error_exit:
 	return (res);
 	return (res);
 }
 }
 
 
-int poll_timer_delete_data (
-	poll_handle handle,
-	poll_timer_handle timer_handle) {
-	struct poll_instance *poll_instance;
-	int res = 0;
-
-	if (timer_handle == 0) {
-		return (0);
-	}
-	res = hdb_handle_get (&poll_instance_database, handle,
-		(void *)&poll_instance);
-	if (res != 0) {
-		res = -ENOENT;
-		goto error_exit;
-	}
-
-	timerlist_del_data (&poll_instance->timerlist, (void *)timer_handle);
-
-	hdb_handle_put (&poll_instance_database, handle);
-
-error_exit:
-	return (res);
-}
-
-
 int poll_run (
 int poll_run (
 	poll_handle handle)
 	poll_handle handle)
 {
 {
 	struct poll_instance *poll_instance;
 	struct poll_instance *poll_instance;
 	int i;
 	int i;
-	int timeout = -1;
+	unsigned long long expire_timeout_msec = -1;
 	int res;
 	int res;
 	int poll_entry_count;
 	int poll_entry_count;
 
 
@@ -382,11 +357,15 @@ int poll_run (
 				&poll_instance->poll_entries[i].ufd,
 				&poll_instance->poll_entries[i].ufd,
 				sizeof (struct pollfd));
 				sizeof (struct pollfd));
 		}
 		}
-		timeout = timerlist_timeout_msec (&poll_instance->timerlist);
+		expire_timeout_msec = timerlist_msec_duration_to_expire (&poll_instance->timerlist);
+
+		if (expire_timeout_msec != -1 && expire_timeout_msec > 0xFFFFFFFF) {
+			expire_timeout_msec = 0xFFFFFFFE;
+		}
 
 
 retry_poll:
 retry_poll:
 		res = poll (poll_instance->ufds,
 		res = poll (poll_instance->ufds,
-			poll_instance->poll_entry_count, timeout);
+			poll_instance->poll_entry_count, expire_timeout_msec);
 		if (errno == EINTR && res == -1) {
 		if (errno == EINTR && res == -1) {
 			goto retry_poll;
 			goto retry_poll;
 		} else
 		} else

+ 0 - 4
exec/aispoll.h

@@ -81,10 +81,6 @@ int poll_timer_delete (
 	poll_handle handle,
 	poll_handle handle,
 	poll_timer_handle timer_handle);
 	poll_timer_handle timer_handle);
 
 
-int poll_timer_delete_data (
-        poll_handle handle,
-        poll_timer_handle timer_handle);
-
 int poll_run (
 int poll_run (
 	poll_handle handle);
 	poll_handle handle);
 
 

+ 26 - 40
exec/ckpt.c

@@ -793,8 +793,8 @@ void clean_checkpoint_list(struct list_head *head)
 			log_printf (LOG_LEVEL_DEBUG, "clean_checkpoint_list: Starting timer to release checkpoint %s.\n",
 			log_printf (LOG_LEVEL_DEBUG, "clean_checkpoint_list: Starting timer to release checkpoint %s.\n",
 				checkpoint->name.value);
 				checkpoint->name.value);
 			openais_timer_delete (checkpoint->retention_timer);
 			openais_timer_delete (checkpoint->retention_timer);
-			openais_timer_add (
-				checkpoint->checkpoint_creation_attributes.retention_duration / 1000000,
+			openais_timer_add_duration (
+				checkpoint->checkpoint_creation_attributes.retention_duration,
 				checkpoint,
 				checkpoint,
 				timer_function_retention,
 				timer_function_retention,
 				&checkpoint->retention_timer);
 				&checkpoint->retention_timer);
@@ -952,6 +952,7 @@ static struct checkpoint_section *checkpoint_section_find (
 	else {
 	else {
 		log_printf (LOG_LEVEL_DEBUG, "Finding default checkpoint section\n");
 		log_printf (LOG_LEVEL_DEBUG, "Finding default checkpoint section\n");
 	}
 	}
+
 	for (checkpoint_section_list = checkpoint->sections_list_head.next;
 	for (checkpoint_section_list = checkpoint->sections_list_head.next;
 		checkpoint_section_list != &checkpoint->sections_list_head;
 		checkpoint_section_list != &checkpoint->sections_list_head;
 		checkpoint_section_list = checkpoint_section_list->next) {
 		checkpoint_section_list = checkpoint_section_list->next) {
@@ -995,14 +996,9 @@ static struct checkpoint_section *checkpoint_section_find (
 	return 0;
 	return 0;
 }
 }
 
 
-/*
- * defect 1112: We need to be able to call section release without
- * having to to delete the timer as in the case of release being called
- * from timer_function_section_expire where the expiry already takes care
- * of the timer and its data
- */
-void checkpoint_section_and_associate_timer_cleanup (struct checkpoint_section *section,int deleteTimer)
+void checkpoint_section_release (struct checkpoint_section *section)
 {
 {
+	log_printf (LOG_LEVEL_DEBUG, "checkpoint_section_release expiration timer = 0x%p\n", section->expiration_timer);
 	list_del (&section->list);
 	list_del (&section->list);
 	if (section->section_descriptor.section_id.id) {
 	if (section->section_descriptor.section_id.id) {
 		free (section->section_descriptor.section_id.id);
 		free (section->section_descriptor.section_id.id);
@@ -1010,21 +1006,9 @@ void checkpoint_section_and_associate_timer_cleanup (struct checkpoint_section *
 	if (section->section_data) {
 	if (section->section_data) {
 		free (section->section_data);
 		free (section->section_data);
 	}
 	}
-	/*
-	 * defect 1112 on a section release we need to delete the timer AND its data or memory leaks
-	 */
-	if (deleteTimer) {
-		openais_timer_delete_data (section->expiration_timer);
-	}
 	free (section);
 	free (section);
 }
 }
 
 
-void checkpoint_section_release (struct checkpoint_section *section)
-{
-	log_printf (LOG_LEVEL_DEBUG, "checkpoint_section_release expiration timer = 0x%p\n", section->expiration_timer);
-	checkpoint_section_and_associate_timer_cleanup (section, 1);
-}
-
 
 
 void checkpoint_release (struct checkpoint *checkpoint)
 void checkpoint_release (struct checkpoint *checkpoint)
 {
 {
@@ -1044,6 +1028,7 @@ void checkpoint_release (struct checkpoint *checkpoint)
 
 
 		list = list->next;
 		list = list->next;
 		checkpoint->section_count -= 1;
 		checkpoint->section_count -= 1;
+		openais_timer_delete (section->expiration_timer);
 		checkpoint_section_release (section);
 		checkpoint_section_release (section);
 	}
 	}
 	list_del (&checkpoint->list);
 	list_del (&checkpoint->list);
@@ -1515,12 +1500,8 @@ void timer_function_section_expire (void *data)
                         ckpt_id->ckpt_name.value);
                         ckpt_id->ckpt_name.value);
 
 
 	checkpoint->section_count -= 1;
 	checkpoint->section_count -= 1;
-	/*
-	 * defect id 1112 "memory leak in checkpoint service" Dont try
-	 * to delete the timer as the timer mechanism takes care of that.
-	 * Just delete the data after this call
-	 */
-	checkpoint_section_and_associate_timer_cleanup (checkpoint_section, 0);
+	checkpoint_section_release (checkpoint_section);
+
 free_mem :
 free_mem :
 	free (ckpt_id);
 	free (ckpt_id);
 
 
@@ -1588,11 +1569,13 @@ static void message_handler_req_exec_ckpt_checkpointclose (
 		release_checkpoint = 1;
 		release_checkpoint = 1;
 	} else
 	} else
 	if (checkpoint->reference_count == 0) {
 	if (checkpoint->reference_count == 0) {
-		openais_timer_add (
-			checkpoint->checkpoint_creation_attributes.retention_duration / 1000000,
-			checkpoint,
-			timer_function_retention,
-			&checkpoint->retention_timer);
+		if (checkpoint->checkpoint_creation_attributes.retention_duration != SA_TIME_END) {
+			openais_timer_add_duration (
+				checkpoint->checkpoint_creation_attributes.retention_duration,
+				checkpoint,
+				timer_function_retention,
+				&checkpoint->retention_timer);
+		}
 	}
 	}
 
 
 error_exit:
 error_exit:
@@ -1687,8 +1670,8 @@ static void message_handler_req_exec_ckpt_checkpointretentiondurationset (
 			if (checkpoint->reference_count == 0) {
 			if (checkpoint->reference_count == 0) {
 				openais_timer_delete (checkpoint->retention_timer);
 				openais_timer_delete (checkpoint->retention_timer);
 
 
-				openais_timer_add (
-					checkpoint->checkpoint_creation_attributes.retention_duration / 1000000,
+				openais_timer_add_duration (
+					checkpoint->checkpoint_creation_attributes.retention_duration,
 					checkpoint,
 					checkpoint,
 					timer_function_retention,
 					timer_function_retention,
 					&checkpoint->retention_timer);
 					&checkpoint->retention_timer);
@@ -1725,8 +1708,10 @@ static void message_handler_req_exec_ckpt_checkpointretentiondurationexpire (
 		&checkpoint_list_head,
 		&checkpoint_list_head,
 		&req_exec_ckpt_checkpointretentiondurationexpire->checkpoint_name,
 		&req_exec_ckpt_checkpointretentiondurationexpire->checkpoint_name,
 		req_exec_ckpt_checkpointretentiondurationexpire->ckpt_id);
 		req_exec_ckpt_checkpointretentiondurationexpire->ckpt_id);
+		log_printf (LOG_LEVEL_NOTICE, "Expiring checkpoint %s\n",
+			get_mar_name_t (&req_exec_ckpt_checkpointretentiondurationexpire->checkpoint_name));
 	if (checkpoint && (checkpoint->reference_count == 0)) {
 	if (checkpoint && (checkpoint->reference_count == 0)) {
-		log_printf (LOG_LEVEL_DEBUG, "Expiring checkpoint %s\n",
+		log_printf (LOG_LEVEL_NOTICE, "Expiring checkpoint %s\n",
 			get_mar_name_t (&req_exec_ckpt_checkpointretentiondurationexpire->checkpoint_name));
 			get_mar_name_t (&req_exec_ckpt_checkpointretentiondurationexpire->checkpoint_name));
 
 
 		req_exec_ckpt_checkpointunlink.header.size =
 		req_exec_ckpt_checkpointunlink.header.size =
@@ -1883,12 +1868,13 @@ static void message_handler_req_exec_ckpt_sectioncreate (
 		log_printf (LOG_LEVEL_DEBUG, "req_exec_ckpt_sectioncreate Enqueuing Timer to Expire section %s in ckpt %s\n",
 		log_printf (LOG_LEVEL_DEBUG, "req_exec_ckpt_sectioncreate Enqueuing Timer to Expire section %s in ckpt %s\n",
 			ckpt_id->ckpt_section_id.id,
 			ckpt_id->ckpt_section_id.id,
 			ckpt_id->ckpt_name.value);
 			ckpt_id->ckpt_name.value);
-		openais_timer_add (
-			abstime_to_msec (checkpoint_section->section_descriptor.expiration_time),
+		openais_timer_add_absolute (
+			checkpoint_section->section_descriptor.expiration_time,
 			ckpt_id,
 			ckpt_id,
 			timer_function_section_expire,
 			timer_function_section_expire,
 			&checkpoint_section->expiration_timer);
 			&checkpoint_section->expiration_timer);
-		log_printf (LOG_LEVEL_DEBUG, "req_exec_ckpt_sectionicreate expiration timer = 0x%p\n",
+		log_printf (LOG_LEVEL_DEBUG,
+			"req_exec_ckpt_sectionicreate expiration timer = 0x%p\n",
 			checkpoint_section->expiration_timer);
 			checkpoint_section->expiration_timer);
 	}
 	}
 
 
@@ -2051,8 +2037,8 @@ static void message_handler_req_exec_ckpt_sectionexpirationtimeset (
 			ckpt_id->ckpt_section_id.id,
 			ckpt_id->ckpt_section_id.id,
 			ckpt_id->ckpt_name.value,
 			ckpt_id->ckpt_name.value,
 			ckpt_id);
 			ckpt_id);
-		openais_timer_add (
-			abstime_to_msec (checkpoint_section->section_descriptor.expiration_time),
+		openais_timer_add_absolute (
+			checkpoint_section->section_descriptor.expiration_time,
 			ckpt_id,
 			ckpt_id,
 			timer_function_section_expire,
 			timer_function_section_expire,
 			&checkpoint_section->expiration_timer);
 			&checkpoint_section->expiration_timer);

+ 14 - 23
exec/evt.c

@@ -2107,27 +2107,23 @@ make_local_event(struct lib_event_data *p,
 static void retain_event(struct event_data *evt)
 static void retain_event(struct event_data *evt)
 {
 {
 	uint32_t ret;
 	uint32_t ret;
-	int msec_in_future;
-
 	evt->ed_ref_count++;
 	evt->ed_ref_count++;
 	evt->ed_my_chan->esc_retained_count++;
 	evt->ed_my_chan->esc_retained_count++;
 	list_add_tail(&evt->ed_retained, &retained_list);
 	list_add_tail(&evt->ed_retained, &retained_list);
-	/*
-	 * Time in nanoseconds - convert to miliseconds
-	 */
-	msec_in_future = (uint32_t)((evt->ed_event.led_retention_time) / 1000000ULL);
-	ret = openais_timer_add(
-					msec_in_future,
-					evt,
-					event_retention_timeout,
-					&evt->ed_timer_handle);
+
+	ret = openais_timer_add_duration (
+		evt->ed_event.led_retention_time,
+		evt,
+		event_retention_timeout,
+		&evt->ed_timer_handle);
+
 	if (ret != 0) {
 	if (ret != 0) {
 		log_printf(LOG_LEVEL_ERROR,
 		log_printf(LOG_LEVEL_ERROR,
 				"retention of event id 0x%llx failed\n",
 				"retention of event id 0x%llx failed\n",
 				(unsigned long long)evt->ed_event.led_event_id);
 				(unsigned long long)evt->ed_event.led_event_id);
 	} else {
 	} else {
-		log_printf(RETENTION_TIME_DEBUG, "Retain event ID 0x%llx for %u ms\n",
-			(unsigned long long)evt->ed_event.led_event_id, msec_in_future);
+		log_printf(RETENTION_TIME_DEBUG, "Retain event ID 0x%llx for %llu ms\n",
+			(unsigned long long)evt->ed_event.led_event_id, evt->ed_event.led_retention_time/100000LL);
 	}
 	}
 }
 }
 
 
@@ -2218,7 +2214,6 @@ static void lib_evt_open_channel(void *conn, void *message)
 	struct req_evt_channel_open *req;
 	struct req_evt_channel_open *req;
 	struct res_evt_channel_open res;
 	struct res_evt_channel_open res;
 	struct open_chan_pending *ocp;
 	struct open_chan_pending *ocp;
-	int msec_in_future;
 	int ret;
 	int ret;
 
 
 	req = message;
 	req = message;
@@ -2260,15 +2255,11 @@ static void lib_evt_open_channel(void *conn, void *message)
 	ocp->ocp_serial_no = open_serial_no;
 	ocp->ocp_serial_no = open_serial_no;
 	list_init(&ocp->ocp_entry);
 	list_init(&ocp->ocp_entry);
 	list_add_tail(&ocp->ocp_entry, &open_pending);
 	list_add_tail(&ocp->ocp_entry, &open_pending);
-	/*
-	 * Time in nanoseconds - convert to miliseconds
-	 */
-	msec_in_future = (uint32_t)(req->ico_timeout / 1000000ULL);
-	ret = openais_timer_add(
-			msec_in_future,
-			ocp,
-			chan_open_timeout,
-			&ocp->ocp_timer_handle);
+	ret = openais_timer_add_duration (
+		req->ico_timeout,
+		ocp,
+		chan_open_timeout,
+		&ocp->ocp_timer_handle);
 	if (ret != 0) {
 	if (ret != 0) {
 		log_printf(LOG_LEVEL_WARNING,
 		log_printf(LOG_LEVEL_WARNING,
 				"Error setting timeout for open channel %s\n",
 				"Error setting timeout for open channel %s\n",

+ 0 - 38
exec/ipc.c

@@ -1262,44 +1262,6 @@ retry_sendmsg_two:
 	return (0);
 	return (0);
 }
 }
 
 
-int openais_ipc_timer_add (
-	void *conn,
-	void (*timer_fn) (void *data),
-	void *data,
-	unsigned int msec_in_future,
-	timer_handle *handle)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-	int res;
-
-	res = timerlist_add_future (
-		&conn_info->timerlist,
-		timer_fn,
-		data,
-		msec_in_future,
-		handle);
-
-	return (res);
-}
-
-void openais_ipc_timer_del (
-	void *conn,
-	timer_handle timer_handle)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-
-	timerlist_del (&conn_info->timerlist, timer_handle);
-}
-
-void openais_ipc_timer_del_data (
-	void *conn,
-	timer_handle timer_handle)
-{
-	struct conn_info *conn_info = (struct conn_info *)conn;
-
-	timerlist_del (&conn_info->timerlist, timer_handle);
-}
-
 void openais_ipc_flow_control_create (
 void openais_ipc_flow_control_create (
 	void *conn,
 	void *conn,
 	unsigned int service,
 	unsigned int service,

+ 29 - 16
exec/timer.c

@@ -1,7 +1,7 @@
 /*
 /*
  * Copyright (c) 2002-2006 MontaVista Software, Inc.
  * Copyright (c) 2002-2006 MontaVista Software, Inc.
- * Copyright (c) 2006 Red Hat, Inc.
  * Copyright (c) 2006 Sun Microsystems, Inc.
  * Copyright (c) 2006 Sun Microsystems, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -103,7 +103,7 @@ extern void pthread_exit(void *) __attribute__((noreturn));
 static void *prioritized_timer_thread (void *data)
 static void *prioritized_timer_thread (void *data)
 {
 {
 	int fds;
 	int fds;
-	unsigned int timeout;
+	unsigned long long timeout;
 
 
 #if ! defined(TS_CLASS) && (defined(OPENAIS_BSD) || defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS))
 #if ! defined(TS_CLASS) && (defined(OPENAIS_BSD) || defined(OPENAIS_LINUX) || defined(OPENAIS_SOLARIS))
 	struct sched_param sched_param;
 	struct sched_param sched_param;
@@ -117,7 +117,10 @@ static void *prioritized_timer_thread (void *data)
 	for (;;) {
 	for (;;) {
 retry_poll:
 retry_poll:
 		timer_serialize_lock_fn ();
 		timer_serialize_lock_fn ();
-		timeout = timerlist_timeout_msec (&timers_timerlist);
+		timeout = timerlist_msec_duration_to_expire (&timers_timerlist);
+		if (timeout != -1 && timeout > 0xFFFFFFFF) {
+			timeout = 0xFFFFFFFE;
+		}
 		timer_serialize_unlock_fn ();
 		timer_serialize_unlock_fn ();
 		fds = poll (NULL, 0, timeout);
 		fds = poll (NULL, 0, timeout);
 		if (fds == -1) {
 		if (fds == -1) {
@@ -165,8 +168,8 @@ int openais_timer_init (
 	return (res);
 	return (res);
 }
 }
 
 
-int openais_timer_add (
-	unsigned int msec_in_future,
+int openais_timer_add_absolute (
+	unsigned long long nanosec_from_epoch,
 	void *data,
 	void *data,
 	void (*timer_fn) (void *data),
 	void (*timer_fn) (void *data),
 	timer_handle *handle)
 	timer_handle *handle)
@@ -181,11 +184,11 @@ int openais_timer_add (
 		pthread_mutex_lock (&timer_mutex);
 		pthread_mutex_lock (&timer_mutex);
 	}
 	}
 
 
-	res = timerlist_add_future (
+	res = timerlist_add_absolute (
 		&timers_timerlist,
 		&timers_timerlist,
 		timer_fn,
 		timer_fn,
 		data,
 		data,
-		msec_in_future,
+		nanosec_from_epoch,
 		handle);
 		handle);
 
 
 	if (unlock) {
 	if (unlock) {
@@ -197,15 +200,15 @@ int openais_timer_add (
 	return (res);
 	return (res);
 }
 }
 
 
-void openais_timer_delete (
-	timer_handle timer_handle)
+int openais_timer_add_duration (
+	unsigned long long nanosec_duration,
+	void *data,
+	void (*timer_fn) (void *data),
+	timer_handle *handle)
 {
 {
+	int res;
 	int unlock;
 	int unlock;
 
 
-	if (timer_handle == 0) {
-		return;
-	}
-
 	if (pthread_equal (pthread_self(), expiry_thread) == 0) {
 	if (pthread_equal (pthread_self(), expiry_thread) == 0) {
 		unlock = 0;
 		unlock = 0;
 	} else {
 	} else {
@@ -213,14 +216,23 @@ void openais_timer_delete (
 		pthread_mutex_lock (&timer_mutex);
 		pthread_mutex_lock (&timer_mutex);
 	}
 	}
 
 
-	timerlist_del (&timers_timerlist, timer_handle);
+	res = timerlist_add_duration (
+		&timers_timerlist,
+		timer_fn,
+		data,
+		nanosec_duration,
+		handle);
 
 
 	if (unlock) {
 	if (unlock) {
 		pthread_mutex_unlock (&timer_mutex);
 		pthread_mutex_unlock (&timer_mutex);
 	}
 	}
+
+	pthread_kill (expiry_thread, SIGUSR1);
+
+	return (res);
 }
 }
 
 
-void openais_timer_delete_data (
+void openais_timer_delete (
 	timer_handle timer_handle)
 	timer_handle timer_handle)
 {
 {
 	int unlock;
 	int unlock;
@@ -228,6 +240,7 @@ void openais_timer_delete_data (
 	if (timer_handle == 0) {
 	if (timer_handle == 0) {
 		return;
 		return;
 	}
 	}
+
 	if (pthread_equal (pthread_self(), expiry_thread) == 0) {
 	if (pthread_equal (pthread_self(), expiry_thread) == 0) {
 		unlock = 0;
 		unlock = 0;
 	} else {
 	} else {
@@ -235,7 +248,7 @@ void openais_timer_delete_data (
 		pthread_mutex_lock (&timer_mutex);
 		pthread_mutex_lock (&timer_mutex);
 	}
 	}
 
 
-	timerlist_del_data (&timers_timerlist, timer_handle);
+	timerlist_del (&timers_timerlist, timer_handle);
 
 
 	if (unlock) {
 	if (unlock) {
 		pthread_mutex_unlock (&timer_mutex);
 		pthread_mutex_unlock (&timer_mutex);

+ 5 - 8
exec/timer.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -43,17 +43,14 @@ extern void openais_timer_init (
         void (*serialize_lock) (void),
         void (*serialize_lock) (void),
         void (*serialize_unlock) (void));
         void (*serialize_unlock) (void));
 
 
-extern int openais_timer_add (
-	unsigned int msec_in_future,
+extern int openais_timer_add_duration (
+	unsigned long long nanoseconds_in_future,
 	void *data,
 	void *data,
 	void (*timer_fn) (void *data),
 	void (*timer_fn) (void *data),
 	timer_handle *handle);
 	timer_handle *handle);
 
 
-/*
- * This should be called when the timer is added from a timer expiration
- */
-extern int openais_timer_add_unlocked (
-	unsigned int msec_in_future,
+extern int openais_timer_add_absolute (
+	unsigned long long nanoseconds_from_epoch,
 	void *data,
 	void *data,
 	void (*timer_fn) (void *data),
 	void (*timer_fn) (void *data),
 	timer_handle *handle);
 	timer_handle *handle);

+ 57 - 102
exec/tlist.h

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2003-2004 MontaVista Software, Inc.
  * Copyright (c) 2003-2004 MontaVista Software, Inc.
- * Copyright (c) 2006 Red Hat, Inc.
+ * Copyright (c) 2006-2007 Red Hat, Inc.
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -41,6 +41,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
+#include <sys/param.h>
 
 
 #include "../include/list.h"
 #include "../include/list.h"
 
 
@@ -53,7 +54,7 @@ struct timerlist {
 
 
 struct timerlist_timer {
 struct timerlist_timer {
 	struct list_head list;
 	struct list_head list;
-	struct timeval tv;
+	unsigned long long nano_from_epoch;
 	void (*timer_fn)(void *data);
 	void (*timer_fn)(void *data);
 	void *data;
 	void *data;
 	timer_handle handle_addr;
 	timer_handle handle_addr;
@@ -64,10 +65,15 @@ static inline void timerlist_init (struct timerlist *timerlist)
 	list_init (&timerlist->timer_head);
 	list_init (&timerlist->timer_head);
 }
 }
 
 
-static inline void timeval_adjust_to_msec (struct timeval *tv) {
-        tv->tv_usec = (tv->tv_usec / 1000) * 1000;
-}
+static inline unsigned long long timerlist_nano_from_epoch (void)
+{
+	unsigned long long nano_from_epoch;
+	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));
+	return (nano_from_epoch);
+}
 
 
 static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_timer *timer)
 static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_timer *timer)
 {
 {
@@ -75,8 +81,6 @@ static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_
 	struct timerlist_timer *timer_from_list;
 	struct timerlist_timer *timer_from_list;
 	int found;
 	int found;
 
 
-	timeval_adjust_to_msec (&timer->tv);
-//printf ("Adding timer %d %d\n", timer->tv.tv_sec, timer->tv.tv_usec);
 	for (found = 0, timer_list = timerlist->timer_head.next;
 	for (found = 0, timer_list = timerlist->timer_head.next;
 		timer_list != &timerlist->timer_head;
 		timer_list != &timerlist->timer_head;
 		timer_list = timer_list->next) {
 		timer_list = timer_list->next) {
@@ -84,9 +88,7 @@ static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_
 		timer_from_list = list_entry (timer_list,
 		timer_from_list = list_entry (timer_list,
 			struct timerlist_timer, list);
 			struct timerlist_timer, list);
 
 
-		if ((timer_from_list->tv.tv_sec > timer->tv.tv_sec) ||
-			((timer_from_list->tv.tv_sec == timer->tv.tv_sec) &&
-			(timer_from_list->tv.tv_usec > timer->tv.tv_usec))) {
+		if (timer_from_list->nano_from_epoch > timer->nano_from_epoch) {
 			list_add (&timer->list, timer_list->prev);
 			list_add (&timer->list, timer_list->prev);
 			found = 1;
 			found = 1;
 			break; /* for timer iteration */
 			break; /* for timer iteration */
@@ -97,16 +99,13 @@ static inline void timerlist_add (struct timerlist *timerlist, struct timerlist_
 	}
 	}
 }
 }
 
 
-static inline int timerlist_add_future (struct timerlist *timerlist,
+static inline int timerlist_add_absolute (struct timerlist *timerlist,
 	void (*timer_fn) (void *data),
 	void (*timer_fn) (void *data),
 	void *data,
 	void *data,
-	unsigned int msec_in_future,
+	unsigned long long nano_from_epoch,
 	timer_handle *handle)
 	timer_handle *handle)
 {
 {
 	struct timerlist_timer *timer;
 	struct timerlist_timer *timer;
-	struct timeval current_time;
-	unsigned int seconds;
-	unsigned int mseconds;
 
 
 	timer = (struct timerlist_timer *)malloc (sizeof (struct timerlist_timer));
 	timer = (struct timerlist_timer *)malloc (sizeof (struct timerlist_timer));
 	if (timer == 0) {
 	if (timer == 0) {
@@ -114,17 +113,31 @@ static inline int timerlist_add_future (struct timerlist *timerlist,
 		return (-1);
 		return (-1);
 	}
 	}
 	
 	
-	seconds = msec_in_future / 1000;
-	mseconds = msec_in_future % 1000;
-
-	gettimeofday (&current_time, 0);
-	timeval_adjust_to_msec (&current_time);
-	timer->tv.tv_sec = current_time.tv_sec + seconds;
-	timer->tv.tv_usec = current_time.tv_usec + mseconds * 1000;
-	if (timer->tv.tv_usec >= 1000000) {
-		timer->tv.tv_sec++;
-		timer->tv.tv_usec -= 1000000;
+	timer->nano_from_epoch = nano_from_epoch;
+	timer->data = data;
+	timer->timer_fn = timer_fn;
+	timer->handle_addr = handle;
+	timerlist_add (timerlist, timer);
+
+	*handle = timer;
+	return (0);
+}
+
+static inline int timerlist_add_duration (struct timerlist *timerlist,
+	void (*timer_fn) (void *data),
+	void *data,
+	unsigned long long nano_duration,
+	timer_handle *handle)
+{
+	struct timerlist_timer *timer;
+
+	timer = (struct timerlist_timer *)malloc (sizeof (struct timerlist_timer));
+	if (timer == 0) {
+		errno = ENOMEM;
+		return (-1);
 	}
 	}
+	
+	timer->nano_from_epoch = timerlist_nano_from_epoch() + nano_duration;
 	timer->data = data;
 	timer->data = data;
 	timer->timer_fn = timer_fn;
 	timer->timer_fn = timer_fn;
 	timer->handle_addr = handle;
 	timer->handle_addr = handle;
@@ -141,7 +154,7 @@ static inline void timerlist_del (struct timerlist *timerlist, timer_handle time
 	memset (timer->handle_addr, 0, sizeof (struct timerlist_timer *));
 	memset (timer->handle_addr, 0, sizeof (struct timerlist_timer *));
 	/*
 	/*
 	 * If the next timer after the currently expiring timer because
 	 * If the next timer after the currently expiring timer because
-	 * timerlist_del is called from a timer handler, get to the enxt
+	 * timerlist_del is called from a timer handler, get to the next
 	 * timer
 	 * timer
 	 */
 	 */
 	if (timerlist->timer_iter == &timer->list) {
 	if (timerlist->timer_iter == &timer->list) {
@@ -152,16 +165,6 @@ static inline void timerlist_del (struct timerlist *timerlist, timer_handle time
 	free (timer);
 	free (timer);
 }
 }
 
 
-static inline void timerlist_del_data (struct timerlist *timerlist, timer_handle timer_handle)
-{
-	struct timerlist_timer *timer = (struct timerlist_timer *)timer_handle;
-
-	if (timer->data) {
-		free (timer->data);
-	}
-	timerlist_del(timerlist,timer_handle);
-}
-
 static inline void timerlist_pre_dispatch (struct timerlist *timerlist, timer_handle timer_handle)
 static inline void timerlist_pre_dispatch (struct timerlist *timerlist, timer_handle timer_handle)
 {
 {
 	struct timerlist_timer *timer = (struct timerlist_timer *)timer_handle;
 	struct timerlist_timer *timer = (struct timerlist_timer *)timer_handle;
@@ -178,57 +181,14 @@ static inline void timerlist_post_dispatch (struct timerlist *timerlist, timer_h
 	free (timer);
 	free (timer);
 }
 }
 
 
-#ifdef CODE_COVERAGE_COMPILE_OUT
-static inline int timer_expire_get_tv (struct timerlist *timerlist, struct timeval *tv)
-{
-	struct timeval current_time;
-	struct timerlist_timer *timer_from_list;
-
-	/*
-	 * empty list, no expire
-	 */
-	if (timerlist->timer_head.next == &timerlist->timer_head) {
-		return (-1);
-	}
-	
-	timer_from_list = list_entry (timerlist->timer_head.next,
-		struct timerlist_timer, list);
-
-	gettimeofday (&current_time, 0);
-	timeval_adjust_to_msec (&current_time);
-
-	/*
-	 * timer at head of list is expired, zero msecs required
-	 */
-	if ((timer_from_list->tv.tv_sec < current_time.tv_sec) ||
-		((timer_from_list->tv.tv_sec == current_time.tv_sec) &&
-		(timer_from_list->tv.tv_usec <= current_time.tv_usec))) {
-		
-		tv->tv_sec = 0;
-		tv->tv_usec = 0;
-	}
-
-	tv->tv_sec = timer_from_list->tv.tv_sec - current_time.tv_sec;
-	tv->tv_usec = timer_from_list->tv.tv_usec - current_time.tv_usec;
-	if (tv->tv_usec < 0) {
-		tv->tv_sec -= 1;
-		tv->tv_usec += 1000000;
-	}
-	if (tv->tv_sec < 0) {
-		tv->tv_sec = 0;
-		tv->tv_usec = 0;
-	}
-
-	timeval_adjust_to_msec (tv);
-	return (0);
-}
-#endif /* CODE_COVERAGE_COMPILE_OUT */
-
-static inline unsigned int timerlist_timeout_msec (struct timerlist *timerlist)
+/*
+ * returns the number of msec until the next timer will expire for use with poll
+ */
+static inline unsigned long long timerlist_msec_duration_to_expire (struct timerlist *timerlist)
 {
 {
-	struct timeval current_time;
 	struct timerlist_timer *timer_from_list;
 	struct timerlist_timer *timer_from_list;
-	int time_in_msec;
+	volatile unsigned long long nano_from_epoch;
+	volatile unsigned long long msec_duration_to_expire;
 
 
 	/*
 	/*
 	 * empty list, no expire
 	 * empty list, no expire
@@ -240,32 +200,30 @@ static inline unsigned int timerlist_timeout_msec (struct timerlist *timerlist)
 	timer_from_list = list_entry (timerlist->timer_head.next,
 	timer_from_list = list_entry (timerlist->timer_head.next,
 		struct timerlist_timer, list);
 		struct timerlist_timer, list);
 
 
-	gettimeofday (&current_time, 0);
-	timeval_adjust_to_msec (&current_time);
+	nano_from_epoch = timerlist_nano_from_epoch();
 
 
 	/*
 	/*
 	 * timer at head of list is expired, zero msecs required
 	 * timer at head of list is expired, zero msecs required
 	 */
 	 */
-	if ((timer_from_list->tv.tv_sec < current_time.tv_sec) ||
-		((timer_from_list->tv.tv_sec == current_time.tv_sec) &&
-		(timer_from_list->tv.tv_usec <= current_time.tv_usec))) {
+	if (timer_from_list->nano_from_epoch < nano_from_epoch) {
 		return (0);
 		return (0);
 	}
 	}
-	time_in_msec = ((timer_from_list->tv.tv_sec - current_time.tv_sec) * 1000) + ((timer_from_list->tv.tv_usec - current_time.tv_usec) / 1000);
 
 
-	if (time_in_msec < 0) {
-		return (0);
-	}
-	return time_in_msec;
+	
+	msec_duration_to_expire = ((timer_from_list->nano_from_epoch - nano_from_epoch) / 1000000ULL) +
+		(1000 / HZ);
+	return (msec_duration_to_expire);
 }
 }
 
 
+/*
+ * Expires any timers that should be expired
+ */
 static inline void timerlist_expire (struct timerlist *timerlist)
 static inline void timerlist_expire (struct timerlist *timerlist)
 {
 {
 	struct timerlist_timer *timer_from_list;
 	struct timerlist_timer *timer_from_list;
-	struct timeval current_time;
+	unsigned long long nano_from_epoch;
 
 
-	gettimeofday (&current_time, 0);
-	timeval_adjust_to_msec (&current_time);
+	nano_from_epoch = timerlist_nano_from_epoch();
 
 
 	for (timerlist->timer_iter = timerlist->timer_head.next;
 	for (timerlist->timer_iter = timerlist->timer_head.next;
 		timerlist->timer_iter != &timerlist->timer_head;) {
 		timerlist->timer_iter != &timerlist->timer_head;) {
@@ -273,10 +231,7 @@ static inline void timerlist_expire (struct timerlist *timerlist)
 		timer_from_list = list_entry (timerlist->timer_iter,
 		timer_from_list = list_entry (timerlist->timer_iter,
 			struct timerlist_timer, list);
 			struct timerlist_timer, list);
 
 
-		if ((timer_from_list->tv.tv_sec < current_time.tv_sec) ||
-			((timer_from_list->tv.tv_sec == current_time.tv_sec) &&
-			(timer_from_list->tv.tv_usec <= current_time.tv_usec))) {
-//printf ("Executing timer %d %d\n", timer_from_list->tv.tv_sec, timer_from_list->tv.tv_usec);
+		if (timer_from_list->nano_from_epoch < nano_from_epoch) {
 			timerlist->timer_iter = timerlist->timer_iter->next;
 			timerlist->timer_iter = timerlist->timer_iter->next;
 
 
 			timerlist_pre_dispatch (timerlist, timer_from_list);
 			timerlist_pre_dispatch (timerlist, timer_from_list);