diff options
author | Jeff Dike <jdike@addtoit.com> | 2007-10-16 04:27:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-16 12:43:08 -0400 |
commit | d2753a6d199791a6abc75d9f657e3457fe61705f (patch) | |
tree | c4cda30f216d6c045ca2b83bee1fa6bc4dfc3de3 /arch/um/os-Linux/skas/process.c | |
parent | 791a644a8d73a9b95515f074afbb3caa0a9964fa (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/os-Linux/skas/process.c')
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 0036164bb0fb..3e64814e888e 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -287,10 +287,18 @@ int start_userspace(unsigned long stub_stack) | |||
287 | 287 | ||
288 | void userspace(struct uml_pt_regs *regs) | 288 | void userspace(struct uml_pt_regs *regs) |
289 | { | 289 | { |
290 | struct itimerval timer; | ||
291 | unsigned long long nsecs, now; | ||
290 | int err, status, op, pid = userspace_pid[0]; | 292 | int err, status, op, pid = userspace_pid[0]; |
291 | /* To prevent races if using_sysemu changes under us.*/ | 293 | /* To prevent races if using_sysemu changes under us.*/ |
292 | int local_using_sysemu; | 294 | int local_using_sysemu; |
293 | 295 | ||
296 | if (getitimer(ITIMER_VIRTUAL, &timer)) | ||
297 | printk("Failed to get itimer, errno = %d\n", errno); | ||
298 | nsecs = timer.it_value.tv_sec * BILLION + | ||
299 | timer.it_value.tv_usec * 1000; | ||
300 | nsecs += os_nsecs(); | ||
301 | |||
294 | while (1) { | 302 | while (1) { |
295 | restore_registers(pid, regs); | 303 | restore_registers(pid, regs); |
296 | 304 | ||
@@ -333,8 +341,18 @@ void userspace(struct uml_pt_regs *regs) | |||
333 | case SIGTRAP: | 341 | case SIGTRAP: |
334 | relay_signal(SIGTRAP, regs); | 342 | relay_signal(SIGTRAP, regs); |
335 | break; | 343 | break; |
336 | case SIGIO: | ||
337 | case SIGVTALRM: | 344 | case SIGVTALRM: |
345 | now = os_nsecs(); | ||
346 | if(now < nsecs) | ||
347 | break; | ||
348 | block_signals(); | ||
349 | (*sig_info[sig])(sig, regs); | ||
350 | unblock_signals(); | ||
351 | nsecs = timer.it_value.tv_sec * BILLION + | ||
352 | timer.it_value.tv_usec * 1000; | ||
353 | nsecs += os_nsecs(); | ||
354 | break; | ||
355 | case SIGIO: | ||
338 | case SIGILL: | 356 | case SIGILL: |
339 | case SIGBUS: | 357 | case SIGBUS: |
340 | case SIGFPE: | 358 | case SIGFPE: |
@@ -378,6 +396,7 @@ __initcall(init_thread_regs); | |||
378 | 396 | ||
379 | int copy_context_skas0(unsigned long new_stack, int pid) | 397 | int copy_context_skas0(unsigned long new_stack, int pid) |
380 | { | 398 | { |
399 | struct timeval tv = { .tv_sec = 0, .tv_usec = 1000000 / UM_HZ }; | ||
381 | int err; | 400 | int err; |
382 | unsigned long current_stack = current_stub_stack(); | 401 | unsigned long current_stack = current_stub_stack(); |
383 | struct stub_data *data = (struct stub_data *) current_stack; | 402 | struct stub_data *data = (struct stub_data *) current_stack; |
@@ -392,9 +411,9 @@ int copy_context_skas0(unsigned long new_stack, int pid) | |||
392 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), | 411 | *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), |
393 | .fd = new_fd, | 412 | .fd = new_fd, |
394 | .timer = ((struct itimerval) | 413 | .timer = ((struct itimerval) |
395 | { { 0, 1000000 / UM_HZ }, | 414 | { .it_value = tv, |
396 | { 0, 1000000 / UM_HZ }}) | 415 | .it_interval = tv }) }); |
397 | }); | 416 | |
398 | err = ptrace_setregs(pid, thread_regs); | 417 | err = ptrace_setregs(pid, thread_regs); |
399 | if (err < 0) | 418 | if (err < 0) |
400 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " | 419 | panic("copy_context_skas0 : PTRACE_SETREGS failed, " |