Index: app.c
===================================================================
RCS file: /usr/cvsroot/asterisk/app.c,v
retrieving revision 1.67
diff -u -r1.67 app.c
--- app.c	6 Jun 2005 22:12:18 -0000	1.67
+++ app.c	10 Jun 2005 08:25:28 -0000
@@ -408,7 +408,6 @@
 
 int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, int skipms) 
 {
-	struct timeval started, ended;
 	long elapsed = 0,last_elapsed =0;
 	char *breaks=NULL;
 	char *end=NULL;
@@ -443,7 +442,7 @@
 	}
 
 	for (;;) {
-		gettimeofday(&started,NULL);
+		struct timeval started = ast_tvnow();
 
 		if (chan)
 			ast_stopstream(chan);
@@ -468,8 +467,7 @@
 			break;
 
 		if (pause != NULL && strchr(pause, res)) {
-			gettimeofday(&ended, NULL);
-			elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
+			elapsed = ast_tvdiff(ast_tvnow(), started) + last_elapsed;
 			for(;;) {
 				if (chan)
 					ast_stopstream(chan);
Index: cdr.c
===================================================================
RCS file: /usr/cvsroot/asterisk/cdr.c,v
retrieving revision 1.41
diff -u -r1.41 cdr.c
--- cdr.c	6 Jun 2005 22:12:18 -0000	1.41
+++ cdr.c	10 Jun 2005 08:25:29 -0000
@@ -415,9 +415,9 @@
 		chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
 		if (!ast_test_flag(cdr, AST_CDR_FLAG_POSTED) && !ast_test_flag(cdr, AST_CDR_FLAG_POST_DISABLED))
 			ast_log(LOG_WARNING, "CDR on channel '%s' not posted\n", chan);
-		if (!cdr->end.tv_sec && !cdr->end.tv_usec)
+		if (ast_tvzero(cdr->end))
 			ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
-		if (!cdr->start.tv_sec && !cdr->start.tv_usec)
+		if (ast_tvzero(cdr->start))
 			ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
 
 		ast_cdr_free_vars(cdr, 0);
@@ -446,7 +446,7 @@
 			chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
 			if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
 				ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
-			if (cdr->start.tv_sec || cdr->start.tv_usec)
+			if (!ast_tvzero(cdr->start))
 				ast_log(LOG_WARNING, "CDR on channel '%s' already started\n", chan);
 			gettimeofday(&cdr->start, NULL);
 		}
@@ -464,9 +464,8 @@
 			ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
 		if (cdr->disposition < AST_CDR_ANSWERED)
 			cdr->disposition = AST_CDR_ANSWERED;
-		if (!cdr->answer.tv_sec && !cdr->answer.tv_usec) {
-			gettimeofday(&cdr->answer, NULL);
-		}
+		if (ast_tvzero(cdr->answer))
+			cdr->answer = ast_tvnow();
 		cdr = cdr->next;
 	}
 }
@@ -633,10 +632,10 @@
 		chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
 		if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
 			ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
-		if (!cdr->start.tv_sec && !cdr->start.tv_usec)
+		if (ast_tvzero(cdr->start))
 			ast_log(LOG_WARNING, "CDR on channel '%s' has not started\n", chan);
-		if (!cdr->end.tv_sec && !cdr->end.tv_usec) 
-			gettimeofday(&cdr->end, NULL);
+		if (ast_tvzero(cdr->end))
+			cdr->end = ast_tvnow();
 		cdr = cdr->next;
 	}
 }
@@ -776,12 +775,12 @@
 		chan = !ast_strlen_zero(cdr->channel) ? cdr->channel : "<unknown>";
 		if (ast_test_flag(cdr, AST_CDR_FLAG_POSTED))
 			ast_log(LOG_WARNING, "CDR on channel '%s' already posted\n", chan);
-		if (!cdr->end.tv_sec && !cdr->end.tv_usec)
+		if (ast_tvzero(cdr->end))
 			ast_log(LOG_WARNING, "CDR on channel '%s' lacks end\n", chan);
-		if (!cdr->start.tv_sec && !cdr->start.tv_usec)
+		if (ast_tvzero(cdr->start))
 			ast_log(LOG_WARNING, "CDR on channel '%s' lacks start\n", chan);
 		cdr->duration = cdr->end.tv_sec - cdr->start.tv_sec + (cdr->end.tv_usec - cdr->start.tv_usec) / 1000000;
-		if (cdr->answer.tv_sec || cdr->answer.tv_usec)
+		if (!ast_tvzero(cdr->answer))
 			cdr->billsec = cdr->end.tv_sec - cdr->answer.tv_sec + (cdr->end.tv_usec - cdr->answer.tv_usec) / 1000000;
 		else
 			cdr->billsec = 0;
@@ -1003,13 +1002,12 @@
 
 static void *do_cdr(void *data)
 {
-	struct timeval now;
 	struct timespec timeout;
 	int schedms;
 	int numevents = 0;
 
 	for(;;) {
-		gettimeofday(&now, NULL);
+		struct timeval now = ast_tvnow();
 		schedms = ast_sched_wait(sched);
 		/* this shouldn't happen, but provide a 1 second default just in case */
 		if (schedms <= 0)
Index: channel.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channel.c,v
retrieving revision 1.203
diff -u -r1.203 channel.c
--- channel.c	6 Jun 2005 22:12:18 -0000	1.203
+++ channel.c	10 Jun 2005 08:25:32 -0000
@@ -1019,7 +1019,7 @@
 int ast_waitfor_n_fd(int *fds, int n, int *ms, int *exception)
 {
 	/* Wait for x amount of time on a file descriptor to have input.  */
-	struct timeval start, now;
+	struct timeval start;
 	int res;
 	int x, y;
 	int winner = -1;
@@ -1032,7 +1032,7 @@
 		return -1;
 	}
 	if (*ms > 0)
-		gettimeofday(&start, NULL);
+		start = ast_tvnow();
 	y = 0;
 	for (x=0;x<n;x++) {
 		if (fds[x] > -1) {
@@ -1065,13 +1065,8 @@
 		}
 	}
 	if (*ms > 0) {
-		long passed;
-		gettimeofday(&now, NULL);
-		passed = (now.tv_sec - start.tv_sec) * 1000;
-		passed += (now.tv_usec - start.tv_usec) / 1000;
-		if (passed <= *ms)
-			*ms -= passed;
-		else
+		*ms -= ast_tvdiff(ast_tvnow(), start);
+		if (*ms < 0)
 			*ms = 0;
 	}
 	return winner;
@@ -1081,7 +1076,7 @@
 	int *exception, int *outfd, int *ms)
 {
 	/* Wait for x amount of time on a file descriptor to have input.  */
-	struct timeval start, end;
+	struct timeval start;
 	struct pollfd *pfds;
 	int res;
 	long rms;
@@ -1152,7 +1147,7 @@
 		}
 	}
 	if (*ms > 0) 
-		gettimeofday(&start, NULL);
+		start = ast_tvnow();
 	res = poll(pfds, max, rms);
 	if (res < 0) {
 		for (x=0;x<n;x++) 
@@ -1214,13 +1209,8 @@
 		}	
 	}
 	if (*ms > 0) {
-		long diff;
-		gettimeofday(&end, NULL);
-		diff = (end.tv_sec - start.tv_sec) * 1000;
-		diff += (end.tv_usec - start.tv_usec) / 1000;
-		if (diff < *ms)
-			*ms -= diff;
-		else
+		*ms -= ast_tvdiff(ast_tvnow(), start);
+		if (*ms < 0)
 			*ms = 0;
 	}
 	return winner;
@@ -2763,15 +2753,6 @@
 	return 0;
 }
 
-static long tvdiff(struct timeval *now, struct timeval *then) 
-{
-#if 0
-	return (((now->tv_sec * 1000) + now->tv_usec / 1000) - ((then->tv_sec * 1000) + then->tv_usec / 1000));
-#else
-	return (now->tv_sec - then->tv_sec) * 1000 + (now->tv_usec - then->tv_usec) / 1000;	
-#endif
-}
-
 /*--- Find bridged channel */
 struct ast_channel *ast_bridged_channel(struct ast_channel *chan)
 {
@@ -2832,7 +2813,6 @@
 	int res=0;
 	int o0nativeformats;
 	int o1nativeformats;
-	struct timeval precise_now;
 	long elapsed_ms=0, time_left_ms=0;
 	
 	cs[0] = c0;
@@ -2853,8 +2833,7 @@
 		/* timestamp */
 		if (config->timelimit) {
 			/* If there is a time limit, return now */
-			gettimeofday(&precise_now,NULL);
-			elapsed_ms = tvdiff(&precise_now,start_time);
+			elapsed_ms = ast_tvdiff(ast_tvnow(), *start_time);
 			time_left_ms = config->timelimit - elapsed_ms;
 
 			if (*playitagain && ((ast_test_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING)) || (ast_test_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING))) && (config->play_warning && time_left_ms <= config->play_warning)) { 
@@ -2974,7 +2953,7 @@
 	int firstpass;
 	int o0nativeformats;
 	int o1nativeformats;
-	struct timeval start_time,precise_now;
+	struct timeval start_time;
 	long elapsed_ms=0, time_left_ms=0;
 	int playit=0, playitagain=1, first_time=1;
 
@@ -2983,7 +2962,7 @@
 	config->firstpass = 0;
 
 	/* timestamp */
-	gettimeofday(&start_time,NULL);
+	start_time = ast_tvnow();
 	time_left_ms = config->timelimit;
 
 	if ((ast_test_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING)) && config->start_sound && firstpass)
@@ -3022,8 +3001,7 @@
 	for (/* ever */;;) {
 		/* timestamp */
 		if (config->timelimit) {
-			gettimeofday(&precise_now,NULL);
-			elapsed_ms = tvdiff(&precise_now,&start_time);
+			elapsed_ms = ast_tvdiff(ast_tvnow(), start_time);
 			time_left_ms = config->timelimit - elapsed_ms;
 
 			if (playitagain && ((ast_test_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING)) || (ast_test_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING))) && (config->play_warning && time_left_ms <= config->play_warning)) { 
Index: frame.c
===================================================================
RCS file: /usr/cvsroot/asterisk/frame.c,v
retrieving revision 1.58
diff -u -r1.58 frame.c
--- frame.c	6 Jun 2005 22:12:18 -0000	1.58
+++ frame.c	10 Jun 2005 08:25:33 -0000
@@ -144,8 +144,7 @@
 	else
 		memcpy(s->data + s->len, f->data, f->datalen);
 	/* If either side is empty, reset the delivery time */
-	if (!s->len || (!f->delivery.tv_sec && !f->delivery.tv_usec) ||
-			(!s->delivery.tv_sec && !s->delivery.tv_usec))
+	if (!s->len || ast_tvzero(f->delivery) || ast_tvzero(s->delivery))	/* XXX really ? */
 		s->delivery = f->delivery;
 	s->len += f->datalen;
 	return 0;
@@ -181,7 +180,7 @@
 	s->f.offset = AST_FRIENDLY_OFFSET;
 	s->f.datalen = len;
 	/* Samples will be improper given VAD, but with VAD the concept really doesn't even exist */
-	s->f.samples = len * s->samplesperbyte;
+	s->f.samples = len * s->samplesperbyte;	/* XXX rounding */
 	s->f.delivery = s->delivery;
 	/* Fill Data */
 	memcpy(s->f.data, s->data, len);
@@ -191,14 +190,9 @@
 		/* In principle this should all be fine because if we are sending
 		   G.729 VAD, the next timestamp will take over anyawy */
 		memmove(s->data, s->data + len, s->len);
-		if (s->delivery.tv_sec || s->delivery.tv_usec) {
+		if (!ast_tvzero(s->delivery)) {
 			/* If we have delivery time, increment it, otherwise, leave it at 0 */
-			s->delivery.tv_sec += (len * s->samplesperbyte) / 8000.0;
-			s->delivery.tv_usec += (((int)(len * s->samplesperbyte)) % 8000) * 125;
-			if (s->delivery.tv_usec > 1000000) {
-				s->delivery.tv_usec -= 1000000;
-				s->delivery.tv_sec += 1;
-			}
+			s->delivery = ast_tvadd(s->delivery, ast_samp2tv(s->f.samples, 8000));
 		}
 	}
 	/* Return frame */
Index: manager.c
===================================================================
RCS file: /usr/cvsroot/asterisk/manager.c,v
retrieving revision 1.100
diff -u -r1.100 manager.c
--- manager.c	6 Jun 2005 22:12:18 -0000	1.100
+++ manager.c	10 Jun 2005 08:25:34 -0000
@@ -683,11 +683,10 @@
 	char idText[256] = "";
 	struct ast_channel *c;
 	char bridge[256];
-	struct timeval now;
+	struct timeval now = ast_tvnow();
 	long elapsed_seconds=0;
 	int all = !name || ast_strlen_zero(name); /* set if we want all channels */
 
-	gettimeofday(&now, NULL);
 	astman_send_ack(s, m, "Channel status will follow");
         if (id && !ast_strlen_zero(id))
                 snprintf(idText,256,"ActionID: %s\r\n",id);
Index: rtp.c
===================================================================
RCS file: /usr/cvsroot/asterisk/rtp.c,v
retrieving revision 1.134
diff -u -r1.134 rtp.c
--- rtp.c	6 Jun 2005 22:12:18 -0000	1.134
+++ rtp.c	10 Jun 2005 08:25:36 -0000
@@ -143,12 +143,10 @@
 
 static struct ast_frame *send_dtmf(struct ast_rtp *rtp)
 {
-	struct timeval tv;
 	static struct ast_frame null_frame = { AST_FRAME_NULL, };
 	char iabuf[INET_ADDRSTRLEN];
-	gettimeofday(&tv, NULL);
-	if ((tv.tv_sec < rtp->dtmfmute.tv_sec) ||
-	    ((tv.tv_sec == rtp->dtmfmute.tv_sec) && (tv.tv_usec < rtp->dtmfmute.tv_usec))) {
+
+	if (ast_tvcmp(ast_tvnow(), rtp->dtmfmute) < 0) {
 		if (option_debug)
 			ast_log(LOG_DEBUG, "Ignore potential DTMF echo from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), rtp->them.sin_addr));
 		rtp->resp = 0;
@@ -363,24 +361,13 @@
 
 static void calc_rxstamp(struct timeval *tv, struct ast_rtp *rtp, unsigned int timestamp, int mark)
 {
-	if ((!rtp->rxcore.tv_sec && !rtp->rxcore.tv_usec) || mark) {
-		gettimeofday(&rtp->rxcore, NULL);
-		rtp->rxcore.tv_sec -= timestamp / 8000;
-		rtp->rxcore.tv_usec -= (timestamp % 8000) * 125;
+	struct timeval ts = ast_samp2tv( timestamp, 8000);
+	if (ast_tvzero(rtp->rxcore) || mark) {
+		rtp->rxcore = ast_tvsub(ast_tvnow(), ts);
 		/* Round to 20ms for nice, pretty timestamps */
 		rtp->rxcore.tv_usec -= rtp->rxcore.tv_usec % 20000;
-		if (rtp->rxcore.tv_usec < 0) {
-			/* Adjust appropriately if necessary */
-			rtp->rxcore.tv_usec += 1000000;
-			rtp->rxcore.tv_sec -= 1;
-		}
-	}
-	tv->tv_sec = rtp->rxcore.tv_sec + timestamp / 8000;
-	tv->tv_usec = rtp->rxcore.tv_usec + (timestamp % 8000) * 125;
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec += 1;
 	}
+	*tv = ast_tvadd(rtp->rxcore, ts);
 }
 
 struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
@@ -1013,28 +1000,19 @@
 
 static unsigned int calc_txstamp(struct ast_rtp *rtp, struct timeval *delivery)
 {
-	struct timeval now;
-	unsigned int ms;
-	if (!rtp->txcore.tv_sec && !rtp->txcore.tv_usec) {
-		gettimeofday(&rtp->txcore, NULL);
+	struct timeval t;
+	long ms;
+	if (ast_tvzero(rtp->txcore)) {
+		rtp->txcore = ast_tvnow();
 		/* Round to 20ms for nice, pretty timestamps */
 		rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
 	}
-	if (delivery && (delivery->tv_sec || delivery->tv_usec)) {
-		/* Use previous txcore */
-		ms = (delivery->tv_sec - rtp->txcore.tv_sec) * 1000;
-		ms += (1000000 + delivery->tv_usec - rtp->txcore.tv_usec) / 1000 - 1000;
-		rtp->txcore.tv_sec = delivery->tv_sec;
-		rtp->txcore.tv_usec = delivery->tv_usec;
-	} else {
-		gettimeofday(&now, NULL);
-		ms = (now.tv_sec - rtp->txcore.tv_sec) * 1000;
-		ms += (1000000 + now.tv_usec - rtp->txcore.tv_usec) / 1000 - 1000;
-		/* Use what we just got for next time */
-		rtp->txcore.tv_sec = now.tv_sec;
-		rtp->txcore.tv_usec = now.tv_usec;
-	}
-	return ms;
+	/* Use previous txcore if available */
+	t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
+	ms = ast_tvdiff(t, rtp->txcore);
+	/* Use what we just got for next time */
+	rtp->txcore = t;
+	return (unsigned int) ms;
 }
 
 int ast_rtp_senddigit(struct ast_rtp *rtp, char digit)
@@ -1067,12 +1045,7 @@
 	if (!rtp->them.sin_addr.s_addr)
 		return 0;
 
-	gettimeofday(&rtp->dtmfmute, NULL);
-	rtp->dtmfmute.tv_usec += (500 * 1000);
-	if (rtp->dtmfmute.tv_usec > 1000000) {
-		rtp->dtmfmute.tv_usec -= 1000000;
-		rtp->dtmfmute.tv_sec += 1;
-	}
+	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
 	
 	/* Get a pointer to the header */
 	rtpheader = (unsigned int *)data;
@@ -1128,13 +1101,8 @@
 	if (!rtp->them.sin_addr.s_addr)
 		return 0;
 
-	gettimeofday(&rtp->dtmfmute, NULL);
-	rtp->dtmfmute.tv_usec += (500 * 1000);
-	if (rtp->dtmfmute.tv_usec > 1000000) {
-		rtp->dtmfmute.tv_usec -= 1000000;
-		rtp->dtmfmute.tv_sec += 1;
-	}
-	
+	rtp->dtmfmute = ast_tvadd(ast_tvnow(), ast_tv(0, 500000));
+
 	/* Get a pointer to the header */
 	rtpheader = (unsigned int *)data;
 	rtpheader[0] = htonl((2 << 30) | (1 << 23) | (payload << 16) | (rtp->seqno++));
@@ -1170,7 +1138,7 @@
 
 		/* Re-calculate last TS */
 		rtp->lastts = rtp->lastts + ms * 8;
-		if (!f->delivery.tv_sec && !f->delivery.tv_usec) {
+		if (ast_tvzero(f->delivery)) {
 			/* If this isn't an absolute delivery time, Check if it is close to our prediction, 
 			   and if so, go with our prediction */
 			if (abs(rtp->lastts - pred) < MAX_TIMESTAMP_SKEW)
@@ -1187,7 +1155,7 @@
 		/* Re-calculate last TS */
 		rtp->lastts = rtp->lastts + ms * 90;
 		/* If it's close to our prediction, go for it */
-		if (!f->delivery.tv_sec && !f->delivery.tv_usec) {
+		if (ast_tvzero(f->delivery)) {
 			if (abs(rtp->lastts - pred) < 7200) {
 				rtp->lastts = pred;
 				rtp->lastovidtimestamp += f->samples;
Index: sched.c
===================================================================
RCS file: /usr/cvsroot/asterisk/sched.c,v
retrieving revision 1.20
diff -u -r1.20 sched.c
--- sched.c	6 Jun 2005 22:12:18 -0000	1.20
+++ sched.c	10 Jun 2005 08:25:36 -0000
@@ -148,18 +148,13 @@
 	 * Return the number of milliseconds 
 	 * until the next scheduled event
 	 */
-	struct timeval tv;
 	int ms;
 	DEBUG(ast_log(LOG_DEBUG, "ast_sched_wait()\n"));
 	ast_mutex_lock(&con->lock);
 	if (!con->schedq) {
 		ms = -1;
-	} else if (gettimeofday(&tv, NULL) < 0) {
-		/* This should never happen */
-		ms = 0;
 	} else {
-		ms = (con->schedq->when.tv_sec - tv.tv_sec) * 1000;
-		ms += (con->schedq->when.tv_usec - tv.tv_usec) / 1000;
+		ms = ast_tvdiff(con->schedq->when, ast_tvnow());
 		if (ms < 0)
 			ms = 0;
 	}
@@ -194,41 +189,21 @@
 	con->schedcnt++;
 }
 
-static inline int sched_settime(struct timeval *tv, int when)
+/*
+ * given the last event *tv and the offset in milliseconds 'when',
+ * computes the next value,
+ */
+static int sched_settime(struct timeval *tv, int when)
 {
-	struct timeval tv_tmp;
-	long error_sec, error_usec;
+	struct timeval now = ast_tvnow();
 
-	if (gettimeofday(&tv_tmp, NULL) < 0) {
-		/* This shouldn't ever happen, but let's be sure */
-		ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
-		return -1;
-	}
 	/*ast_log(LOG_DEBUG, "TV -> %lu,%lu\n", tv->tv_sec, tv->tv_usec);*/
-	if (((unsigned long)(tv->tv_sec) > 0)||((unsigned long)(tv->tv_usec) > 0)) {
-		if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv->tv_usec)) {
-			tv_tmp.tv_usec += 1000000;
-			tv_tmp.tv_sec -= 1;
-		}
-		error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv->tv_sec);
-		error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv->tv_usec);
-	} else {
-		/*ast_log(LOG_DEBUG, "Initializing error\n");*/
-		error_sec = 0;
-		error_usec = 0;
-	}
-	/*ast_log(LOG_DEBUG, "ERROR -> %lu,%lu\n", error_sec, error_usec);*/
-	if (error_sec * 1000 + error_usec / 1000 < when) {
-		tv->tv_sec = tv_tmp.tv_sec + (when/1000 - error_sec);
-		tv->tv_usec = tv_tmp.tv_usec + ((when % 1000) * 1000 - error_usec);
-	} else {
+	if (ast_tvzero(*tv))	/* not supplied, default to now */
+		*tv = now;
+	*tv = ast_tvadd(*tv, ast_samp2tv(when, 1000));
+	if (ast_tvcmp(*tv, now) < 0) {
 		ast_log(LOG_DEBUG, "Request to schedule in the past?!?!\n");
-		tv->tv_sec = tv_tmp.tv_sec;
-		tv->tv_usec = tv_tmp.tv_usec;
-	}
-	if (tv->tv_usec > 1000000) {
-		tv->tv_sec++;
-		tv->tv_usec-= 1000000;
+		*tv = now;
 	}
 	return 0;
 }
@@ -251,8 +226,7 @@
 		tmp->callback = callback;
 		tmp->data = data;
 		tmp->resched = when;
-		tmp->when.tv_sec = 0;
-		tmp->when.tv_usec = 0;
+		tmp->when = ast_tv(0, 0);
 		if (sched_settime(&tmp->when, when)) {
 			sched_release(con, tmp);
 		} else {
@@ -307,9 +281,7 @@
 	 * stderr
 	 */
 	struct sched *q;
-	struct timeval tv;
-	time_t s, ms;
-	gettimeofday(&tv, NULL);
+	struct timeval tv = ast_tvnow();
 #ifdef SCHED_MAX_CACHE
 	ast_log(LOG_DEBUG, "Asterisk Schedule Dump (%d in Q, %d Total, %d Cache)\n", 
 							con-> schedcnt, con->eventcnt - 1, con->schedccnt);
@@ -321,21 +293,14 @@
 	ast_log(LOG_DEBUG, "=================================================\n");
 	ast_log(LOG_DEBUG, "|ID    Callback    Data        Time  (sec:ms)   |\n");
 	ast_log(LOG_DEBUG, "+-----+-----------+-----------+-----------------+\n");
-	q = con->schedq;
-	while(q) {
-		s =  q->when.tv_sec - tv.tv_sec;
-		ms = q->when.tv_usec - tv.tv_usec;
-		if (ms < 0) {
-			ms += 1000000;
-			s--;
-		}
+	for (q = con->schedq; q; q = q->next) {
+		struct timeval delta =  ast_tvsub(q->when, tv);
 		ast_log(LOG_DEBUG, "|%.4d | %p | %p | %.6ld : %.6ld |\n", 
 				q->id,
 				q->callback,
 				q->data,
-				(long)s,
-				(long)ms);
-		q=q->next;
+				delta.tv_sec,
+				delta.tv_usec);
 	}
 	ast_log(LOG_DEBUG, "=================================================\n");
 	
@@ -356,15 +321,13 @@
 	for(;;) {
 		if (!con->schedq)
 			break;
-		if (gettimeofday(&tv, NULL)) {
-			/* This should never happen */
-			ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
-			break;
-		}
-		/* We only care about millisecond accuracy anyway, so this will
-		   help us get more than one event at one time if they are very
-		   close together. */
-		tv.tv_usec += 1000;
+		
+		/* schedule all events which are going to expire within 1ms.
+		 * We only care about millisecond accuracy anyway, so this will
+		 * help us get more than one event at one time if they are very
+		 * close together.
+		 */
+		tv = ast_tvadd(ast_tvnow(), ast_tv(0, 1000));
 		if (SOONER(con->schedq->when, tv)) {
 			current = con->schedq;
 			con->schedq = con->schedq->next;
@@ -408,7 +371,6 @@
 {
 	struct sched *s;
 	long secs;
-	struct timeval now;
 	DEBUG(ast_log(LOG_DEBUG, "ast_sched_when()\n"));
 
 	ast_mutex_lock(&con->lock);
@@ -419,11 +381,8 @@
 	}
 	secs=-1;
 	if (s!=NULL) {
-		if (gettimeofday(&now, NULL)) {
-			ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
-		} else {
-			secs=s->when.tv_sec-now.tv_sec;
-		}
+		struct timeval now = ast_tvnow();
+		secs=s->when.tv_sec-now.tv_sec;
 	}
 	ast_mutex_unlock(&con->lock);
 	return secs;
Index: translate.c
===================================================================
RCS file: /usr/cvsroot/asterisk/translate.c,v
retrieving revision 1.38
diff -u -r1.38 translate.c
--- translate.c	6 Jun 2005 22:12:18 -0000	1.38
+++ translate.c	10 Jun 2005 08:25:36 -0000
@@ -107,10 +107,7 @@
 				
 			if (tmp) {
 				tmp->next = NULL;
-				tmp->nextin.tv_sec = 0;
-				tmp->nextin.tv_usec = 0;
-				tmp->nextout.tv_sec = 0;
-				tmp->nextout.tv_usec = 0;
+				tmp->nextin = tmp->nextout = ast_tv( 0, 0 );
 				tmp->step = tr_matrix[source][dest].step;
 				tmp->state = tmp->step->newpvt();
 				if (!tmp->state) {
@@ -147,47 +144,26 @@
 	p = path;
 	/* Feed the first frame into the first translator */
 	p->step->framein(p->state, f);
-	if (f->delivery.tv_sec || f->delivery.tv_usec) {
-		if (path->nextin.tv_sec || path->nextin.tv_usec) {
+	if (!ast_tvzero(f->delivery)) {
+		if (!ast_tvzero(path->nextin)) {
 			/* Make sure this is in line with what we were expecting */
-			if ((path->nextin.tv_sec != f->delivery.tv_sec) ||
-			    (path->nextin.tv_usec != f->delivery.tv_usec)) {
+			if (!ast_tveq(path->nextin, f->delivery)) {
 				/* The time has changed between what we expected and this
 				   most recent time on the new packet.  Adjust our output
 				   time appropriately */
-				long sdiff;
-				long udiff;
-				sdiff = f->delivery.tv_sec - path->nextin.tv_sec;
-				udiff = f->delivery.tv_usec - path->nextin.tv_usec;
-				path->nextin.tv_sec = f->delivery.tv_sec;
-				path->nextin.tv_usec = f->delivery.tv_usec;
-				path->nextout.tv_sec += sdiff;
-				path->nextout.tv_usec += udiff;
-				if (path->nextout.tv_usec < 0) {
-					path->nextout.tv_usec += 1000000;
-					path->nextout.tv_sec--;
-				} else if (path->nextout.tv_usec >= 1000000) {
-					path->nextout.tv_usec -= 1000000;
-					path->nextout.tv_sec++;
-				}
+				path->nextout = ast_tvadd(path->nextout,
+					ast_tvsub(f->delivery, path->nextin));
+				path->nextin = f->delivery;
 			}
 		} else {
 			/* This is our first pass.  Make sure the timing looks good */
-			path->nextin.tv_sec = f->delivery.tv_sec;
-			path->nextin.tv_usec = f->delivery.tv_usec;
-			path->nextout.tv_sec = f->delivery.tv_sec;
-			path->nextout.tv_usec = f->delivery.tv_usec;
+			path->nextin = f->delivery;
+			path->nextout = f->delivery;
 		}
 		/* Predict next incoming sample */
-		path->nextin.tv_sec += (f->samples / 8000);
-		path->nextin.tv_usec += ((f->samples % 8000) * 125);
-		if (path->nextin.tv_usec >= 1000000) {
-			path->nextin.tv_usec -= 1000000;
-			path->nextin.tv_sec++;
-		}
+		path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000));
 	}
-	delivery.tv_sec = f->delivery.tv_sec;
-	delivery.tv_usec = f->delivery.tv_usec;
+	delivery = f->delivery;
 	if (consume)
 		ast_frfree(f);
 	while(p) {
@@ -200,22 +176,15 @@
 		if (p->next) 
 			p->next->step->framein(p->next->state, out);
 		else {
-			if (delivery.tv_sec || delivery.tv_usec) {
+			if (!ast_tvzero(delivery)) {
 				/* Use next predicted outgoing timestamp */
-				out->delivery.tv_sec = path->nextout.tv_sec;
-				out->delivery.tv_usec = path->nextout.tv_usec;
+				out->delivery = path->nextout;
 				
 				/* Predict next outgoing timestamp from samples in this
 				   frame. */
-				path->nextout.tv_sec += (out->samples / 8000);
-				path->nextout.tv_usec += ((out->samples % 8000) * 125);
-				if (path->nextout.tv_usec >= 1000000) {
-					path->nextout.tv_sec++;
-					path->nextout.tv_usec -= 1000000;
-				}
+				path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000));
 			} else {
-				out->delivery.tv_sec = 0;
-				out->delivery.tv_usec = 0;
+				out->delivery = ast_tv(0, 0);
 			}
 			return out;
 		}
@@ -231,7 +200,7 @@
 	int sofar=0;
 	struct ast_translator_pvt *pvt;
 	struct ast_frame *f, *out;
-	struct timeval start, finish;
+	struct timeval start;
 	int cost;
 	if(!samples)
 	  samples = 1;
@@ -248,7 +217,7 @@
 		t->cost = 99999;
 		return;
 	}
-	gettimeofday(&start, NULL);
+	start = ast_tvnow();
 	/* Call the encoder until we've processed one second of time */
 	while(sofar < samples * 8000) {
 		f = t->sample();
@@ -265,9 +234,8 @@
 			ast_frfree(out);
 		}
 	}
-	gettimeofday(&finish, NULL);
+	cost = ast_tvdiff(ast_tvnow(), start);
 	t->destroy(pvt);
-	cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
 	t->cost = cost / samples;
 	if (!t->cost)
 		t->cost = 1;
Index: utils.c
===================================================================
RCS file: /usr/cvsroot/asterisk/utils.c,v
retrieving revision 1.48
diff -u -r1.48 utils.c
--- utils.c	6 Jun 2005 22:12:18 -0000	1.48
+++ utils.c	10 Jun 2005 08:25:37 -0000
@@ -65,6 +100,65 @@
 
 	return s;
 }
+
+/*
+ * Here are routines to deal with struct timeval - add, sub,
+ * and compute difference into milliseconds
+ */
+long ast_tvdiff(struct timeval now, struct timeval then)
+{
+	return (now.tv_sec - then.tv_sec) * 1000 +
+		(now.tv_usec - then.tv_usec) / 1000;
+}
+
+#define ONE_MILLION	1000000
+/*
+ * put timeval in a valid range. usec is 0..999999
+ * negative values are not allowed and truncated.
+ */
+static struct timeval tvfix(struct timeval a)
+{
+	if (a.tv_usec >= ONE_MILLION) {
+		ast_log(LOG_ERROR, "warning too large timestamp %ld.%ld\n",
+			a.tv_sec, a.tv_usec);
+		a.tv_sec += a.tv_usec % ONE_MILLION;
+		a.tv_usec %= ONE_MILLION;
+	} else if (a.tv_usec < 0) {
+		ast_log(LOG_ERROR, "warning negative timestamp %ld.%ld\n",
+			a.tv_sec, a.tv_usec);
+		a.tv_usec = 0;
+	}
+	return a;
+}
+
+struct timeval ast_tvadd(struct timeval a, struct timeval b)
+{
+	/* consistency checks to guarantee usec in 0..999999 */
+	a = tvfix(a);
+	b = tvfix(b);
+	a.tv_sec += b.tv_sec;
+	a.tv_usec += b.tv_usec;
+	if (a.tv_usec >= ONE_MILLION) {
+		a.tv_sec++;
+		a.tv_usec -= ONE_MILLION;
+	}
+	return a;
+}
+
+struct timeval ast_tvsub(struct timeval a, struct timeval b)
+{
+	/* consistency checks to guarantee usec in 0..999999 */
+	a = tvfix(a);
+	b = tvfix(b);
+	a.tv_sec -= b.tv_sec;
+	a.tv_usec -= b.tv_usec;
+	if (a.tv_usec < 0) {
+		a.tv_sec-- ;
+		a.tv_usec += ONE_MILLION;
+	}
+	return a;
+}
+#undef ONE_MILLION
 
 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
 
Index: apps/app_alarmreceiver.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_alarmreceiver.c,v
retrieving revision 1.10
diff -u -r1.10 app_alarmreceiver.c
--- apps/app_alarmreceiver.c	6 Jun 2005 22:39:31 -0000	1.10
+++ apps/app_alarmreceiver.c	10 Jun 2005 08:25:38 -0000
@@ -219,20 +219,6 @@
 }
 
 /*
-* Return the difference in milliseconds between two timeval structs
-*/
-
-static int ms_diff(struct timeval *tv1, struct timeval *tv2){
-
-	int	ms;
-	
-	ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
-	ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
-	
-	return(ms);
-}
-
-/*
 * Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
 * treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
 * digits.
@@ -249,14 +235,12 @@
 	int i = 0;
 	int r;
 	struct ast_frame *f;
-	struct timeval now, lastdigittime;
+	struct timeval lastdigittime;
 	
-	gettimeofday(&lastdigittime,NULL);
+	lastdigittime = ast_tvnow();
 	for(;;){
-		gettimeofday(&now,NULL);
-		
 		  /* if outa time, leave */
-		if (ms_diff(&now,&lastdigittime) > 
+		if (ast_tvdiff(ast_tvnow(), lastdigittime) > 
 		    ((i > 0) ? sdto : fdto)){
 			if(option_verbose >= 4)
 				ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
Index: apps/app_disa.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_disa.c,v
retrieving revision 1.28
diff -u -r1.28 app_disa.c
--- apps/app_disa.c	6 Jun 2005 22:39:31 -0000	1.28
+++ apps/app_disa.c	10 Jun 2005 08:25:38 -0000
@@ -90,15 +90,6 @@
 
 LOCAL_USER_DECL;
 
-static int ms_diff(struct timeval *tv1, struct timeval *tv2)
-{
-int	ms;
-	
-	ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
-	ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
-	return(ms);
-}
-
 static void play_dialtone(struct ast_channel *chan, char *mailbox)
 {
 	const struct tone_zone_sound *ts = NULL;
@@ -121,7 +112,7 @@
 	char tmp[256],arg2[256]="",exten[AST_MAX_EXTENSION],acctcode[20]="";
 	char *ourcontext,*ourcallerid,ourcidname[256],ourcidnum[256],*mailbox;
 	struct ast_frame *f;
-	struct timeval lastout, now, lastdigittime;
+	struct timeval lastdigittime;
 	int res;
 	time_t rstart;
 	FILE *fp;
@@ -142,7 +133,6 @@
 		ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
 		return -1;
 	}
-	lastout.tv_sec = lastout.tv_usec = 0;
 	if (!data || !strlen((char *)data)) {
 		ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
 		return -1;
@@ -193,9 +183,8 @@
 
 	for(;;)
 	{
-		gettimeofday(&now,NULL);
 		  /* if outa time, give em reorder */
-		if (ms_diff(&now,&lastdigittime) > 
+		if (ast_tvdiff(ast_tvnow(), lastdigittime) > 
 		    ((k&2) ? digittimeout : firstdigittimeout))
 		{
 			ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
Index: apps/app_mp3.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_mp3.c,v
retrieving revision 1.25
diff -u -r1.25 app_mp3.c
--- apps/app_mp3.c	6 Jun 2005 22:39:31 -0000	1.25
+++ apps/app_mp3.c	10 Jun 2005 08:25:38 -0000
@@ -140,7 +140,7 @@
 		timeout = 10000;
 	}
 	/* Wait 1000 ms first */
-	next = now;
+	next = ast_tvnow();
 	next.tv_sec += 1;
 	if (res >= 0) {
 		pid = res;
@@ -148,21 +148,8 @@
 		   user */
 		for (;;) {
 			gettimeofday(&now, NULL);
-			ms = (next.tv_sec - now.tv_sec) * 1000;
-			ms += (next.tv_usec - now.tv_usec) / 1000;
-#if 0
-			printf("ms: %d\n", ms);
-#endif			
+			ms = ast_tvdiff(next, ast_tvnow());
 			if (ms <= 0) {
-#if 0
-				{
-					static struct timeval last;
-					struct timeval tv;
-					gettimeofday(&tv, NULL);
-					printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
-					last = tv;
-				}
-#endif
 				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
 				if (res > 0) {
 					myf.f.frametype = AST_FRAME_VOICE;
@@ -184,14 +171,7 @@
 					res = 0;
 					break;
 				}
-				next.tv_usec += res / 2 * 125;
-				if (next.tv_usec >= 1000000) {
-					next.tv_usec -= 1000000;
-					next.tv_sec++;
-				}
-#if 0
-				printf("Next: %d\n", ms);
-#endif				
+				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
 			} else {
 				ms = ast_waitfor(chan, ms);
 				if (ms < 0) {
Index: apps/app_nbscat.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_nbscat.c,v
retrieving revision 1.10
diff -u -r1.10 app_nbscat.c
--- apps/app_nbscat.c	6 Jun 2005 22:39:31 -0000	1.10
+++ apps/app_nbscat.c	10 Jun 2005 08:25:38 -0000
@@ -99,7 +99,7 @@
 	int ms = -1;
 	int pid = -1;
 	int owriteformat;
-	struct timeval now, next;
+	struct timeval next;
 	struct ast_frame *f;
 	struct myframe {
 		struct ast_frame f;
@@ -122,29 +122,15 @@
 	
 	res = NBScatplay(fds[1]);
 	/* Wait 1000 ms first */
-	next = now;
+	next = ast_tvnow();
 	next.tv_sec += 1;
 	if (res >= 0) {
 		pid = res;
 		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
 		   user */
 		for (;;) {
-			gettimeofday(&now, NULL);
-			ms = (next.tv_sec - now.tv_sec) * 1000;
-			ms += (next.tv_usec - now.tv_usec) / 1000;
-#if 0
-			printf("ms: %d\n", ms);
-#endif			
+			ms = ast_tvdiff(next, ast_tvnow());
 			if (ms <= 0) {
-#if 0
-				{
-					static struct timeval last;
-					struct timeval tv;
-					gettimeofday(&tv, NULL);
-					printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
-					last = tv;
-				}
-#endif
 				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
 				if (res > 0) {
 					myf.f.frametype = AST_FRAME_VOICE;
@@ -166,14 +152,7 @@
 					res = 0;
 					break;
 				}
-				next.tv_usec += res / 2 * 125;
-				if (next.tv_usec >= 1000000) {
-					next.tv_usec -= 1000000;
-					next.tv_sec++;
-				}
-#if 0
-				printf("Next: %d\n", ms);
-#endif				
+				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
 			} else {
 				ms = ast_waitfor(chan, ms);
 				if (ms < 0) {
Index: apps/app_talkdetect.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_talkdetect.c,v
retrieving revision 1.9
diff -u -r1.9 app_talkdetect.c
--- apps/app_talkdetect.c	6 Jun 2005 22:39:32 -0000	1.9
+++ apps/app_talkdetect.c	10 Jun 2005 08:25:38 -0000
@@ -59,7 +59,7 @@
 	char *stringp;
 	struct ast_frame *fr;
 	int notsilent=0;
-	struct timeval start = { 0, 0}, end = {0, 0};
+	struct timeval start = { 0, 0};
 	int sil = 1000;
 	int min = 100;
 	int max = -1;
@@ -143,9 +143,7 @@
 							/* We've been quiet a little while */
 							if (notsilent) {
 								/* We had heard some talking */
-								gettimeofday(&end, NULL);
-								ms = (end.tv_sec - start.tv_sec) * 1000;
-								ms += (end.tv_usec - start.tv_usec) / 1000;
+								ms = ast_tvdiff(ast_tvnow(), start);
 								ms -= sil;
 								if (ms < 0)
 									ms = 0;
Index: apps/app_test.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_test.c,v
retrieving revision 1.10
diff -u -r1.10 app_test.c
--- apps/app_test.c	6 Jun 2005 22:39:32 -0000	1.10
+++ apps/app_test.c	10 Jun 2005 08:25:39 -0000
@@ -55,7 +55,7 @@
 	int samples=0;
 	int x;
 	short *foo;
-	struct timeval start, tv;
+	struct timeval start;
 	struct ast_frame *f;
 	int rformat;
 	rformat = chan->readformat;
@@ -65,9 +65,7 @@
 	}
 	gettimeofday(&start, NULL);
 	for(;;) {
-		gettimeofday(&tv, NULL);
-		mssofar = (tv.tv_sec - start.tv_sec) * 1000;
-		mssofar += (tv.tv_usec - start.tv_usec) / 1000;
+		mssofar = ast_tvdiff(ast_tvnow(), start);
 		if (mssofar > ms)
 			break;
 		res = ast_waitfor(chan, ms - mssofar);
Index: cdr/cdr_csv.c
===================================================================
RCS file: /usr/cvsroot/asterisk/cdr/cdr_csv.c,v
retrieving revision 1.17
diff -u -r1.17 cdr_csv.c
--- cdr/cdr_csv.c	6 Jun 2005 22:12:18 -0000	1.17
+++ cdr/cdr_csv.c	10 Jun 2005 08:25:39 -0000
@@ -123,7 +123,7 @@
 	t = tv.tv_sec;
 	if (strlen(buf) > bufsize - 3)
 		return -1;
-	if (!tv.tv_sec && !tv.tv_usec) {
+	if (ast_tvzero(tv)) {
 		strncat(buf, ",", bufsize - strlen(buf) - 1);
 		return 0;
 	}
Index: cdr/cdr_tds.c
===================================================================
RCS file: /usr/cvsroot/asterisk/cdr/cdr_tds.c,v
retrieving revision 1.11
diff -u -r1.11 cdr_tds.c
--- cdr/cdr_tds.c	6 Jun 2005 23:12:05 -0000	1.11
+++ cdr/cdr_tds.c	10 Jun 2005 08:25:40 -0000
@@ -372,7 +372,7 @@
 	char buf[80];
 
 	/* To make sure we have date variable if not insert null to SQL */
-	if (tv.tv_sec && tv.tv_usec)
+	if (!ast_tvzero(tv))
 	{
 		t = tv.tv_sec;
 		localtime_r(&t, &tm);
Index: channels/chan_agent.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v
retrieving revision 1.138
diff -u -r1.138 chan_agent.c
--- channels/chan_agent.c	7 Jun 2005 17:06:33 -0000	1.138
+++ channels/chan_agent.c	10 Jun 2005 08:25:42 -0000
@@ -418,15 +418,8 @@
 				if (p->chan)
 					ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name);
 				ast_hangup(p->chan);
-				if (p->wrapuptime && p->acknowledged) {
-					gettimeofday(&p->lastdisc, NULL);
-					p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000;
-					if (p->lastdisc.tv_usec > 1000000) {
-						p->lastdisc.tv_usec -= 1000000;
-						p->lastdisc.tv_sec++;
-					}
-					p->lastdisc.tv_sec += (p->wrapuptime / 1000);
-				}
+				if (p->wrapuptime && p->acknowledged)
+					p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
 			}
 			p->chan = NULL;
 			p->acknowledged = 0;
@@ -680,16 +673,10 @@
 		/* If they're dead, go ahead and hang up on the agent now */
 		if (!ast_strlen_zero(p->loginchan)) {
 			/* Store last disconnect time */
-			if (p->wrapuptime && p->acknowledged) {
-				gettimeofday(&p->lastdisc, NULL);
-				p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000;
-				if (p->lastdisc.tv_usec >= 1000000) {
-					p->lastdisc.tv_usec -= 1000000;
-					p->lastdisc.tv_sec++;
-				}
-				p->lastdisc.tv_sec += (p->wrapuptime / 1000);
-			} else
-				memset(&p->lastdisc, 0, sizeof(p->lastdisc));
+			if (p->wrapuptime && p->acknowledged)
+				p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
+			else
+				p->lastdisc = ast_tv(0,0);
 			if (p->chan) {
 				/* Recognize the hangup and pass it along immediately */
 				ast_hangup(p->chan);
@@ -758,7 +745,7 @@
 			/* Not dead -- check availability now */
 			ast_mutex_lock(&p->lock);
 			/* Store last disconnect time */
-			gettimeofday(&p->lastdisc, NULL);
+			p->lastdisc = ast_tvnow();
 			ast_mutex_unlock(&p->lock);
 		}
 		/* Release ownership of the agent to other threads (presumably running the login app). */
@@ -770,7 +757,6 @@
 static int agent_cont_sleep( void *data )
 {
 	struct agent_pvt *p;
-	struct timeval tv;
 	int res;
 
 	p = (struct agent_pvt *)data;
@@ -778,9 +764,7 @@
 	ast_mutex_lock(&p->lock);
 	res = p->app_sleep_cond;
 	if (p->lastdisc.tv_sec) {
-		gettimeofday(&tv, NULL);
-		if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 + 
-			(tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime) 
+		if (ast_tvdiff(ast_tvnow(), p->lastdisc) > p->wrapuptime) 
 			res = 1;
 	}
 	ast_mutex_unlock(&p->lock);
@@ -1523,7 +1507,6 @@
 	int max_login_tries = maxlogintries;
 	struct agent_pvt *p;
 	struct localuser *u;
-	struct timeval tv;
 	int login_state = 0;
 	char user[AST_MAX_AGENT] = "";
 	char pass[AST_MAX_AGENT];
@@ -1848,9 +1831,7 @@
 								ast_mutex_lock(&agentlock);
 								ast_mutex_lock(&p->lock);
 								if (p->lastdisc.tv_sec) {
-									gettimeofday(&tv, NULL);
-									if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 + 
-										(tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime) {
+									if (ast_tvdiff(ast_tvnow(), p->lastdisc) > p->wrapuptime) {
 											if (option_debug)
 												ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent);
 										memset(&p->lastdisc, 0, sizeof(p->lastdisc));
Index: channels/chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.304
diff -u -r1.304 chan_iax2.c
--- channels/chan_iax2.c	6 Jun 2005 22:12:19 -0000	1.304
+++ channels/chan_iax2.c	10 Jun 2005 08:25:51 -0000
@@ -2080,12 +2080,8 @@
 
 static void update_jbsched(struct chan_iax2_pvt *pvt) {
     int when;
-    struct timeval tv;
-
-    gettimeofday(&tv,NULL);
 
-    when = (tv.tv_sec - pvt->rxcore.tv_sec) * 1000 +
-	  (tv.tv_usec - pvt->rxcore.tv_usec) / 1000;
+    when = ast_tvdiff(ast_tvnow(), pvt->rxcore);
 
     /*    fprintf(stderr, "now = %d, next=%d\n", when, jb_next(pvt->jb)); */
 
@@ -2122,8 +2118,7 @@
     /* to catch up with runq's now */
     tv.tv_usec += 1000;
 
-    now = (tv.tv_sec - pvt->rxcore.tv_sec) * 1000 +
-	  (tv.tv_usec - pvt->rxcore.tv_usec) / 1000;
+    now = ast_tvdiff(tv, pvt->rxcore);
 
     if(now >= (next = jb_next(pvt->jb))) {
 	ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
@@ -2148,15 +2143,8 @@
 		af.mallocd  = 0;
 		af.src  = "IAX2 JB interpolation";
 		af.data  = NULL;
-		af.delivery.tv_sec = pvt->rxcore.tv_sec;
-		af.delivery.tv_usec = pvt->rxcore.tv_usec;
-		af.delivery.tv_sec += next / 1000;
-		af.delivery.tv_usec += (next % 1000) * 1000;
+		af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
 		af.offset=AST_FRIENDLY_OFFSET;
-		if (af.delivery.tv_usec >= 1000000) {
-			af.delivery.tv_usec -= 1000000;
-			af.delivery.tv_sec += 1;
-		}
 
 		/* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
 		 * which we'd need to malloc, and then it would free it.  That seems like a drag */
@@ -2229,8 +2217,7 @@
 				ast_log(LOG_DEBUG, "schedule_delivery: call=%d: TS jumped.  resyncing rxcore (ts=%d, last=%d)\n",
 							fr->callno, fr->ts, iaxs[fr->callno]->last);
 			/* zap rxcore - calc_rxstamp will make a new one based on this frame */
-			iaxs[fr->callno]->rxcore.tv_sec = 0;
-			iaxs[fr->callno]->rxcore.tv_usec = 0;
+			iaxs[fr->callno]->rxcore = ast_tv(0, 0);
 			/* wipe "last" if stamps have jumped backwards */
 			if (x<0)
 				iaxs[fr->callno]->last = 0;
@@ -2257,23 +2244,15 @@
 
 
 	/* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
-	if ( (!fromtrunk) && (iaxs[fr->callno]->rxcore.tv_sec || iaxs[fr->callno]->rxcore.tv_usec) ) {
-		fr->af.delivery.tv_sec = iaxs[fr->callno]->rxcore.tv_sec;
-		fr->af.delivery.tv_usec = iaxs[fr->callno]->rxcore.tv_usec;
-		fr->af.delivery.tv_sec += fr->ts / 1000;
-		fr->af.delivery.tv_usec += (fr->ts % 1000) * 1000;
-		if (fr->af.delivery.tv_usec >= 1000000) {
-			fr->af.delivery.tv_usec -= 1000000;
-			fr->af.delivery.tv_sec += 1;
-		}
+	if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore)) {
+		fr->af.delivery = ast_tvadd(iaxs[fr->callno]->rxcore, ast_samp2tv(fr->ts, 1000));
 	}
 	else {
 #if 0
 		if (reallydeliver)
 			ast_log(LOG_DEBUG, "schedule_delivery: set delivery to 0 as we don't have an rxcore yet, or frame is from trunk.\n");
 #endif
-		fr->af.delivery.tv_sec = 0;
-		fr->af.delivery.tv_usec = 0;
+		fr->af.delivery = ast_tv(0,0);
 	}
 
 #ifndef NEWJB
@@ -3141,9 +3120,8 @@
 		if ((iaxs[callno0]->transferring == TRANSFER_RELEASED) && (iaxs[callno1]->transferring == TRANSFER_RELEASED)) {
 			/* Call has been transferred.  We're no longer involved */
 			gettimeofday(&tv, NULL);
-			if (!waittimer.tv_sec && !waittimer.tv_usec) {
-				waittimer.tv_sec = tv.tv_sec;
-				waittimer.tv_usec = tv.tv_usec;
+			if (ast_tvzero(waittimer)) {
+				waittimer = tv;
 			} else if (tv.tv_sec - waittimer.tv_sec > IAX_LINGER_TIMEOUT) {
 				c0->_softhangup |= AST_SOFTHANGUP_DEV;
 				c1->_softhangup |= AST_SOFTHANGUP_DEV;
@@ -3362,21 +3340,17 @@
 	long int ms, pred;
 
 	tpeer->trunkact = *tv;
-	mssincetx = (tv->tv_sec - tpeer->lasttxtime.tv_sec) * 1000 +
-			(1000000 + tv->tv_usec - tpeer->lasttxtime.tv_usec) / 1000 - 1000;
-	if (mssincetx > 5000 || (!tpeer->txtrunktime.tv_sec && !tpeer->txtrunktime.tv_usec)) {
+	mssincetx = ast_tvdiff(*tv, tpeer->lasttxtime);
+	if (mssincetx > 5000 || ast_tvzero(tpeer->txtrunktime)) {
 		/* If it's been at least 5 seconds since the last time we transmitted on this trunk, reset our timers */
-		tpeer->txtrunktime.tv_sec = tv->tv_sec;
-		tpeer->txtrunktime.tv_usec = tv->tv_usec;
+		tpeer->txtrunktime = *tv;
 		tpeer->lastsent = 999999;
 	}
 	/* Update last transmit time now */
-	tpeer->lasttxtime.tv_sec = tv->tv_sec;
-	tpeer->lasttxtime.tv_usec = tv->tv_usec;
+	tpeer->lasttxtime = *tv;
 	
 	/* Calculate ms offset */
-	ms = (tv->tv_sec - tpeer->txtrunktime.tv_sec) * 1000 +
-		(1000000 + tv->tv_usec - tpeer->txtrunktime.tv_usec) / 1000 - 1000;
+	ms = ast_tvdiff(*tv, tpeer->txtrunktime);
 	/* Predict from last value */
 	pred = tpeer->lastsent + sampms;
 	if (abs(ms - pred) < MAX_TIMESTAMP_SKEW)
@@ -3392,34 +3366,20 @@
 static unsigned int fix_peerts(struct timeval *tv, int callno, unsigned int ts)
 {
 	long ms;	/* NOT unsigned */
-	if (!iaxs[callno]->rxcore.tv_sec && !iaxs[callno]->rxcore.tv_usec) {
+	if (ast_tvzero(iaxs[callno]->rxcore)) {
 		/* Initialize rxcore time if appropriate */
 		gettimeofday(&iaxs[callno]->rxcore, NULL);
 		/* Round to nearest 20ms so traces look pretty */
 		iaxs[callno]->rxcore.tv_usec -= iaxs[callno]->rxcore.tv_usec % 20000;
 	}
 	/* Calculate difference between trunk and channel */
-	ms = (tv->tv_sec - iaxs[callno]->rxcore.tv_sec) * 1000 + 
-		(1000000 + tv->tv_usec - iaxs[callno]->rxcore.tv_usec) / 1000 - 1000;
+	ms = ast_tvdiff(*tv, iaxs[callno]->rxcore);
 	/* Return as the sum of trunk time and the difference between trunk and real time */
 	return ms + ts;
 }
 
-static void add_ms(struct timeval *tv, int ms) {
-	tv->tv_usec += ms * 1000;
-	if(tv->tv_usec > 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
-	if(tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
-}
-
 static unsigned int calc_timestamp(struct chan_iax2_pvt *p, unsigned int ts, struct ast_frame *f)
 {
-	struct timeval tv;
 	int ms;
 	int voice = 0;
 	int genuine = 0;
@@ -3442,7 +3402,7 @@
 			p->notsilenttx = 0;	
 		}
 	}
-	if (!p->offset.tv_sec && !p->offset.tv_usec) {
+	if (ast_tvzero(p->offset)) {
 		gettimeofday(&p->offset, NULL);
 		/* Round to nearest 20ms for nice looking traces */
 		p->offset.tv_usec -= p->offset.tv_usec % 20000;
@@ -3451,15 +3411,12 @@
 	if (ts)
 		return ts;
 	/* If we have a time that the frame arrived, always use it to make our timestamp */
-	if (delivery && (delivery->tv_sec || delivery->tv_usec)) {
-		ms = (delivery->tv_sec - p->offset.tv_sec) * 1000 +
-			(1000000 + delivery->tv_usec - p->offset.tv_usec) / 1000 - 1000;
+	if (delivery && !ast_tvzero(*delivery)) {
+		ms = ast_tvdiff(*delivery, p->offset);
 		if (option_debug > 2)
 			ast_log(LOG_DEBUG, "calc_timestamp: call %d/%d: Timestamp slaved to delivery time\n", p->callno, iaxs[p->callno]->peercallno);
 	} else {
-		gettimeofday(&tv, NULL);
-		ms = (tv.tv_sec - p->offset.tv_sec) * 1000 +
-			(1000000 + tv.tv_usec - p->offset.tv_usec) / 1000 - 1000;
+		ms = ast_tvdiff(ast_tvnow(), p->offset);
 		if (ms < 0)
 			ms = 0;
 		if (voice) {
@@ -3467,7 +3424,8 @@
 			if (p->notsilenttx && abs(ms - p->nextpred) <= MAX_TIMESTAMP_SKEW) {
 				/* Adjust our txcore, keeping voice and 
 					non-voice synchronized */
-				add_ms(&p->offset, (int)(ms - p->nextpred)/10);
+				p->offset = ast_tvadd(p->offset,
+						ast_samp2tv((ms - p->nextpred)/10, 1000)); /* XXX what scale is this ??? */
 
 				if (!p->nextpred) {
 					p->nextpred = ms; /*f->samples / 8;*/
@@ -3528,19 +3486,18 @@
 	/* Receive from p1, send to p2 */
 	
 	/* Setup rxcore if necessary on outgoing channel */
-	if (!p1->rxcore.tv_sec && !p1->rxcore.tv_usec)
-		gettimeofday(&p1->rxcore, NULL);
+	if (ast_tvzero(p1->rxcore))
+		p1->rxcore = ast_tvnow();
 
 	/* Setup txcore if necessary on outgoing channel */
-	if (!p2->offset.tv_sec && !p2->offset.tv_usec)
-		gettimeofday(&p2->offset, NULL);
+	if (ast_tvzero(p2->offset))
+		p2->offset = ast_tvnow();
 	
 	/* Now, ts is the timestamp of the original packet in the orignal context.
 	   Adding rxcore to it gives us when we would want the packet to be delivered normally.
 	   Subtracting txcore of the outgoing channel gives us what we'd expect */
 	
-	ms = (p1->rxcore.tv_sec - p2->offset.tv_sec) * 1000 +
-		(1000000 + p1->rxcore.tv_usec - p2->offset.tv_usec) / 1000 - 1000;
+	ms = ast_tvdiff(p1->rxcore, p2->offset);
 	fakets += ms;
 
 	/* FIXME? SLD would rather remove this and leave it to the end system to deal with */
@@ -3555,23 +3512,17 @@
 {
 	/* Returns where in "receive time" we are.  That is, how many ms
 	   since we received (or would have received) the frame with timestamp 0 */
-	struct timeval tv;
 	int ms;
 #ifdef IAXTESTS
 	int jit;
 #endif /* IAXTESTS */
 	/* Setup rxcore if necessary */
-	if (!p->rxcore.tv_sec && !p->rxcore.tv_usec) {
-		gettimeofday(&p->rxcore, NULL);
+	if (ast_tvzero(p->rxcore)) {
+		p->rxcore = ast_tvnow();
 		if (option_debug)
 			ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: rxcore set to %d.%6.6d - %dms\n",
 					p->callno, (int)(p->rxcore.tv_sec), (int)(p->rxcore.tv_usec), offset);
-		p->rxcore.tv_sec -= offset / 1000;
-		p->rxcore.tv_usec -= (offset % 1000) * 1000;
-		if (p->rxcore.tv_usec < 0) {
-			p->rxcore.tv_usec += 1000000;
-			p->rxcore.tv_sec -= 1;
-		}
+		p->rxcore = ast_tvsub(p->rxcore, ast_samp2tv(offset, 1000));
 #if 1
 		if (option_debug)
 			ast_log(LOG_DEBUG, "calc_rxstamp: call=%d: works out as %d.%6.6d\n",
@@ -3579,9 +3530,7 @@
 #endif
 	}
 
-	gettimeofday(&tv, NULL);
-	ms = (tv.tv_sec - p->rxcore.tv_sec) * 1000 +
-		(1000000 + tv.tv_usec - p->rxcore.tv_usec) / 1000 - 1000;
+	ms = ast_tvdiff(ast_tvnow(), p->rxcore);
 #ifdef IAXTESTS
 	if (test_jit) {
 		if (!test_jitpct || ((100.0 * rand() / (RAND_MAX + 1.0)) < test_jitpct)) {
@@ -3621,7 +3570,7 @@
 			ast_mutex_init(&tpeer->lock);
 			tpeer->lastsent = 9999;
 			memcpy(&tpeer->addr, sin, sizeof(tpeer->addr));
-			gettimeofday(&tpeer->trunkact, NULL);
+			tpeer->trunkact = ast_tvnow();
 			ast_mutex_lock(&tpeer->lock);
 			tpeer->next = tpeers;
 			tpeer->sockfd = fd;
@@ -6176,11 +6125,9 @@
 				ast_log(LOG_WARNING, "Unable to accept trunked packet from '%s:%d': No matching peer\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
 				return 1;
 			}
-			if (!ts || (!tpeer->rxtrunktime.tv_sec && !tpeer->rxtrunktime.tv_usec)) {
-				gettimeofday(&tpeer->rxtrunktime, NULL);
-				tpeer->trunkact = tpeer->rxtrunktime;
-			} else
-				gettimeofday(&tpeer->trunkact, NULL);
+			tpeer->trunkact = ast_tvnow();
+			if (!ts || ast_tvzero(tpeer->rxtrunktime))
+				tpeer->rxtrunktime = tpeer->trunkact;
 			rxtrunktime = tpeer->rxtrunktime;
 			ast_mutex_unlock(&tpeer->lock);
 			while(res >= sizeof(struct ast_iax2_meta_trunk_entry)) {
@@ -8602,8 +8549,7 @@
 	while(dp) {
 		next = dp->next;
 		/* Expire old caches */
-		if ((tv.tv_sec > dp->expirey.tv_sec) ||
-				((tv.tv_sec == dp->expirey.tv_sec) && (tv.tv_usec > dp->expirey.tv_usec)))  {
+		if (ast_tvcmp(tv, dp->expirey) > 0) {
 				/* It's expired, let it disappear */
 				if (prev)
 					prev->next = dp->next;
Index: channels/chan_phone.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_phone.c,v
retrieving revision 1.53
diff -u -r1.53 chan_phone.c
--- channels/chan_phone.c	6 Jun 2005 22:12:19 -0000	1.53
+++ channels/chan_phone.c	10 Jun 2005 08:25:57 -0000
@@ -446,8 +446,7 @@
 	p->fr.src = type;
 	p->fr.offset = 0;
 	p->fr.mallocd=0;
-	p->fr.delivery.tv_sec = 0;
-	p->fr.delivery.tv_usec = 0;
+	p->fr.delivery = ast_tv(0,0);
 	
 	phonee.bytes = ioctl(p->fd, PHONE_EXCEPTION);
 	if (phonee.bits.dtmf_ready)  {
@@ -509,8 +508,7 @@
 	p->fr.src = type;
 	p->fr.offset = 0;
 	p->fr.mallocd=0;
-	p->fr.delivery.tv_sec = 0;
-	p->fr.delivery.tv_usec = 0;
+	p->fr.delivery = ast_tv(0,0);
 
 	/* Try to read some data... */
 	CHECK_BLOCKING(ast);
@@ -993,7 +991,7 @@
 				if (i->dialtone) {
 					/* Remember we're going to have to come back and play
 					   more dialtones */
-					if (!tv.tv_usec && !tv.tv_sec) {
+					if (ast_tvzero(tv)) {
 						/* If we're due for a dialtone, play one */
 						if (write(i->fd, DialTone + tonepos, 240) != 240)
 							ast_log(LOG_WARNING, "Dial tone write error\n");
@@ -1016,15 +1014,13 @@
 			tonepos += 240;
 			if (tonepos >= sizeof(DialTone))
 					tonepos = 0;
-			if (!tv.tv_usec && !tv.tv_sec) {
-				tv.tv_usec = 30000;
-				tv.tv_sec = 0;
+			if (ast_tvzero(tv)) {
+				tv = ast_tv(30000, 0);
 			}
 			res = ast_select(n + 1, &rfds, NULL, &efds, &tv);
 		} else {
 			res = ast_select(n + 1, &rfds, NULL, &efds, NULL);
-			tv.tv_usec = 0;
-			tv.tv_sec = 0;
+			tv = ast_tv(0,0);
 			tonepos = 0;
 		}
 		/* Okay, select has finished.  Let's see what happened.  */
Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.757
diff -u -r1.757 chan_sip.c
--- channels/chan_sip.c	7 Jun 2005 17:06:33 -0000	1.757
+++ channels/chan_sip.c	10 Jun 2005 08:26:08 -0000
@@ -8282,8 +8193,7 @@
 		int newstate = 0;
 		peer = p->peerpoke;
 		gettimeofday(&tv, NULL);
-		pingtime = (tv.tv_sec - peer->ps.tv_sec) * 1000 +
-					(tv.tv_usec - peer->ps.tv_usec) / 1000;
+		pingtime = ast_tvdiff(tv, peer->ps);
 		if (pingtime < 1)
 			pingtime = 1;
 		if ((peer->lastms < 0)  || (peer->lastms > peer->maxms)) {
Index: channels/chan_vpb.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_vpb.c,v
retrieving revision 1.86
diff -u -r1.86 chan_vpb.c
--- channels/chan_vpb.c	8 Jun 2005 00:10:09 -0000	1.86
+++ channels/chan_vpb.c	10 Jun 2005 08:26:11 -0000
@@ -292,7 +292,7 @@
 
 	struct ast_dsp *vad;			/* AST  Voice Activation Detection dsp */
 
-	double lastgrunt;			/* time stamp (secs since epoc) of last grunt event */
+	struct timeval lastgrunt;			/* time stamp of last grunt event */
 
 	ast_mutex_t lock;			/* This one just protects bridge ptr below */
 	vpb_bridge_t *bridge;
@@ -583,13 +583,6 @@
 	return (res==VPB_OK)?0:-1;
 }
 
-static double get_time_in_ms()
-{
-	struct timeval tv;
-	gettimeofday(&tv, NULL);
-	return ((double)tv.tv_sec*1000)+((double)tv.tv_usec/1000);
-}
-
 /* Caller ID can be located in different positions between the rings depending on your Telco
  * Australian (Telstra) callerid starts 700ms after 1st ring and finishes 1.5s after first ring
  * Use ANALYSE_CID to record rings and determine location of callerid
@@ -601,7 +594,7 @@
 static void get_callerid(struct vpb_pvt *p)
 {
 	short buf[CID_MSECS*8]; /* 8kHz sampling rate */
-	double cid_record_time;
+	struct timeval cid_record_time;
 	int rc;
 	struct ast_channel *owner = p->owner;
 	void * ws;
@@ -612,7 +605,7 @@
 
 		char callerid[AST_MAX_EXTENSION] = ""; 
 
-		cid_record_time = get_time_in_ms();
+		cid_record_time = ast_tvnow();
 		if (option_verbose>3) 
 			ast_verbose(VERBOSE_PREFIX_4 "CID record - start\n");
 
@@ -620,9 +613,9 @@
 		vpb_sleep(RING_SKIP);
 
 		if (option_verbose>3) 
-			ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %fms trailing ring\n",
-				 get_time_in_ms() - cid_record_time);
-		cid_record_time = get_time_in_ms();
+			ast_verbose(VERBOSE_PREFIX_4 "CID record - skipped %ldms trailing ring\n",
+				 ast_tvdiff(ast_tvnow(), cid_record_time));
+		cid_record_time = ast_tvnow();
 
 		/* Record bit between the rings which contains the callerid */
 		vpb_record_buf_start(p->handle, VPB_LINEAR);
@@ -635,8 +628,8 @@
 #endif
 
 		if (option_verbose>3) 
-			ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %fms between rings\n", 
-				get_time_in_ms() - cid_record_time);
+			ast_verbose(VERBOSE_PREFIX_4 "CID record - recorded %ldms between rings\n", 
+				 ast_tvdiff(ast_tvnow(), cid_record_time));
 
 		ast_mutex_unlock(&p->record_lock);
 
@@ -903,7 +896,7 @@
 
 			} 
 			else if (e->data == VPB_GRUNT) {
-				if( ( get_time_in_ms() - p->lastgrunt ) > gruntdetect_timeout ) {
+				if( ( ast_tvdiff(ast_tvnow(), p->lastgrunt) > gruntdetect_timeout ) {
 					/* Nothing heard on line for a very long time
 					 * Timeout connection */
 					if (option_verbose > 2) 
@@ -911,7 +904,7 @@
 					ast_log(LOG_NOTICE,"%s: Line hangup due of lack of conversation\n",p->dev); 
 					f.subclass = AST_CONTROL_HANGUP;
 				} else {
-					p->lastgrunt = get_time_in_ms();
+					p->lastgrunt = ast_tvnow();
 					f.frametype = -1;
 				}
 			} 
@@ -2178,7 +2171,7 @@
 {
 	struct vpb_pvt *p = (struct vpb_pvt *)ast->tech_pvt; 
 	int res = 0, fmt = 0;
-	struct timeval play_buf_time_start,play_buf_time_finish;
+	struct timeval play_buf_time_start;
 /*	ast_mutex_lock(&p->lock); */
 	if(option_verbose>5) 
 		ast_verbose("%s: vpb_write: Writing to channel\n", p->dev);
@@ -2234,25 +2227,14 @@
 
 /*	ast_log(LOG_DEBUG, "%s: vpb_write: Applied gain..\n", p->dev); */
 
-/*	gettimeofday(&tv, NULL); */
-/*	return ((double)tv.tv_sec*1000)+((double)tv.tv_usec/1000); */
-
 	if ((p->read_state == 1)&&(p->play_buf_time<5)){
-	gettimeofday(&play_buf_time_start,NULL);
-	res = vpb_play_buf_sync(p->handle, (char*)frame->data, frame->datalen);
-	if( (res == VPB_OK) && (option_verbose > 5) ) {
-		short * data = (short*)frame->data;
-		ast_verbose("%s: vpb_write: Wrote chan (codec=%d) %d %d\n", p->dev, fmt, data[0],data[1]);
-	}
-	gettimeofday(&play_buf_time_finish,NULL);
-	if (play_buf_time_finish.tv_sec == play_buf_time_start.tv_sec){
-		p->play_buf_time=(int)((play_buf_time_finish.tv_usec-play_buf_time_start.tv_usec)/1000);
-/*		ast_log(LOG_DEBUG, "%s: vpb_write: Timing start(%d) finish(%d)\n", p->dev,play_buf_time_start.tv_usec,play_buf_time_finish.tv_usec); */
-	}
-	else {
-		p->play_buf_time=(int)((play_buf_time_finish.tv_sec - play_buf_time_start.tv_sec)*100)+(int)((play_buf_time_finish.tv_usec-play_buf_time_start.tv_usec)/1000);
-	}
-/*	ast_log(LOG_DEBUG, "%s: vpb_write: Wrote data [%d](%d=>%s) to play_buf in [%d]ms..\n", p->dev,frame->datalen,fmt,ast2vpbformatname(frame->subclass),p->play_buf_time); */
+		play_buf_time_start = ast_tvnow();
+		res = vpb_play_buf_sync(p->handle, (char*)frame->data, frame->datalen);
+		if( (res == VPB_OK) && (option_verbose > 5) ) {
+			short * data = (short*)frame->data;
+			ast_verbose("%s: vpb_write: Wrote chan (codec=%d) %d %d\n", p->dev, fmt, data[0],data[1]);
+		}
+		p->play_buf_time = ast_tvdiff(ast_tvnow(), play_buf_time_start);
 	}
 	else {
 		p->chuck_count++;
@@ -2588,7 +2570,7 @@
 		me->play_dtmf[0] = '\0';
 		me->faxhandled =0;
 		
-		me->lastgrunt  = get_time_in_ms(); /* Assume at least one grunt tone seen now. */
+		me->lastgrunt  = ast_tvnow(); /* Assume at least one grunt tone seen now. */
 
 		ast_mutex_lock(&usecnt_lock);
 		usecnt++;
Index: channels/chan_zap.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_zap.c,v
retrieving revision 1.460
diff -u -r1.460 chan_zap.c
--- channels/chan_zap.c	7 Jun 2005 21:13:35 -0000	1.460
+++ channels/chan_zap.c	10 Jun 2005 08:26:21 -0000
@@ -3446,7 +3446,6 @@
 							p->dialing = 1;
 						zt_ring_phone(p);
 					} else if (p->subs[SUB_THREEWAY].owner) {
-						struct timeval tv;
 						unsigned int mssinceflash;
 						/* Here we have to retain the lock on both the main channel, the 3-way channel, and
 						   the private structure -- not especially easy or clean */
@@ -3469,8 +3468,7 @@
 							ast_log(LOG_NOTICE, "Whoa, threeway disappeared kinda randomly.\n");
 							return NULL;
 						}
-						gettimeofday(&tv, NULL);
-						mssinceflash = (tv.tv_sec - p->flashtime.tv_sec) * 1000 + (tv.tv_usec - p->flashtime.tv_usec) / 1000;
+						mssinceflash = ast_tvdiff(ast_tvnow(), p->flashtime);
 						ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
 						if (mssinceflash < MIN_MS_SINCE_FLASH) {
 							/* It hasn't been long enough since the last flashook.  This is probably a bounce on 
@@ -3946,10 +3944,8 @@
 				(p->polarityonanswerdelay > 0) &&
 			        (p->polarity == POLARITY_REV) &&
 				(ast->_state == AST_STATE_UP)) {
-				struct timeval tv;
-				gettimeofday(&tv, NULL);
 
-				if((((tv.tv_sec - p->polaritydelaytv.tv_sec) * 1000) + ((tv.tv_usec - p->polaritydelaytv.tv_usec)/1000)) > p->polarityonanswerdelay) {
+				if(ast_tvdiff(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
 					ast_log(LOG_DEBUG, "Hangup due to Reverse Polarity on channel %d\n", p->channel);
 					ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
 					p->polarity = POLARITY_IDLE;
@@ -3986,8 +3982,7 @@
 	p->subs[index].f.mallocd = 0;
 	p->subs[index].f.offset = 0;
 	p->subs[index].f.subclass = 0;
-	p->subs[index].f.delivery.tv_sec = 0;
-	p->subs[index].f.delivery.tv_usec = 0;
+	p->subs[index].f.delivery = ast_tv(0,0);
 	p->subs[index].f.src = "zt_exception";
 	p->subs[index].f.data = NULL;
 	
@@ -4112,8 +4107,7 @@
 	p->subs[index].f.mallocd = 0;
 	p->subs[index].f.offset = 0;
 	p->subs[index].f.subclass = 0;
-	p->subs[index].f.delivery.tv_sec = 0;
-	p->subs[index].f.delivery.tv_usec = 0;
+	p->subs[index].f.delivery = ast_tv(0,0);
 	p->subs[index].f.src = "zt_read";
 	p->subs[index].f.data = NULL;
 	
@@ -7702,15 +7696,11 @@
 #if 0
 			printf("nextidle: %d, haveidles: %d, minunsed: %d\n",
 				nextidle, haveidles, minunused);
-			gettimeofday(&tv, NULL);
 			printf("nextidle: %d, haveidles: %d, ms: %ld, minunsed: %d\n",
-				nextidle, haveidles, (tv.tv_sec - lastidle.tv_sec) * 1000 +
-				    (tv.tv_usec - lastidle.tv_usec) / 1000, minunused);
+				nextidle, haveidles, ast_tvdiff(ast_tvnow(), lastidle), minunused);
 #endif
 			if (nextidle > -1) {
-				gettimeofday(&tv, NULL);
-				if (((tv.tv_sec - lastidle.tv_sec) * 1000 +
-				    (tv.tv_usec - lastidle.tv_usec) / 1000) > 1000) {
+				if (ast_tvdiff(ast_tvnow(), lastidle) > 1000) {
 					/* Don't create a new idle call more than once per second */
 					snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
 					idle = zt_request("Zap", AST_FORMAT_ULAW, idlen, &cause);
@@ -7743,49 +7733,36 @@
 			}
 		}
 		/* Start with reasonable max */
-		lowest.tv_sec = 60;
-		lowest.tv_usec = 0;
+		lowest = ast_tv(60, 0);
 		for (i=0; i<NUM_DCHANS; i++) {
 			/* Find lowest available d-channel */
 			if (!pri->dchannels[i])
 				break;
 			if ((next = pri_schedule_next(pri->dchans[i]))) {
 				/* We need relative time here */
-				gettimeofday(&tv, NULL);
-				tv.tv_sec = next->tv_sec - tv.tv_sec;
-				tv.tv_usec = next->tv_usec - tv.tv_usec;
-				if (tv.tv_usec < 0) {
-					tv.tv_usec += 1000000;
-					tv.tv_sec -= 1;
-				}
+				tv = ast_tvdiff(*next, ast_tvnow());
 				if (tv.tv_sec < 0) {
-					tv.tv_sec = 0;
-					tv.tv_usec = 0;
+					tv = ast_tv(0,0);
 				}
 				if (doidling || pri->resetting) {
 					if (tv.tv_sec > 1) {
-						tv.tv_sec = 1;
-						tv.tv_usec = 0;
+						tv = ast_tv(1, 0);
 					}
 				} else {
 					if (tv.tv_sec > 60) {
-						tv.tv_sec = 60;
-						tv.tv_usec = 0;
+						tv = ast_tv(60, 0);
 					}
 				}
 			} else if (doidling || pri->resetting) {
 				/* Make sure we stop at least once per second if we're
 				   monitoring idle channels */
-				tv.tv_sec = 1;
-				tv.tv_usec = 0;
+				tv = ast_tv(1,0);
 			} else {
 				/* Don't poll for more than 60 seconds */
-				tv.tv_sec = 60;
-				tv.tv_usec = 0;
+				tv = ast_tv(60, 0);
 			}
-			if (!i || (tv.tv_sec < lowest.tv_sec) || ((tv.tv_sec == lowest.tv_sec) && (tv.tv_usec < lowest.tv_usec))) {
-				lowest.tv_sec = tv.tv_sec;
-				lowest.tv_usec = tv.tv_usec;
+			if (!i || ast_tvcmp(tv, lowest) < 0) {
+				lowest = tv;
 			}
 		}
 		ast_mutex_unlock(&pri->lock);
Index: funcs/func_strings.c
===================================================================
RCS file: /usr/cvsroot/asterisk/funcs/func_strings.c,v
retrieving revision 1.5
diff -u -r1.5 func_strings.c
--- funcs/func_strings.c	6 Jun 2005 22:12:19 -0000	1.5
+++ funcs/func_strings.c	10 Jun 2005 08:26:24 -0000
@@ -127,7 +127,6 @@
 {
 	char *format, *epoch, *timezone;
 	long epochi;
-	struct timeval tv;
 	struct tm time;
 
 	if (data) {
@@ -137,11 +136,9 @@
 			timezone = strsep(&format, "|");
 
 			if (epoch && !ast_strlen_zero(epoch) && sscanf(epoch, "%ld", &epochi) == 1) {
-			} else if (!gettimeofday(&tv, NULL)) {
-				epochi = tv.tv_sec;
 			} else {
-				ast_log(LOG_ERROR, "Cannot gettimeofday() ?!!\n");
-				return "";
+				struct timeval tv = ast_tvnow();
+				epochi = tv.tv_sec;
 			}
 
 			ast_localtime(&epochi, &time, timezone);
Index: include/asterisk/utils.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/utils.h,v
retrieving revision 1.32
diff -u -r1.32 utils.h
--- include/asterisk/utils.h	7 Jun 2005 17:06:33 -0000	1.32
+++ include/asterisk/utils.h	10 Jun 2005 08:26:25 -0000
@@ -132,6 +132,88 @@
 };
 
 /*!
+ Returns the difference in milliseconds between two struct timeval
+ */
+long ast_tvdiff(struct timeval now, struct timeval then);
+
+/*!
+ Returns true if the timestamp is 0,0
+ */
+static inline int ast_tvzero(struct timeval _t) {
+	return (_t.tv_sec == 0 && _t.tv_usec == 0);
+}
+
+/*!
+ Compares timestamps
+ */
+static inline int ast_tvcmp(struct timeval _a, struct timeval _b) {
+	if (_a.tv_sec < _b.tv_sec)
+		return -1;
+	if (_a.tv_sec > _b.tv_sec)
+		return 1;
+	/* now seconds are equal */
+	if (_a.tv_usec < _b.tv_usec)
+		return -1;
+	if (_a.tv_usec > _b.tv_usec)
+		return 1;
+	return 0;
+}
+
+static inline int ast_tveq(struct timeval _a, struct timeval _b) {
+	return (_a.tv_sec == _b.tv_sec && _a.tv_usec == _b.tv_usec);
+}
+
+/*!
+ Returns a timeval from sec - usec
+ */
+static inline struct timeval ast_tv(int _s, int _us) {
+	struct timeval t = { _s, _us};
+	return t;
+}
+
+/*!
+ Returns a timeval from nsamples and rate
+ */
+static inline struct timeval ast_samp2tv(long _nsamp, long _rate) {
+	return ast_tv(_nsamp / _rate, (_nsamp % _rate) * (1000000 / _rate));
+}
+
+/*!
+ Returns current timeval
+ */
+static inline struct timeval ast_tvnow(void) {
+	struct timeval t;
+	gettimeofday(&t, NULL);
+	return t;
+}
+
+/*!
+ Returns the sum of two timevals
+ */
+struct timeval ast_tvadd(struct timeval a, struct timeval b);
+
+/*!
+ Returns the difference of two timevals
+ */
+struct timeval ast_tvsub(struct timeval a, struct timeval b);
+
+/*!
+ Advance the pointer past the 'blanks' (chars <= 33).
+ A NULL argument is acceptable, it returns NULL in case.
+*/
+char *ast_skip_blanks(char *c);
+
+/*!
+   Remove trailing blanks. A NULL arg is acceptable.
+ */
+char *ast_trim_blanks(char *c);
+
+/*!
+   Skip all non-blank characters.
+*/
+char *ast_skip_nonblanks(char *c);
+
+/*!
   \brief Strip leading/trailing whitespace from a string.
   \param s The string to be stripped (will be modified).
   \return The stripped string.
Index: pbx/pbx_dundi.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx/pbx_dundi.c,v
retrieving revision 1.37
diff -u -r1.37 pbx_dundi.c
--- pbx/pbx_dundi.c	7 Jun 2005 17:06:33 -0000	1.37
+++ pbx/pbx_dundi.c	10 Jun 2005 08:26:29 -0000
@@ -679,13 +679,6 @@
 	return NULL;	
 }
 
-static inline int calc_ms(struct timeval *start)
-{
-	struct timeval tv;
-	gettimeofday(&tv, NULL);
-	return ((tv.tv_sec - start->tv_sec) * 1000 + (tv.tv_usec - start->tv_usec) / 1000);
-}
-
 static int dundi_query_eid_internal(struct dundi_entity_info *dei, const char *dcontext, dundi_eid *eid, struct dundi_hint_metadata *hmd, int ttl, int blockempty, dundi_eid *avoid[]);
 
 static void *dundi_query_thread(void *data)
@@ -2301,7 +2294,7 @@
 		*context = '\0';
 		context++;
 	}
-	gettimeofday(&start, NULL);
+	start = ast_tvnow();
 	res = dundi_lookup(dr, MAX_RESULTS, NULL, context, tmp, bypass);
 	
 	if (res < 0) 
@@ -2314,7 +2307,7 @@
 		ast_cli(fd, "%3d. %5d %s/%s (%s)\n", x + 1, dr[x].weight, dr[x].tech, dr[x].dest, dundi_flags2str(fs, sizeof(fs), dr[x].flags));
 		ast_cli(fd, "     from %s, expires in %d s\n", dr[x].eid_str, dr[x].expiration);
 	}
-	ast_cli(fd, "DUNDi lookup completed in %d ms\n", calc_ms(&start));
+	ast_cli(fd, "DUNDi lookup completed in %ld ms\n", ast_tvdiff(ast_tvnow(), start));
 	return RESULT_SUCCESS;
 }
 
@@ -2332,14 +2325,14 @@
 		*context = '\0';
 		context++;
 	}
-	gettimeofday(&start, NULL);
+	start = ast_tvnow();
 	res = dundi_precache(context, tmp);
 	
 	if (res < 0) 
 		ast_cli(fd, "DUNDi precache returned error.\n");
 	else if (!res) 
 		ast_cli(fd, "DUNDi precache returned no error.\n");
-	ast_cli(fd, "DUNDi lookup completed in %d ms\n", calc_ms(&start));
+	ast_cli(fd, "DUNDi lookup completed in %ld ms\n", ast_tvdiff(ast_tvnow(), start));
 	return RESULT_SUCCESS;
 }
 
@@ -2778,7 +2771,7 @@
 	if (trans) {
 		memset(trans, 0, sizeof(struct dundi_transaction));
 		if (global_storehistory) {
-			gettimeofday(&trans->start, NULL);
+			trans->start = ast_tvnow();
 			ast_set_flag(trans, FLAG_STOREHIST);
 		}
 		trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
@@ -2844,7 +2837,6 @@
 {
 	struct dundi_transaction *cur, *prev;
 	struct dundi_peer *peer;
-	struct timeval tv;
 	int ms;
 	int x;
 	int cnt;
@@ -2862,9 +2854,7 @@
 						ast_log(LOG_NOTICE, "Peer '%s' has become UNREACHABLE!\n", dundi_eid_to_str(eid_str, sizeof(eid_str), &peer->eid));
 					peer->lastms = -1;
 				} else {
-					gettimeofday(&tv, NULL);
-					ms = (tv.tv_sec - peer->qualtx.tv_sec) * 1000 + 
-							(tv.tv_usec - peer->qualtx.tv_usec) / 1000;
+					ms = ast_tvdiff(ast_tvnow(), peer->qualtx);
 					if (ms < 1)
 						ms = 1;
 					if (ms < peer->maxms) {
@@ -2892,7 +2882,7 @@
 								cnt++;
 							}
 						}
-						peer->lookuptimes[0] = calc_ms(&trans->start);
+						peer->lookuptimes[0] = ast_tvdiff(ast_tvnow(), trans->start);
 						peer->lookups[0] = malloc(strlen(trans->parent->number) + strlen(trans->parent->dcontext) + 2);
 						if (peer->lookups[0]) {
 							sprintf(peer->lookups[0], "%s@%s", trans->parent->number, trans->parent->dcontext);
@@ -3576,9 +3566,10 @@
 			/* Wait for the cache to populate */
 			ast_log(LOG_DEBUG, "Waiting for similar request for '%s@%s' for '%s'\n",
 				dr.number,dr.dcontext,dundi_eid_to_str(eid_str, sizeof(eid_str), &pending->root_eid));
-			gettimeofday(&start, NULL);
-			while(check_request(pending) && (calc_ms(&start) < ttlms) && (!chan || !chan->_softhangup)) {
+			start = ast_tvnow();
+			while(check_request(pending) && (ast_tvdiff(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
 				/* XXX Would be nice to have a way to poll/select here XXX */
+				/* XXX this is a busy wait loop!!! */
 				usleep(1);
 			}
 			/* Continue on as normal, our cache should kick in */
@@ -3608,8 +3599,8 @@
 	/* Actually perform transactions */
 	discover_transactions(&dr);
 	/* Wait for transaction to come back */
-	gettimeofday(&start, NULL);
-	while(dr.trans && (calc_ms(&start) < ttlms) && (!chan || !chan->_softhangup)) {
+	start = ast_tvnow();
+	while(dr.trans && (ast_tvdiff(ast_tvnow(), start) < ttlms) && (!chan || !chan->_softhangup)) {
 		ms = 100;
 		ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
 	}
@@ -3766,8 +3757,8 @@
 		else
 			ast_log(LOG_NOTICE, "Weird, expiration = %d, but need to precache for %s@%s?!\n", dr.expiration, dr.number, dr.dcontext);
 	}
-	gettimeofday(&start, NULL);
-	while(dr.trans && (calc_ms(&start) < ttlms)) {
+	start = ast_tvnow();
+	while(dr.trans && (ast_tvdiff(ast_tvnow(), start) < ttlms)) {
 		if (dr.pfds[0] > -1) {
 			ms = 100;
 			ast_waitfor_n_fd(dr.pfds, 1, &ms, NULL);
@@ -3828,8 +3819,8 @@
 	/* Actually perform transactions */
 	query_transactions(&dr);
 	/* Wait for transaction to come back */
-	gettimeofday(&start, NULL);
-	while(dr.trans && (calc_ms(&start) < ttlms))
+	start = ast_tvnow();
+	while(dr.trans && (ast_tvdiff(ast_tvnow(), start) < ttlms))
 		usleep(1);
 	res = dr.respcount;
 	return res;
@@ -4149,7 +4140,7 @@
 		if (!schedonly)
 			peer->qualtrans = create_transaction(peer);
 		if (peer->qualtrans) {
-			gettimeofday(&peer->qualtx, NULL);
+			peer->qualtx = ast_tvnow();
 			ast_set_flag(peer->qualtrans, FLAG_ISQUAL);
 			dundi_send(peer->qualtrans, DUNDI_COMMAND_NULL, 0, 1, NULL);
 		}
Index: pbx/pbx_gtkconsole.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx/pbx_gtkconsole.c,v
retrieving revision 1.17
diff -u -r1.17 pbx_gtkconsole.c
--- pbx/pbx_gtkconsole.c	6 Jun 2005 22:12:19 -0000	1.17
+++ pbx/pbx_gtkconsole.c	10 Jun 2005 08:26:30 -0000
@@ -107,12 +107,12 @@
 	if (replacelast) 
 		gtk_clist_remove(GTK_CLIST(verb), GTK_CLIST(verb)->rows - 1);
 	gtk_clist_append(GTK_CLIST(verb), s2);
-	if (last.tv_sec || last.tv_usec) {
+	if (!ast_tvzero(last)) {
 		gdk_threads_leave();
 		gettimeofday(&tv, NULL);
 		if (cleanupid > -1)
 			gtk_timeout_remove(cleanupid);
-		ms = (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000;
+		ms = ast_tvdiff(tv, last);
 		if (ms < 100) {
 			/* We just got a message within 100ms, so just schedule an update
 			   in the near future */
Index: res/res_agi.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_agi.c,v
retrieving revision 1.39
diff -u -r1.39 res_agi.c
--- res/res_agi.c	6 Jun 2005 22:12:19 -0000	1.39
+++ res/res_agi.c	10 Jun 2005 08:26:32 -0000
@@ -774,7 +774,7 @@
 {
 	struct ast_filestream *fs;
 	struct ast_frame *f;
-	struct timeval tv, start;
+	struct timeval start;
 	long sample_offset = 0;
 	int res = 0;
 	int ms;
@@ -841,7 +841,9 @@
 
 	if (!res)
 		res = ast_waitstream(chan, argv[4]);
-	if (!res) {
+	if (res) {
+		fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
+	} else {
 		fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, 0644);
 		if (!fs) {
 			res = -1;
@@ -857,9 +859,8 @@
 		ast_seekstream(fs, sample_offset, SEEK_SET);
 		ast_truncstream(fs);
 		
-		gettimeofday(&start, NULL);
-		gettimeofday(&tv, NULL);
-		while ((ms < 0) || (((tv.tv_sec - start.tv_sec) * 1000 + (tv.tv_usec - start.tv_usec)/1000) < ms)) {
+		start = ast_tvnow();
+		while ((ms < 0) || ast_tvdiff(ast_tvnow(), start) < ms) {
 			res = ast_waitfor(chan, -1);
 			if (res < 0) {
 				ast_closestream(fs);
@@ -913,7 +914,6 @@
 				break;
 			}
 			ast_frfree(f);
-		    	gettimeofday(&tv, NULL);
 			if (gotsilence)
 				break;
         	}
@@ -925,8 +925,7 @@
 		}		
 		fdprintf(agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
 		ast_closestream(fs);
-	} else
-		fdprintf(agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
+	}
 
         if (silence > 0) {
                 res = ast_set_read_format(chan, rfmt);
Index: res/res_features.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_features.c,v
retrieving revision 1.57
diff -u -r1.57 res_features.c
--- res/res_features.c	6 Jun 2005 22:12:19 -0000	1.57
+++ res/res_features.c	10 Jun 2005 08:26:33 -0000
@@ -927,7 +927,7 @@
 	int hasfeatures=0;
 	int hadfeatures=0;
 	struct ast_option_header *aoh;
-	struct timeval start, end;
+	struct timeval start;
 	struct ast_bridge_config backup_config;
 	int allowdisconnect_in,allowdisconnect_out,allowredirect_in,allowredirect_out;
 	char *monitor_exec;
@@ -977,13 +977,11 @@
 	}
 	for (;;) {
 		if (config->timelimit)
-			gettimeofday(&start, NULL);
+			start = ast_tvnow();
 		res = ast_channel_bridge(chan,peer,config,&f, &who);
 		if (config->timelimit) {
 			/* Update time limit for next pass */
-			gettimeofday(&end, NULL);
-			diff = (end.tv_sec - start.tv_sec) * 1000;
-			diff += (end.tv_usec - start.tv_usec) / 1000;
+			diff = ast_tvdiff(ast_tvnow(), start);
 			config->timelimit -= diff;
 			if (hasfeatures) {
 				/* Running on backup config, meaning a feature might be being
@@ -1164,8 +1162,7 @@
 				pu = pu->next;
 				continue;
 			}
-			gettimeofday(&tv, NULL);
-			tms = (tv.tv_sec - pu->start.tv_sec) * 1000 + (tv.tv_usec - pu->start.tv_usec) / 1000;
+			tms = ast_tvdiff(ast_tvnow(), pu->start);
 			if (tms > pu->parkingtime) {
 				/* Stop music on hold */
 				ast_moh_stop(pu->chan);
@@ -1306,8 +1303,7 @@
 		ast_mutex_unlock(&parking_lock);
 		rfds = nrfds;
 		efds = nefds;
-		tv.tv_sec = ms / 1000;
-		tv.tv_usec = (ms % 1000) * 1000;
+		tv = ast_samp2tv(ms, 1000);
 		/* Wait for something to happen */
 		ast_select(max + 1, &rfds, NULL, &efds, (ms > -1) ? &tv : NULL);
 		pthread_testcancel();
Index: res/res_musiconhold.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_musiconhold.c,v
retrieving revision 1.61
diff -u -r1.61 res_musiconhold.c
--- res/res_musiconhold.c	6 Jun 2005 22:12:19 -0000	1.61
+++ res/res_musiconhold.c	10 Jun 2005 08:26:34 -0000
@@ -439,17 +439,10 @@
 	char buf[8192];
 	short sbuf[8192];
 	int res, res2;
-	struct timeval tv;
-	struct timeval tv_tmp;
-	long error_sec, error_usec;
-	long delay;
+	struct timeval tv, tv_tmp;
 
-	tv_tmp.tv_sec = 0;
-	tv_tmp.tv_usec = 0;
 	tv.tv_sec = 0;
 	tv.tv_usec = 0;
-	error_sec = 0;
-	error_usec = 0;
 	for(;/* ever */;) {
 		/* Spawn mp3 player if it's not there */
 		if (class->srcfd < 0) {
@@ -463,40 +456,20 @@
 			/* Pause some amount of time */
 			res = read(class->pseudofd, buf, sizeof(buf));
 		} else {
+			long delta;
 			/* Reliable sleep */
-			if (gettimeofday(&tv_tmp, NULL) < 0) {
-				ast_log(LOG_NOTICE, "gettimeofday() failed!\n");
-				return NULL;
-			}
-			if (((unsigned long)(tv.tv_sec) > 0)&&((unsigned long)(tv.tv_usec) > 0)) {
-				if ((unsigned long)(tv_tmp.tv_usec) < (unsigned long)(tv.tv_usec)) {
-					tv_tmp.tv_usec += 1000000;
-					tv_tmp.tv_sec -= 1;
-				}
-				error_sec = (unsigned long)(tv_tmp.tv_sec) - (unsigned long)(tv.tv_sec);
-				error_usec = (unsigned long)(tv_tmp.tv_usec) - (unsigned long)(tv.tv_usec);
-			} else {
-				error_sec = 0;
-				error_usec = 0;
-			}
-			if (error_sec * 1000 + error_usec / 1000 < MOH_MS_INTERVAL) {
-				tv.tv_sec = tv_tmp.tv_sec + (MOH_MS_INTERVAL/1000 - error_sec);
-				tv.tv_usec = tv_tmp.tv_usec + ((MOH_MS_INTERVAL % 1000) * 1000 - error_usec);
-				delay = (MOH_MS_INTERVAL/1000 - error_sec) * 1000 +
-					((MOH_MS_INTERVAL % 1000) * 1000 - error_usec) / 1000;
+			tv_tmp = ast_tvnow();
+			if (ast_tvzero(tv))
+				tv = tv_tmp;
+			delta = ast_tvdiff(tv_tmp, tv);
+			if (delta < MOH_MS_INTERVAL) {	/* too early */
+				tv = ast_tvadd(tv, ast_samp2tv(MOH_MS_INTERVAL, 1000));	/* next deadline */
+				usleep(1000 * (MOH_MS_INTERVAL - delta));
 			} else {
 				ast_log(LOG_NOTICE, "Request to schedule in the past?!?!\n");
-				tv.tv_sec = tv_tmp.tv_sec;
-				tv.tv_usec = tv_tmp.tv_usec;
-				delay = 0;
-			}
-			if (tv.tv_usec > 1000000) {
-				tv.tv_sec++;
-				tv.tv_usec-= 1000000;
+				tv = tv_tmp;
 			}
-			if (delay > 0)
-				usleep(delay * 1000);
-			res = 800;		/* 800 samples */
+			res = 8 * MOH_MS_INTERVAL;	/* 8 samples per millisecond */
 		}
 		if (!class->members)
 			continue;
