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
- Lines: 90
- Date:
Tue Oct 19 17:14:02 1999
- Orig file:
v2.2.12/linux/kernel/time.c
- Orig date:
Thu Mar 11 23:26:03 1999
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)