aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-10-16 04:27:25 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:43:08 -0400
commitd2753a6d199791a6abc75d9f657e3457fe61705f (patch)
treec4cda30f216d6c045ca2b83bee1fa6bc4dfc3de3 /arch/um/kernel
parent791a644a8d73a9b95515f074afbb3caa0a9964fa (diff)
uml: tickless support
Enable tickless support. CONFIG_TICK_ONESHOT and CONFIG_NO_HZ are enabled. itimer_clockevent gets CLOCK_EVT_FEAT_ONESHOT and an implementation of .set_next_event. CONFIG_UML_REAL_TIME_CLOCK goes away because it only makes sense when there is a clock ticking away all the time. timer_handler now just calls do_IRQ once without trying to figure out how many ticks to emulate. The idle loop now needs to turn ticking on and off. Userspace ticks keep happening as usual. However, the userspace loop keep track of when the next wakeup should happen and suppresses process ticks until that happens. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/process.c3
-rw-r--r--arch/um/kernel/time.c45
2 files changed, 13 insertions, 35 deletions
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 56d75afedbf7..aef494b6b81a 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -13,6 +13,7 @@
13#include "linux/ptrace.h" 13#include "linux/ptrace.h"
14#include "linux/random.h" 14#include "linux/random.h"
15#include "linux/sched.h" 15#include "linux/sched.h"
16#include "linux/tick.h"
16#include "linux/threads.h" 17#include "linux/threads.h"
17#include "asm/pgtable.h" 18#include "asm/pgtable.h"
18#include "asm/uaccess.h" 19#include "asm/uaccess.h"
@@ -244,9 +245,11 @@ void default_idle(void)
244 if (need_resched()) 245 if (need_resched())
245 schedule(); 246 schedule();
246 247
248 tick_nohz_stop_sched_tick();
247 switch_timers(1); 249 switch_timers(1);
248 idle_sleep(10); 250 idle_sleep(10);
249 switch_timers(0); 251 switch_timers(0);
252 tick_nohz_restart_sched_tick();
250 } 253 }
251} 254}
252 255
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 3cb7135e5c47..2acdc7efb2ac 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -20,41 +20,12 @@ unsigned long long sched_clock(void)
20 return (unsigned long long)jiffies_64 * (1000000000 / HZ); 20 return (unsigned long long)jiffies_64 * (1000000000 / HZ);
21} 21}
22 22
23#ifdef CONFIG_UML_REAL_TIME_CLOCK
24static unsigned long long prev_nsecs[NR_CPUS];
25static long long delta[NR_CPUS]; /* Deviation per interval */
26#endif
27
28void timer_handler(int sig, struct uml_pt_regs *regs) 23void timer_handler(int sig, struct uml_pt_regs *regs)
29{ 24{
30 unsigned long long ticks = 0;
31 unsigned long flags; 25 unsigned long flags;
32#ifdef CONFIG_UML_REAL_TIME_CLOCK
33 int c = cpu();
34 if (prev_nsecs[c]) {
35 /* We've had 1 tick */
36 unsigned long long nsecs = os_nsecs();
37
38 delta[c] += nsecs - prev_nsecs[c];
39 prev_nsecs[c] = nsecs;
40
41 /* Protect against the host clock being set backwards */
42 if (delta[c] < 0)
43 delta[c] = 0;
44
45 ticks += (delta[c] * HZ) / BILLION;
46 delta[c] -= (ticks * BILLION) / HZ;
47 }
48 else prev_nsecs[c] = os_nsecs();
49#else
50 ticks = 1;
51#endif
52 26
53 local_irq_save(flags); 27 local_irq_save(flags);
54 while (ticks > 0) { 28 do_IRQ(TIMER_IRQ, regs);
55 do_IRQ(TIMER_IRQ, regs);
56 ticks--;
57 }
58 local_irq_restore(flags); 29 local_irq_restore(flags);
59} 30}
60 31
@@ -68,10 +39,8 @@ static void itimer_set_mode(enum clock_event_mode mode,
68 39
69 case CLOCK_EVT_MODE_SHUTDOWN: 40 case CLOCK_EVT_MODE_SHUTDOWN:
70 case CLOCK_EVT_MODE_UNUSED: 41 case CLOCK_EVT_MODE_UNUSED:
71 disable_timer();
72 break;
73 case CLOCK_EVT_MODE_ONESHOT: 42 case CLOCK_EVT_MODE_ONESHOT:
74 BUG(); 43 disable_timer();
75 break; 44 break;
76 45
77 case CLOCK_EVT_MODE_RESUME: 46 case CLOCK_EVT_MODE_RESUME:
@@ -79,13 +48,19 @@ static void itimer_set_mode(enum clock_event_mode mode,
79 } 48 }
80} 49}
81 50
51static int itimer_next_event(unsigned long delta,
52 struct clock_event_device *evt)
53{
54 return timer_one_shot(delta + 1);
55}
56
82static struct clock_event_device itimer_clockevent = { 57static struct clock_event_device itimer_clockevent = {
83 .name = "itimer", 58 .name = "itimer",
84 .rating = 250, 59 .rating = 250,
85 .cpumask = CPU_MASK_ALL, 60 .cpumask = CPU_MASK_ALL,
86 .features = CLOCK_EVT_FEAT_PERIODIC, 61 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
87 .set_mode = itimer_set_mode, 62 .set_mode = itimer_set_mode,
88 .set_next_event = NULL, 63 .set_next_event = itimer_next_event,
89 .shift = 32, 64 .shift = 32,
90 .irq = 0, 65 .irq = 0,
91}; 66};