Messages in this thread Patches in this message | | | Subject | tiny patch for sys_time() and sys_stime() | From | Urs Thuermann <> | Date | 01 May 2003 14:09:36 +0200 |
| |
A couple of years ago, when some 2.0.x kernel was current, I did a patch for the time() and stime() system call, which I also sent for inclusion, AFAIR to LKML. However I didn't get any response to it.
Now I see that the patch went partially in, i.e. for the sys_time() syscall but not sys_stime().
These syscalls were implemented as they are still in 2.0.40-rc6 and 2.2.25 like this
asmlinkage int sys_time(int * tloc) { int i; /* SMP: This is fairly trivial. We grab CURRENT_TIME and stuff it to user space. No side effects */ i = CURRENT_TIME; if (tloc) { if (put_user(i,tloc)) i = -EFAULT; } return i; }
where CURRENT_TIME is defined as xtime.tv_sec and asmlinkage int sys_stime(int * tptr) { int value; if (!capable(CAP_SYS_TIME)) return -EPERM; if (get_user(value, tptr)) return -EFAULT; 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; write_unlock_irq(&xtime_lock); return 0; }
Both calls do not take into account the hardware timer, which may cause the time read or set to be offset by almost one tick. sys_settimeofday() and sys_gettimeofday() do take into account the value of the hardware timer (i8254 or tsc on x86).
My patch was to make sys_time() and sys_stime() to be just wrappers to do_gettimeofday() and do_settimeofday(). In 2.4.17 this was done for sys_time() but not sys_stime(). In 2.5.x the macro CURRENT_TIME was replaced by an inline function get_seconds() which also only does return the value of xtime.tv_sec.
I append patches for 2.0.40-rc6, 2.2.25, 2.4.20-rc1 and 2.5.68 which make both, sys_time() and sys_stime() just wrappers for the do_{get,set}timeofday() calls. This looks cleaner, eliminates a small amount of code duplication of code already present in do_{get,set}timeofday, and it reduces the possibility of overseeing necessary changes, like the call to clock_was_set() in the 2.5.x version of do_settimeofday() for some architectures.
For 2.5.x and 2.6 kernels I'd actually like too see these calls eliminated completely, as is the case for alpha and ia64 already.
urs
diff -ru linux-2.0.40-rc6/kernel/time.c linux-2.0.40-rc6-ut/kernel/time.c --- linux-2.0.40-rc6/kernel/time.c 1998-06-04 00:17:50.000000000 +0200 +++ linux-2.0.40-rc6-ut/kernel/time.c 2003-04-04 20:14:48.000000000 +0200 @@ -52,9 +52,11 @@ */ asmlinkage int sys_time(int * tloc) { + struct timeval now; int i; - i = CURRENT_TIME; + do_gettimeofday(&now); + i = now.tv_sec; if (tloc) { int error = verify_area(VERIFY_WRITE, tloc, sizeof(*tloc)); if (error) @@ -73,6 +75,7 @@ asmlinkage int sys_stime(int * tptr) { int error, value; + struct timeval new_tv; if (!suser()) return -EPERM; @@ -80,15 +83,9 @@ if (error) return error; value = get_user(tptr); - cli(); - xtime.tv_sec = value; - xtime.tv_usec = 0; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_state = TIME_ERROR; /* p. 24, (a) */ - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - sti(); + new_tv.tv_sec = value; + new_tv.tv_usec = 0; + do_settimeofday(&new_tv); return 0; }
diff -ru linux-2.2.25/kernel/time.c linux-2.2.25-ut/kernel/time.c --- linux-2.2.25/kernel/time.c 2001-03-25 18:31:02.000000000 +0200 +++ linux-2.2.25-ut/kernel/time.c 2003-04-04 18:18:17.000000000 +0200 @@ -73,11 +73,11 @@ */ asmlinkage int sys_time(int * tloc) { + struct timeval now; int i; - /* SMP: This is fairly trivial. We grab CURRENT_TIME and - stuff it to user space. No side effects */ - i = CURRENT_TIME; + do_gettimeofday(&now); + i = now.tv_sec; if (tloc) { if (put_user(i,tloc)) i = -EFAULT; @@ -95,19 +95,15 @@ asmlinkage int sys_stime(int * tptr) { int value; + struct timeval new_tv; if (!capable(CAP_SYS_TIME)) return -EPERM; if (get_user(value, tptr)) return -EFAULT; - 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; - write_unlock_irq(&xtime_lock); + new_tv.tv_sec = value; + new_tv.tv_usec = 0; + do_settimeofday(&new_tv); return 0; }
diff -ru linux-2.4.20-rc1/kernel/time.c linux-2.4.20-rc1-ut/kernel/time.c --- linux-2.4.20-rc1/kernel/time.c 2003-04-04 17:41:41.000000000 +0200 +++ linux-2.4.20-rc1-ut/kernel/time.c 2003-04-04 20:39:14.000000000 +0200 @@ -74,21 +74,15 @@ asmlinkage long sys_stime(int * tptr) { int value; + struct timeval new_tv; if (!capable(CAP_SYS_TIME)) return -EPERM; if (get_user(value, tptr)) return -EFAULT; - write_lock_irq(&xtime_lock); - vxtime_lock(); - xtime.tv_sec = value; - xtime.tv_usec = 0; - vxtime_unlock(); - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_unlock_irq(&xtime_lock); + new_tv.tv_sec = value; + new_tv.tv_usec = 0; + do_settimeofday(&new_tv); return 0; }
diff -ru linux-2.5.68/kernel/time.c linux-2.5.68-ut/kernel/time.c --- linux-2.5.68/kernel/time.c 2003-05-01 12:26:40.000000000 +0200 +++ linux-2.5.68-ut/kernel/time.c 2003-05-01 12:29:10.000000000 +0200 @@ -49,11 +49,11 @@ */ asmlinkage long sys_time(int * tloc) { + struct timeval now; int i; - /* SMP: This is fairly trivial. We grab CURRENT_TIME and - stuff it to user space. No side effects */ - i = get_seconds(); + do_gettimeofday(&now); + i = now.tv_sec; if (tloc) { if (put_user(i,tloc)) i = -EFAULT; @@ -71,20 +71,15 @@ asmlinkage long sys_stime(int * tptr) { int value; + struct timeval new_tv; if (!capable(CAP_SYS_TIME)) return -EPERM; if (get_user(value, tptr)) return -EFAULT; - write_seqlock_irq(&xtime_lock); - xtime.tv_sec = value; - xtime.tv_nsec = 0; - last_time_offset = 0; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); + new_tv.tv_sec = value; + new_tv.tv_usec = 0; + do_settimeofday(&new_tv); return 0; } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |