arm: tegra: register save and restore ops
[linux-3.10.git] / kernel / time.c
index 6a08660..d3617db 100644 (file)
  *     with nanosecond accuracy
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/timex.h>
 #include <linux/capability.h>
-#include <linux/clocksource.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/errno.h>
 #include <linux/syscalls.h>
 #include <linux/security.h>
 #include <linux/fs.h>
-#include <linux/slab.h>
 #include <linux/math64.h>
+#include <linux/ptrace.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -59,14 +59,15 @@ EXPORT_SYMBOL(sys_tz);
  * why not move it into the appropriate arch directory (for those
  * architectures that need it).
  */
-asmlinkage long sys_time(time_t __user * tloc)
+SYSCALL_DEFINE1(time, time_t __user *, tloc)
 {
        time_t i = get_seconds();
 
        if (tloc) {
                if (put_user(i,tloc))
-                       i = -EFAULT;
+                       return -EFAULT;
        }
+       force_successful_syscall_return();
        return i;
 }
 
@@ -77,7 +78,7 @@ asmlinkage long sys_time(time_t __user * tloc)
  * architectures that need it).
  */
 
-asmlinkage long sys_stime(time_t __user *tptr)
+SYSCALL_DEFINE1(stime, time_t __user *, tptr)
 {
        struct timespec tv;
        int err;
@@ -97,8 +98,8 @@ asmlinkage long sys_stime(time_t __user *tptr)
 
 #endif /* __ARCH_WANT_SYS_TIME */
 
-asmlinkage long sys_gettimeofday(struct timeval __user *tv,
-                                struct timezone __user *tz)
+SYSCALL_DEFINE2(gettimeofday, struct timeval __user *, tv,
+               struct timezone __user *, tz)
 {
        if (likely(tv != NULL)) {
                struct timeval ktv;
@@ -114,6 +115,12 @@ asmlinkage long sys_gettimeofday(struct timeval __user *tv,
 }
 
 /*
+ * Indicates if there is an offset between the system clock and the hardware
+ * clock/persistent clock/rtc.
+ */
+int persistent_clock_is_local;
+
+/*
  * Adjust the time obtained from the CMOS to be UTC time instead of
  * local time.
  *
@@ -131,12 +138,14 @@ asmlinkage long sys_gettimeofday(struct timeval __user *tv,
  */
 static inline void warp_clock(void)
 {
-       write_seqlock_irq(&xtime_lock);
-       wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
-       xtime.tv_sec += sys_tz.tz_minuteswest * 60;
-       update_xtime_cache(0);
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
+       if (sys_tz.tz_minuteswest != 0) {
+               struct timespec adjust;
+
+               persistent_clock_is_local = 1;
+               adjust.tv_sec = sys_tz.tz_minuteswest * 60;
+               adjust.tv_nsec = 0;
+               timekeeping_inject_offset(&adjust);
+       }
 }
 
 /*
@@ -150,7 +159,7 @@ static inline void warp_clock(void)
  * various programs will get confused when the clock gets warped.
  */
 
-int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
+int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
 {
        static int firsttime = 1;
        int error = 0;
@@ -163,7 +172,6 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
                return error;
 
        if (tz) {
-               /* SMP safe, global irq locking makes it work. */
                sys_tz = *tz;
                update_vsyscall_tz();
                if (firsttime) {
@@ -173,17 +181,12 @@ int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
                }
        }
        if (tv)
-       {
-               /* SMP safe, again the code in arch/foo/time.c should
-                * globally block out interrupts when it runs.
-                */
                return do_settimeofday(tv);
-       }
        return 0;
 }
 
-asmlinkage long sys_settimeofday(struct timeval __user *tv,
-                               struct timezone __user *tz)
+SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
+               struct timezone __user *, tz)
 {
        struct timeval user_tv;
        struct timespec new_ts;
@@ -203,7 +206,7 @@ asmlinkage long sys_settimeofday(struct timeval __user *tv,
        return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 }
 
-asmlinkage long sys_adjtimex(struct timex __user *txc_p)
+SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
 {
        struct timex txc;               /* Local copy of parameter */
        int ret;
@@ -238,7 +241,7 @@ EXPORT_SYMBOL(current_fs_time);
  * Avoid unnecessary multiplications/divisions in the
  * two most common HZ cases:
  */
-unsigned int inline jiffies_to_msecs(const unsigned long j)
+unsigned int jiffies_to_msecs(const unsigned long j)
 {
 #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ)
        return (MSEC_PER_SEC / HZ) * j;
@@ -254,7 +257,7 @@ unsigned int inline jiffies_to_msecs(const unsigned long j)
 }
 EXPORT_SYMBOL(jiffies_to_msecs);
 
-unsigned int inline jiffies_to_usecs(const unsigned long j)
+unsigned int jiffies_to_usecs(const unsigned long j)
 {
 #if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ)
        return (USEC_PER_SEC / HZ) * j;
@@ -300,22 +303,6 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran)
 }
 EXPORT_SYMBOL(timespec_trunc);
 
-#ifndef CONFIG_GENERIC_TIME
-/*
- * Simulate gettimeofday using do_gettimeofday which only allows a timeval
- * and therefore only yields usec accuracy
- */
-void getnstimeofday(struct timespec *tv)
-{
-       struct timeval x;
-
-       do_gettimeofday(&x);
-       tv->tv_sec = x.tv_sec;
-       tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
-}
-EXPORT_SYMBOL_GPL(getnstimeofday);
-#endif
-
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -368,13 +355,20 @@ EXPORT_SYMBOL(mktime);
  *     0 <= tv_nsec < NSEC_PER_SEC
  * For negative values only the tv_sec field is negative !
  */
-void set_normalized_timespec(struct timespec *ts, time_t sec, long nsec)
+void set_normalized_timespec(struct timespec *ts, time_t sec, s64 nsec)
 {
        while (nsec >= NSEC_PER_SEC) {
+               /*
+                * The following asm() prevents the compiler from
+                * optimising this loop into a modulo operation. See
+                * also __iter_div_u64_rem() in include/linux/time.h
+                */
+               asm("" : "+rm"(nsec));
                nsec -= NSEC_PER_SEC;
                ++sec;
        }
        while (nsec < 0) {
+               asm("" : "+rm"(nsec));
                nsec += NSEC_PER_SEC;
                --sec;
        }
@@ -584,7 +578,7 @@ EXPORT_SYMBOL(jiffies_to_timeval);
 /*
  * Convert jiffies/jiffies_64 to clock_t and back.
  */
-clock_t jiffies_to_clock_t(long x)
+clock_t jiffies_to_clock_t(unsigned long x)
 {
 #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0
 # if HZ < USER_HZ
@@ -653,19 +647,68 @@ u64 nsec_to_clock_t(u64 x)
 #endif
 }
 
-#if (BITS_PER_LONG < 64)
-u64 get_jiffies_64(void)
+/**
+ * nsecs_to_jiffies64 - Convert nsecs in u64 to jiffies64
+ *
+ * @n: nsecs in u64
+ *
+ * Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64.
+ * And this doesn't return MAX_JIFFY_OFFSET since this function is designed
+ * for scheduler, not for use in device drivers to calculate timeout value.
+ *
+ * note:
+ *   NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
+ *   ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
+ */
+u64 nsecs_to_jiffies64(u64 n)
 {
-       unsigned long seq;
-       u64 ret;
-
-       do {
-               seq = read_seqbegin(&xtime_lock);
-               ret = jiffies_64;
-       } while (read_seqretry(&xtime_lock, seq));
-       return ret;
-}
-EXPORT_SYMBOL(get_jiffies_64);
+#if (NSEC_PER_SEC % HZ) == 0
+       /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
+       return div_u64(n, NSEC_PER_SEC / HZ);
+#elif (HZ % 512) == 0
+       /* overflow after 292 years if HZ = 1024 */
+       return div_u64(n * HZ / 512, NSEC_PER_SEC / 512);
+#else
+       /*
+        * Generic case - optimized for cases where HZ is a multiple of 3.
+        * overflow after 64.99 years, exact for HZ = 60, 72, 90, 120 etc.
+        */
+       return div_u64(n * 9, (9ull * NSEC_PER_SEC + HZ / 2) / HZ);
 #endif
+}
+
+/**
+ * nsecs_to_jiffies - Convert nsecs in u64 to jiffies
+ *
+ * @n: nsecs in u64
+ *
+ * Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64.
+ * And this doesn't return MAX_JIFFY_OFFSET since this function is designed
+ * for scheduler, not for use in device drivers to calculate timeout value.
+ *
+ * note:
+ *   NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
+ *   ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
+ */
+unsigned long nsecs_to_jiffies(u64 n)
+{
+       return (unsigned long)nsecs_to_jiffies64(n);
+}
+
+/*
+ * Add two timespec values and do a safety check for overflow.
+ * It's assumed that both values are valid (>= 0)
+ */
+struct timespec timespec_add_safe(const struct timespec lhs,
+                                 const struct timespec rhs)
+{
+       struct timespec res;
+
+       set_normalized_timespec(&res, lhs.tv_sec + rhs.tv_sec,
+                               lhs.tv_nsec + rhs.tv_nsec);
 
-EXPORT_SYMBOL(jiffies);
+       if (res.tv_sec < lhs.tv_sec || res.tv_sec < rhs.tv_sec)
+               res.tv_sec = TIME_T_MAX;
+
+       return res;
+}