: This patch fixes the broken adjtime() emulation of PPSkit with nanokernel.
Index: kernel/time.c
===================================================================
RCS file: /root/LinuxCVS/Kernel/kernel/time.c,v
retrieving revision 1.1.1.5.2.3
diff -u -r1.1.1.5.2.3 time.c
--- kernel/time.c	8 Mar 2003 15:52:45 -0000	1.1.1.5.2.3
+++ kernel/time.c	21 Mar 2003 21:09:05 -0000
@@ -155,6 +155,11 @@
  * 2003-02-04	Ulrich Windl
  *	Added missing permission check for ``sys_clock_settime()''.  Added
  *	strategy routine to implement proper permission checks for sysctl.
+ * 2003-03-21	Ulrich Windl
+ *	Fixed bug: adjtimex() was accepting microseconds as nanoseconds,
+ *	returning nanoseconds as microseconds.  Indicate broken adjtime()
+ *	implementation with limited range.  Changed ``tickadj'' back to
+ *	microseconds (which is the granularity of adjtime() anyway).
  */
 
 #include <linux/config.h>
@@ -201,7 +206,8 @@
 static long time_adjust = 0;	/* remaining adjustment for adjtime() */
 
 long time_tick;			/* nanoseconds per tick (ns) */
-static	long tickadj;		/* number of nanoseconds to adjust time_tick */
+static	long tickadj;	/* number of microseconds to adjust time_tick */
+
 /* [extension by UW]: If ``rtc_update'' is positive then update the RTC as
  * before, but using the value as interval between updates.
  * ``rtc_update_slave'' will contain the value of ``rtc_update'' if the RTC
@@ -371,7 +377,7 @@
 static /* const */ int	sysctl_no_max	= 1 << 30;
 static /* const */ int	sysctl_tick_min	= 9 * (NANOSECOND/10/hz);
 static /* const */ int	sysctl_tick_max	= 11 * (NANOSECOND/10/hz);
-static /* const */ int	sysctl_tickadj_max = (NANOSECOND/hz) / 4;
+static /* const */ int	sysctl_tickadj_max = (NANOSECOND/1000/hz) / 4;
 static /* const */ int	sysctl_hz = HZ;
 
 /* strategy routine for sysctl() */
@@ -624,6 +630,7 @@
 	     
 		/* Update remaining adjustment */
 		time_adjust -= time_update;
+		time_update *= 1000;	/* convert to nanoseconds */
 	}
 #ifdef CONFIG_NTP
 	/*
@@ -1501,9 +1508,6 @@
 	result = 0;
 #endif
 
-	/* Save for later - semantics of adjtime is to return old value */
-	save_adjust = time_adjust;
-
 #if defined(CONFIG_NTP) && 0	/* STA_CLOCKERR is never set yet */
 	time_status &= ~STA_CLOCKERR;		/* reset STA_CLOCKERR */
 #endif
@@ -1627,8 +1631,17 @@
 		}
 #endif /* CONFIG_NTP */
 		if (txc->modes == ADJ_ADJTIME) {
-			/* adjtime() is independent from ntp_adjtime() */
+			/*
+			 * The emulation of adjtime() is actually broken,
+			 * because only one ``long'' is available to represent
+			 * a ``struct timeval''.
+			 */
+			/* Save current adjustment to be retuned */
+			save_adjust = time_adjust;
 			time_adjust = txc->offset;
+			if (txc->offset < -30000000 || txc->offset > 30000000)
+				printk(KERN_WARNING
+				       "adjtime() fails with large offsets\n");
 		}
 		if (txc->modes & ADJ_TIMETICK) {
 #ifdef CONFIG_NTP
@@ -1654,11 +1667,11 @@
 			   Larger values might cause trouble!
 			*/
 			if (txc->tickadj <= 0 ||
-			    txc->tickadj > time_tick/4000) {
+			    txc->tickadj > time_tick / 4) {
 				result = -EINVAL;
 				goto leave;
 			}
-			tickadj = txc->tickadj * 1000;
+			tickadj = txc->tickadj;
 		}
 	} /* txc->modes */
 leave:
@@ -1703,7 +1716,7 @@
 	txc->errcnt	   = pps.errcnt;
 	txc->stbcnt	   = pps.stbcnt;
 #endif
-	txc->tickadj	   = tickadj / 1000;	/* extension by UW */
+	txc->tickadj	   = tickadj;	/* extension by UW */
 
 #ifdef CONFIG_NTP
 	if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
@@ -1772,7 +1785,7 @@
 	 */
 	time_tick = (NANOSECOND + hz/2) / hz;
 	/* Speed of adjtime() is 50ms/s; may not be <= 0 */
-	tickadj = 50000000/hz ? : 1;
+	tickadj = 50000/hz ? : 1;
 	time_adjust = 0;
 	rtc_update = 660;			/* update every 11 minutes */
 
