patch-2.2.13 linux/kernel/time.c

Next file: linux/mm/filemap.c
Previous file: linux/kernel/sysctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.12/linux/kernel/time.c linux/kernel/time.c
@@ -22,6 +22,8 @@
  *	"A Kernel Model for Precision Timekeeping" by Dave Mills
  *	Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
  *	(Even though the technical memorandum forbids it)
+ * 1999-09-17    Andrea Arcangeli <andrea@suse.de>
+ *	Fixed adjtimex/settimeofday/stime SMP races.
  */
 
 #include <linux/mm.h>
@@ -54,6 +56,13 @@
 	do_get_fast_time(t);
 }
 
+/* The xtime_lock is not only serializing the xtime read/writes but it's also
+   serializing all accesses to the global NTP variables.
+   NOTE NOTE: We really need a spinlock here as the global irq locking
+   only protect us against the timer irq and not against other time-related
+   syscall running under us. */
+extern rwlock_t xtime_lock;
+
 #ifndef __alpha__
 
 /*
@@ -91,14 +100,14 @@
 		return -EPERM;
 	if (get_user(value, tptr))
 		return -EFAULT;
-	cli();
+	write_lock_irq(&xtime_lock);
 	xtime.tv_sec = value;
 	xtime.tv_usec = 0;
 	time_adjust = 0;	/* stop active adjtime() */
 	time_status |= STA_UNSYNC;
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
-	sti();
+	write_unlock_irq(&xtime_lock);
 	return 0;
 }
 
@@ -137,9 +146,9 @@
  */
 inline static void warp_clock(void)
 {
-	cli();
+	write_lock_irq(&xtime_lock);
 	xtime.tv_sec += sys_tz.tz_minuteswest * 60;
-	sti();
+	write_unlock_irq(&xtime_lock);
 }
 
 /*
@@ -220,7 +229,7 @@
 int do_adjtimex(struct timex *txc)
 {
         long ltemp, mtemp, save_adjust;
-	int result = time_state;	/* mostly `TIME_OK' */
+	int result;
 
 	/* In order to modify anything, you gotta be super-user! */
 	if (txc->modes && !capable(CAP_SYS_TIME))
@@ -238,7 +247,8 @@
 		if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ)
 			return -EINVAL;
 
-	cli(); /* SMP: global cli() is enough protection. */
+	write_lock_irq(&xtime_lock);
+	result = time_state;	/* mostly `TIME_OK' */
 
 	/* Save for later - semantics of adjtime is to return old value */
 	save_adjust = time_adjust;
@@ -383,7 +393,6 @@
 	txc->constant	   = time_constant;
 	txc->precision	   = time_precision;
 	txc->tolerance	   = time_tolerance;
-	do_gettimeofday(&txc->time);
 	txc->tick	   = tick;
 	txc->ppsfreq	   = pps_freq;
 	txc->jitter	   = pps_jitter >> PPS_AVG;
@@ -393,8 +402,8 @@
 	txc->calcnt	   = pps_calcnt;
 	txc->errcnt	   = pps_errcnt;
 	txc->stbcnt	   = pps_stbcnt;
-
-	sti();
+	write_unlock_irq(&xtime_lock);
+	do_gettimeofday(&txc->time);
 	return(result);
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)