[PATCH] uml: avoid already done dirtying
[pandora-kernel.git] / kernel / timer.c
index 5377f40..f4152fc 100644 (file)
@@ -950,6 +950,7 @@ void do_timer(struct pt_regs *regs)
 {
        jiffies_64++;
        update_times();
+       softlockup_tick(regs);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
@@ -1153,6 +1154,20 @@ fastcall signed long __sched schedule_timeout(signed long timeout)
 
 EXPORT_SYMBOL(schedule_timeout);
 
+signed long __sched schedule_timeout_interruptible(signed long timeout)
+{
+       set_current_state(TASK_INTERRUPTIBLE);
+       return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_interruptible);
+
+signed long __sched schedule_timeout_uninterruptible(signed long timeout)
+{
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       return schedule_timeout(timeout);
+}
+EXPORT_SYMBOL(schedule_timeout_uninterruptible);
+
 /* Thread ID - the internal kernel "pid" */
 asmlinkage long sys_gettid(void)
 {
@@ -1169,8 +1184,7 @@ static long __sched nanosleep_restart(struct restart_block *restart)
        if (!time_after(expire, now))
                return 0;
 
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire - now);
+       expire = schedule_timeout_interruptible(expire - now);
 
        ret = 0;
        if (expire) {
@@ -1198,8 +1212,7 @@ asmlinkage long sys_nanosleep(struct timespec __user *rqtp, struct timespec __us
                return -EINVAL;
 
        expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
-       current->state = TASK_INTERRUPTIBLE;
-       expire = schedule_timeout(expire);
+       expire = schedule_timeout_interruptible(expire);
 
        ret = 0;
        if (expire) {
@@ -1428,7 +1441,7 @@ static inline u64 time_interpolator_get_cycles(unsigned int src)
        }
 }
 
-static inline u64 time_interpolator_get_counter(void)
+static inline u64 time_interpolator_get_counter(int writelock)
 {
        unsigned int src = time_interpolator->source;
 
@@ -1442,6 +1455,15 @@ static inline u64 time_interpolator_get_counter(void)
                        now = time_interpolator_get_cycles(src);
                        if (lcycle && time_after(lcycle, now))
                                return lcycle;
+
+                       /* When holding the xtime write lock, there's no need
+                        * to add the overhead of the cmpxchg.  Readers are
+                        * force to retry until the write lock is released.
+                        */
+                       if (writelock) {
+                               time_interpolator->last_cycle = now;
+                               return now;
+                       }
                        /* Keep track of the last timer value returned. The use of cmpxchg here
                         * will cause contention in an SMP environment.
                         */
@@ -1455,7 +1477,7 @@ static inline u64 time_interpolator_get_counter(void)
 void time_interpolator_reset(void)
 {
        time_interpolator->offset = 0;
-       time_interpolator->last_counter = time_interpolator_get_counter();
+       time_interpolator->last_counter = time_interpolator_get_counter(1);
 }
 
 #define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
@@ -1467,7 +1489,7 @@ unsigned long time_interpolator_get_offset(void)
                return 0;
 
        return time_interpolator->offset +
-               GET_TI_NSECS(time_interpolator_get_counter(), time_interpolator);
+               GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
 }
 
 #define INTERPOLATOR_ADJUST 65536
@@ -1490,7 +1512,7 @@ static void time_interpolator_update(long delta_nsec)
         * and the tuning logic insures that.
          */
 
-       counter = time_interpolator_get_counter();
+       counter = time_interpolator_get_counter(1);
        offset = time_interpolator->offset + GET_TI_NSECS(counter, time_interpolator);
 
        if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
@@ -1588,10 +1610,8 @@ void msleep(unsigned int msecs)
 {
        unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
-       while (timeout) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-       }
+       while (timeout)
+               timeout = schedule_timeout_uninterruptible(timeout);
 }
 
 EXPORT_SYMBOL(msleep);
@@ -1604,10 +1624,8 @@ unsigned long msleep_interruptible(unsigned int msecs)
 {
        unsigned long timeout = msecs_to_jiffies(msecs) + 1;
 
-       while (timeout && !signal_pending(current)) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               timeout = schedule_timeout(timeout);
-       }
+       while (timeout && !signal_pending(current))
+               timeout = schedule_timeout_interruptible(timeout);
        return jiffies_to_msecs(timeout);
 }