]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
um: time-travel: Fix periodic timers
authorJohannes Berg <johannes.berg@intel.com>
Tue, 10 Sep 2019 15:03:52 +0000 (17:03 +0200)
committerRichard Weinberger <richard@nod.at>
Sun, 15 Sep 2019 19:37:13 +0000 (21:37 +0200)
Periodic timers are broken, because the also only fire once.
As it happens, Linux doesn't care because it only sets the
timer to periodic very briefly during boot, and then switches
it only between one-shot and off later.

Nevertheless, fix the logic (we shouldn't even be looking at
time_travel_timer_expiry unless the timer is enabled) and
change the code to fire the timer periodically in periodic
mode, in case it ever gets used in the future.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
arch/um/include/shared/timer-internal.h
arch/um/kernel/process.c
arch/um/kernel/time.c

index 9991ec2371e44e21626df7b587f486c18dc4641d..a4d79389b223351472a5ea1c023f7847edacf4ff 100644 (file)
@@ -43,6 +43,11 @@ static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
        time_travel_timer_expiry = expiry;
 }
+
+static inline void time_travel_set_timer_interval(unsigned long long interval)
+{
+       time_travel_timer_interval = interval;
+}
 #else
 #define time_travel_mode TT_MODE_OFF
 #define time_travel_time 0
@@ -61,6 +66,10 @@ static inline void time_travel_set_timer_expiry(unsigned long long expiry)
 {
 }
 
+static inline void time_travel_set_timer_interval(unsigned long long interval)
+{
+}
+
 #define time_travel_timer_mode TT_TMR_DISABLED
 #endif
 
index 6bede7888fc202f1a268ffcab0f763219a9fba5d..cf242fc5fe9488497f050c5caf1768c137463e8f 100644 (file)
@@ -210,7 +210,12 @@ static void time_travel_sleep(unsigned long long duration)
        if (time_travel_mode != TT_MODE_INFCPU)
                os_timer_disable();
 
-       if (time_travel_timer_mode != TT_TMR_DISABLED ||
+       while (time_travel_timer_mode == TT_TMR_PERIODIC &&
+              time_travel_timer_expiry < time_travel_time)
+               time_travel_set_timer_expiry(time_travel_timer_expiry +
+                                            time_travel_timer_interval);
+
+       if (time_travel_timer_mode != TT_TMR_DISABLED &&
            time_travel_timer_expiry < next) {
                if (time_travel_timer_mode == TT_TMR_ONESHOT)
                        time_travel_set_timer_mode(TT_TMR_DISABLED);
index 234757233355fb1278bac9f98dca9c0bc637ea46..4ecabf7e54c9fbf98127a033cc8b2cb286610f68 100644 (file)
@@ -65,6 +65,7 @@ static int itimer_set_periodic(struct clock_event_device *evt)
        if (time_travel_mode != TT_MODE_OFF) {
                time_travel_set_timer_mode(TT_TMR_PERIODIC);
                time_travel_set_timer_expiry(time_travel_time + interval);
+               time_travel_set_timer_interval(interval);
        }
 
        if (time_travel_mode != TT_MODE_INFCPU)