tiny patch for sys_time() and sys_stime()
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
kernel/time.c +7 -10
@@ -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 ; }
kernel/time.c +7 -11
@@ -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 ; }
kernel/time.c +4 -10
@@ -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 ; }
kernel/time.c +7 -12
@@ -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 ; }