diff -Nru linux-old/include/linux/time.h linux-new/include/linux/time.h
--- linux-old/include/linux/time.h	2002-10-23 20:54:40.000000000 -0400
+++ linux-new/include/linux/time.h	2002-10-23 21:58:33.000000000 -0400
@@ -48,6 +48,27 @@
 	value->tv_sec = jiffies / HZ;
 }
 
+static __inline__ int
+timespec_before(struct timespec a, struct timespec b)
+{
+	if (a.tv_sec == b.tv_sec)
+		return a.tv_nsec < b.tv_nsec;
+	return a.tv_sec < b.tv_sec;
+}
+
+/* computes `a - b'  and write the result in `result', assumes `a >= b' */
+static inline void
+timespec_less(struct timespec a, struct timespec b, struct timespec * result)
+{
+	if (a.tv_nsec < b.tv_nsec)
+	{
+		a.tv_sec--;
+		a.tv_nsec += 1000000000;
+	}
+
+	result->tv_sec = a.tv_sec - b.tv_sec;
+	result->tv_nsec = a.tv_nsec - b.tv_nsec;
+}
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
@@ -90,6 +111,27 @@
 	suseconds_t	tv_usec;	/* microseconds */
 };
 
+/* computes `a - b'  and write the result in `result', assumes `a >= b' */
+static inline void
+timeval_less(struct timeval a, struct timeval b, struct timeval * result)
+{
+	if (a.tv_usec < b.tv_usec)
+	{
+		a.tv_sec--;
+		a.tv_usec += 1000000;
+	}
+
+	result->tv_sec = a.tv_sec - b.tv_sec;
+	result->tv_usec = a.tv_usec - b.tv_usec;
+}
+
+static __inline__ void
+timeval_to_timespec(struct timeval tv, struct timespec * ts)
+{
+	ts->tv_sec = tv.tv_sec;
+	ts->tv_nsec = (long) tv.tv_usec * 1000;
+}
+
 struct timezone {
 	int	tz_minuteswest;	/* minutes west of Greenwich */
 	int	tz_dsttime;	/* type of dst correction */
diff -Nru linux-old/kernel/timer.c linux-new/kernel/timer.c
--- linux-old/kernel/timer.c	2002-10-23 21:49:29.000000000 -0400
+++ linux-new/kernel/timer.c	2002-10-23 21:58:33.000000000 -0400
@@ -960,6 +960,7 @@
 {
 	struct timespec t;
 	unsigned long expire;
+	struct timeval before, after;
 
 	if(copy_from_user(&t, rqtp, sizeof(struct timespec)))
 		return -EFAULT;
@@ -984,11 +985,20 @@
 	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
 
 	current->state = TASK_INTERRUPTIBLE;
+	do_gettimeofday(&before);
 	expire = schedule_timeout(expire);
+	do_gettimeofday(&after);
 
 	if (expire) {
 		if (rmtp) {
-			jiffies_to_timespec(expire, &t);
+			struct timespec elapsed;
+
+			timeval_less(after, before, &after);
+			timeval_to_timespec(after, &elapsed);
+			if (timespec_before(elapsed, t))
+				timespec_less(t, elapsed, &t);
+			else
+				t.tv_nsec = t.tv_sec = 0;
 			if (copy_to_user(rmtp, &t, sizeof(struct timespec)))
 				return -EFAULT;
 		}
