diff options
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/drivers/ethertap_user.c | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/helper.c | 4 | ||||
-rw-r--r-- | arch/um/os-Linux/main.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/sigio.c | 39 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 1 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 81 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 5 | ||||
-rw-r--r-- | arch/um/os-Linux/time.c | 54 |
9 files changed, 124 insertions, 68 deletions
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 6fb0b174f538..cc72cb2c1af6 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c | |||
@@ -52,7 +52,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, | |||
52 | return; | 52 | return; |
53 | } | 53 | } |
54 | 54 | ||
55 | output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); | 55 | output = uml_kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); |
56 | if (output == NULL) | 56 | if (output == NULL) |
57 | printk(UM_KERN_ERR "etap_change : Failed to allocate output " | 57 | printk(UM_KERN_ERR "etap_change : Failed to allocate output " |
58 | "buffer\n"); | 58 | "buffer\n"); |
@@ -165,7 +165,7 @@ static int etap_open(void *data) | |||
165 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], | 165 | err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], |
166 | control_fds[1], data_fds[0], data_fds[1]); | 166 | control_fds[1], data_fds[0], data_fds[1]); |
167 | output_len = UM_KERN_PAGE_SIZE; | 167 | output_len = UM_KERN_PAGE_SIZE; |
168 | output = kmalloc(output_len, UM_GFP_KERNEL); | 168 | output = uml_kmalloc(output_len, UM_GFP_KERNEL); |
169 | read_output(control_fds[0], output, output_len); | 169 | read_output(control_fds[0], output, output_len); |
170 | 170 | ||
171 | if (output == NULL) | 171 | if (output == NULL) |
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index f25c29a12d00..74ca7aabf4e1 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c | |||
@@ -71,8 +71,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) | |||
71 | data.pre_data = pre_data; | 71 | data.pre_data = pre_data; |
72 | data.argv = argv; | 72 | data.argv = argv; |
73 | data.fd = fds[1]; | 73 | data.fd = fds[1]; |
74 | data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) : | 74 | data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) : |
75 | kmalloc(PATH_MAX, UM_GFP_KERNEL); | 75 | uml_kmalloc(PATH_MAX, UM_GFP_KERNEL); |
76 | pid = clone(helper_child, (void *) sp, CLONE_VM, &data); | 76 | pid = clone(helper_child, (void *) sp, CLONE_VM, &data); |
77 | if (pid < 0) { | 77 | if (pid < 0) { |
78 | ret = -errno; | 78 | ret = -errno; |
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index abb9b0ffd960..eee69b9f52c9 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c | |||
@@ -199,7 +199,7 @@ void *__wrap_malloc(int size) | |||
199 | return __real_malloc(size); | 199 | return __real_malloc(size); |
200 | else if (size <= UM_KERN_PAGE_SIZE) | 200 | else if (size <= UM_KERN_PAGE_SIZE) |
201 | /* finding contiguous pages can be hard*/ | 201 | /* finding contiguous pages can be hard*/ |
202 | ret = kmalloc(size, UM_GFP_KERNEL); | 202 | ret = uml_kmalloc(size, UM_GFP_KERNEL); |
203 | else ret = vmalloc(size); | 203 | else ret = vmalloc(size); |
204 | 204 | ||
205 | /* | 205 | /* |
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index abf47a7c4abd..eb8f2e4be192 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) | 2 | * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -15,6 +15,7 @@ | |||
15 | #include "kern_util.h" | 15 | #include "kern_util.h" |
16 | #include "init.h" | 16 | #include "init.h" |
17 | #include "os.h" | 17 | #include "os.h" |
18 | #include "process.h" | ||
18 | #include "sigio.h" | 19 | #include "sigio.h" |
19 | #include "um_malloc.h" | 20 | #include "um_malloc.h" |
20 | #include "user.h" | 21 | #include "user.h" |
@@ -109,7 +110,7 @@ static int need_poll(struct pollfds *polls, int n) | |||
109 | if (n <= polls->size) | 110 | if (n <= polls->size) |
110 | return 0; | 111 | return 0; |
111 | 112 | ||
112 | new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); | 113 | new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); |
113 | if (new == NULL) { | 114 | if (new == NULL) { |
114 | printk(UM_KERN_ERR "need_poll : failed to allocate new " | 115 | printk(UM_KERN_ERR "need_poll : failed to allocate new " |
115 | "pollfds\n"); | 116 | "pollfds\n"); |
@@ -243,7 +244,7 @@ static struct pollfd *setup_initial_poll(int fd) | |||
243 | { | 244 | { |
244 | struct pollfd *p; | 245 | struct pollfd *p; |
245 | 246 | ||
246 | p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); | 247 | p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); |
247 | if (p == NULL) { | 248 | if (p == NULL) { |
248 | printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " | 249 | printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " |
249 | "poll\n"); | 250 | "poll\n"); |
@@ -338,20 +339,10 @@ out_close1: | |||
338 | close(l_write_sigio_fds[1]); | 339 | close(l_write_sigio_fds[1]); |
339 | } | 340 | } |
340 | 341 | ||
341 | /* Changed during early boot */ | 342 | void sigio_broken(int fd, int read) |
342 | static int pty_output_sigio = 0; | ||
343 | static int pty_close_sigio = 0; | ||
344 | |||
345 | void maybe_sigio_broken(int fd, int read) | ||
346 | { | 343 | { |
347 | int err; | 344 | int err; |
348 | 345 | ||
349 | if (!isatty(fd)) | ||
350 | return; | ||
351 | |||
352 | if ((read || pty_output_sigio) && (!read || pty_close_sigio)) | ||
353 | return; | ||
354 | |||
355 | write_sigio_workaround(); | 346 | write_sigio_workaround(); |
356 | 347 | ||
357 | sigio_lock(); | 348 | sigio_lock(); |
@@ -370,6 +361,21 @@ out: | |||
370 | sigio_unlock(); | 361 | sigio_unlock(); |
371 | } | 362 | } |
372 | 363 | ||
364 | /* Changed during early boot */ | ||
365 | static int pty_output_sigio; | ||
366 | static int pty_close_sigio; | ||
367 | |||
368 | void maybe_sigio_broken(int fd, int read) | ||
369 | { | ||
370 | if (!isatty(fd)) | ||
371 | return; | ||
372 | |||
373 | if ((read || pty_output_sigio) && (!read || pty_close_sigio)) | ||
374 | return; | ||
375 | |||
376 | sigio_broken(fd, read); | ||
377 | } | ||
378 | |||
373 | static void sigio_cleanup(void) | 379 | static void sigio_cleanup(void) |
374 | { | 380 | { |
375 | if (write_sigio_pid == -1) | 381 | if (write_sigio_pid == -1) |
@@ -383,7 +389,7 @@ static void sigio_cleanup(void) | |||
383 | __uml_exitcall(sigio_cleanup); | 389 | __uml_exitcall(sigio_cleanup); |
384 | 390 | ||
385 | /* Used as a flag during SIGIO testing early in boot */ | 391 | /* Used as a flag during SIGIO testing early in boot */ |
386 | static volatile int got_sigio = 0; | 392 | static int got_sigio; |
387 | 393 | ||
388 | static void __init handler(int sig) | 394 | static void __init handler(int sig) |
389 | { | 395 | { |
@@ -498,7 +504,8 @@ static void tty_output(int master, int slave) | |||
498 | if (errno != EAGAIN) | 504 | if (errno != EAGAIN) |
499 | printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", | 505 | printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", |
500 | errno); | 506 | errno); |
501 | while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) | 507 | while (((n = read(slave, buf, sizeof(buf))) > 0) && |
508 | !({ barrier(); got_sigio; })) | ||
502 | ; | 509 | ; |
503 | 510 | ||
504 | if (got_sigio) { | 511 | if (got_sigio) { |
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 3f1694b134cb..5aade6027e40 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "as-layout.h" | 12 | #include "as-layout.h" |
13 | #include "kern_util.h" | 13 | #include "kern_util.h" |
14 | #include "os.h" | 14 | #include "os.h" |
15 | #include "process.h" | ||
15 | #include "sysdep/barrier.h" | 16 | #include "sysdep/barrier.h" |
16 | #include "sysdep/sigcontext.h" | 17 | #include "sysdep/sigcontext.h" |
17 | #include "user.h" | 18 | #include "user.h" |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 1e8cba6550a9..6be028ca1817 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
@@ -442,7 +442,7 @@ void userspace(struct uml_pt_regs *regs) | |||
442 | unblock_signals(); | 442 | unblock_signals(); |
443 | break; | 443 | break; |
444 | default: | 444 | default: |
445 | printk(UM_KERN_ERR "userspace - child stopped " | 445 | printk(UM_KERN_ERR "userspace - child stopped " |
446 | "with signal %d\n", sig); | 446 | "with signal %d\n", sig); |
447 | fatal_sigsegv(); | 447 | fatal_sigsegv(); |
448 | } | 448 | } |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 997d01944f91..b4b36e0f2e89 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "mem_user.h" | 23 | #include "mem_user.h" |
24 | #include "ptrace_user.h" | 24 | #include "ptrace_user.h" |
25 | #include "registers.h" | 25 | #include "registers.h" |
26 | #include "skas.h" | ||
26 | #include "skas_ptrace.h" | 27 | #include "skas_ptrace.h" |
27 | 28 | ||
28 | static void ptrace_child(void) | 29 | static void ptrace_child(void) |
@@ -140,14 +141,27 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) | |||
140 | } | 141 | } |
141 | 142 | ||
142 | /* Changed only during early boot */ | 143 | /* Changed only during early boot */ |
143 | int ptrace_faultinfo = 1; | 144 | int ptrace_faultinfo; |
144 | int ptrace_ldt = 1; | 145 | static int disable_ptrace_faultinfo; |
145 | int proc_mm = 1; | 146 | |
146 | int skas_needs_stub = 0; | 147 | int ptrace_ldt; |
148 | static int disable_ptrace_ldt; | ||
149 | |||
150 | int proc_mm; | ||
151 | static int disable_proc_mm; | ||
152 | |||
153 | int have_switch_mm; | ||
154 | static int disable_switch_mm; | ||
155 | |||
156 | int skas_needs_stub; | ||
147 | 157 | ||
148 | static int __init skas0_cmd_param(char *str, int* add) | 158 | static int __init skas0_cmd_param(char *str, int* add) |
149 | { | 159 | { |
150 | ptrace_faultinfo = proc_mm = 0; | 160 | disable_ptrace_faultinfo = 1; |
161 | disable_ptrace_ldt = 1; | ||
162 | disable_proc_mm = 1; | ||
163 | disable_switch_mm = 1; | ||
164 | |||
151 | return 0; | 165 | return 0; |
152 | } | 166 | } |
153 | 167 | ||
@@ -157,15 +171,12 @@ static int __init mode_skas0_cmd_param(char *str, int* add) | |||
157 | __attribute__((alias("skas0_cmd_param"))); | 171 | __attribute__((alias("skas0_cmd_param"))); |
158 | 172 | ||
159 | __uml_setup("skas0", skas0_cmd_param, | 173 | __uml_setup("skas0", skas0_cmd_param, |
160 | "skas0\n" | 174 | "skas0\n" |
161 | " Disables SKAS3 usage, so that SKAS0 is used, unless \n" | 175 | " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); |
162 | " you specify mode=tt.\n\n"); | ||
163 | 176 | ||
164 | __uml_setup("mode=skas0", mode_skas0_cmd_param, | 177 | __uml_setup("mode=skas0", mode_skas0_cmd_param, |
165 | "mode=skas0\n" | 178 | "mode=skas0\n" |
166 | " Disables SKAS3 usage, so that SKAS0 is used, unless you \n" | 179 | " Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); |
167 | " specify mode=tt. Note that this was recently added - on \n" | ||
168 | " older kernels you must use simply \"skas0\".\n\n"); | ||
169 | 180 | ||
170 | /* Changed only during early boot */ | 181 | /* Changed only during early boot */ |
171 | static int force_sysemu_disabled = 0; | 182 | static int force_sysemu_disabled = 0; |
@@ -360,7 +371,7 @@ void __init os_early_checks(void) | |||
360 | 371 | ||
361 | static int __init noprocmm_cmd_param(char *str, int* add) | 372 | static int __init noprocmm_cmd_param(char *str, int* add) |
362 | { | 373 | { |
363 | proc_mm = 0; | 374 | disable_proc_mm = 1; |
364 | return 0; | 375 | return 0; |
365 | } | 376 | } |
366 | 377 | ||
@@ -372,7 +383,7 @@ __uml_setup("noprocmm", noprocmm_cmd_param, | |||
372 | 383 | ||
373 | static int __init noptracefaultinfo_cmd_param(char *str, int* add) | 384 | static int __init noptracefaultinfo_cmd_param(char *str, int* add) |
374 | { | 385 | { |
375 | ptrace_faultinfo = 0; | 386 | disable_ptrace_faultinfo = 1; |
376 | return 0; | 387 | return 0; |
377 | } | 388 | } |
378 | 389 | ||
@@ -384,7 +395,7 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, | |||
384 | 395 | ||
385 | static int __init noptraceldt_cmd_param(char *str, int* add) | 396 | static int __init noptraceldt_cmd_param(char *str, int* add) |
386 | { | 397 | { |
387 | ptrace_ldt = 0; | 398 | disable_ptrace_ldt = 1; |
388 | return 0; | 399 | return 0; |
389 | } | 400 | } |
390 | 401 | ||
@@ -404,17 +415,15 @@ static inline void check_skas3_ptrace_faultinfo(void) | |||
404 | 415 | ||
405 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); | 416 | n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); |
406 | if (n < 0) { | 417 | if (n < 0) { |
407 | ptrace_faultinfo = 0; | ||
408 | if (errno == EIO) | 418 | if (errno == EIO) |
409 | non_fatal("not found\n"); | 419 | non_fatal("not found\n"); |
410 | else | 420 | else |
411 | perror("not found"); | 421 | perror("not found"); |
412 | } | 422 | } else if (disable_ptrace_faultinfo) |
423 | non_fatal("found but disabled on command line\n"); | ||
413 | else { | 424 | else { |
414 | if (!ptrace_faultinfo) | 425 | ptrace_faultinfo = 1; |
415 | non_fatal("found but disabled on command line\n"); | 426 | non_fatal("found\n"); |
416 | else | ||
417 | non_fatal("found\n"); | ||
418 | } | 427 | } |
419 | 428 | ||
420 | stop_ptraced_child(pid, 1, 1); | 429 | stop_ptraced_child(pid, 1, 1); |
@@ -437,38 +446,30 @@ static inline void check_skas3_ptrace_ldt(void) | |||
437 | if (n < 0) { | 446 | if (n < 0) { |
438 | if (errno == EIO) | 447 | if (errno == EIO) |
439 | non_fatal("not found\n"); | 448 | non_fatal("not found\n"); |
440 | else { | 449 | else |
441 | perror("not found"); | 450 | perror("not found"); |
442 | } | 451 | } else if (disable_ptrace_ldt) |
443 | ptrace_ldt = 0; | 452 | non_fatal("found, but use is disabled\n"); |
444 | } | ||
445 | else { | 453 | else { |
446 | if (ptrace_ldt) | 454 | ptrace_ldt = 1; |
447 | non_fatal("found\n"); | 455 | non_fatal("found\n"); |
448 | else | ||
449 | non_fatal("found, but use is disabled\n"); | ||
450 | } | 456 | } |
451 | 457 | ||
452 | stop_ptraced_child(pid, 1, 1); | 458 | stop_ptraced_child(pid, 1, 1); |
453 | #else | ||
454 | /* PTRACE_LDT might be disabled via cmdline option. | ||
455 | * We want to override this, else we might use the stub | ||
456 | * without real need | ||
457 | */ | ||
458 | ptrace_ldt = 1; | ||
459 | #endif | 459 | #endif |
460 | } | 460 | } |
461 | 461 | ||
462 | static inline void check_skas3_proc_mm(void) | 462 | static inline void check_skas3_proc_mm(void) |
463 | { | 463 | { |
464 | non_fatal(" - /proc/mm..."); | 464 | non_fatal(" - /proc/mm..."); |
465 | if (access("/proc/mm", W_OK) < 0) { | 465 | if (access("/proc/mm", W_OK) < 0) |
466 | proc_mm = 0; | ||
467 | perror("not found"); | 466 | perror("not found"); |
468 | } | 467 | else if (disable_proc_mm) |
469 | else if (!proc_mm) | ||
470 | non_fatal("found but disabled on command line\n"); | 468 | non_fatal("found but disabled on command line\n"); |
471 | else non_fatal("found\n"); | 469 | else { |
470 | proc_mm = 1; | ||
471 | non_fatal("found\n"); | ||
472 | } | ||
472 | } | 473 | } |
473 | 474 | ||
474 | void can_do_skas(void) | 475 | void can_do_skas(void) |
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b613473b3ec1..c6183e7aec3d 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <asm/user.h> | ||
8 | #include "kern_constants.h" | 9 | #include "kern_constants.h" |
9 | #include "longjmp.h" | 10 | #include "longjmp.h" |
10 | #include "user.h" | 11 | #include "user.h" |
@@ -74,10 +75,10 @@ int put_fp_registers(int pid, unsigned long *regs) | |||
74 | 75 | ||
75 | void arch_init_registers(int pid) | 76 | void arch_init_registers(int pid) |
76 | { | 77 | { |
77 | unsigned long fpx_regs[HOST_XFP_SIZE]; | 78 | struct user_fxsr_struct fpx_regs; |
78 | int err; | 79 | int err; |
79 | 80 | ||
80 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); | 81 | err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); |
81 | if (!err) | 82 | if (!err) |
82 | return; | 83 | return; |
83 | 84 | ||
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index e49280599465..bee98f466d66 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
@@ -9,7 +9,9 @@ | |||
9 | #include <time.h> | 9 | #include <time.h> |
10 | #include <sys/time.h> | 10 | #include <sys/time.h> |
11 | #include "kern_constants.h" | 11 | #include "kern_constants.h" |
12 | #include "kern_util.h" | ||
12 | #include "os.h" | 13 | #include "os.h" |
14 | #include "process.h" | ||
13 | #include "user.h" | 15 | #include "user.h" |
14 | 16 | ||
15 | int set_interval(void) | 17 | int set_interval(void) |
@@ -58,12 +60,17 @@ static inline long long timeval_to_ns(const struct timeval *tv) | |||
58 | long long disable_timer(void) | 60 | long long disable_timer(void) |
59 | { | 61 | { |
60 | struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); | 62 | struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); |
63 | int remain, max = UM_NSEC_PER_SEC / UM_HZ; | ||
61 | 64 | ||
62 | if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) | 65 | if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) |
63 | printk(UM_KERN_ERR "disable_timer - setitimer failed, " | 66 | printk(UM_KERN_ERR "disable_timer - setitimer failed, " |
64 | "errno = %d\n", errno); | 67 | "errno = %d\n", errno); |
65 | 68 | ||
66 | return timeval_to_ns(&time.it_value); | 69 | remain = timeval_to_ns(&time.it_value); |
70 | if (remain > max) | ||
71 | remain = max; | ||
72 | |||
73 | return remain; | ||
67 | } | 74 | } |
68 | 75 | ||
69 | long long os_nsecs(void) | 76 | long long os_nsecs(void) |
@@ -79,7 +86,44 @@ static int after_sleep_interval(struct timespec *ts) | |||
79 | { | 86 | { |
80 | return 0; | 87 | return 0; |
81 | } | 88 | } |
89 | |||
90 | static void deliver_alarm(void) | ||
91 | { | ||
92 | alarm_handler(SIGVTALRM, NULL); | ||
93 | } | ||
94 | |||
95 | static unsigned long long sleep_time(unsigned long long nsecs) | ||
96 | { | ||
97 | return nsecs; | ||
98 | } | ||
99 | |||
82 | #else | 100 | #else |
101 | unsigned long long last_tick; | ||
102 | unsigned long long skew; | ||
103 | |||
104 | static void deliver_alarm(void) | ||
105 | { | ||
106 | unsigned long long this_tick = os_nsecs(); | ||
107 | int one_tick = UM_NSEC_PER_SEC / UM_HZ; | ||
108 | |||
109 | if (last_tick == 0) | ||
110 | last_tick = this_tick - one_tick; | ||
111 | |||
112 | skew += this_tick - last_tick; | ||
113 | |||
114 | while (skew >= one_tick) { | ||
115 | alarm_handler(SIGVTALRM, NULL); | ||
116 | skew -= one_tick; | ||
117 | } | ||
118 | |||
119 | last_tick = this_tick; | ||
120 | } | ||
121 | |||
122 | static unsigned long long sleep_time(unsigned long long nsecs) | ||
123 | { | ||
124 | return nsecs > skew ? nsecs - skew : 0; | ||
125 | } | ||
126 | |||
83 | static inline long long timespec_to_us(const struct timespec *ts) | 127 | static inline long long timespec_to_us(const struct timespec *ts) |
84 | { | 128 | { |
85 | return ((long long) ts->tv_sec * UM_USEC_PER_SEC) + | 129 | return ((long long) ts->tv_sec * UM_USEC_PER_SEC) + |
@@ -102,6 +146,8 @@ static int after_sleep_interval(struct timespec *ts) | |||
102 | */ | 146 | */ |
103 | if (start_usecs > usec) | 147 | if (start_usecs > usec) |
104 | start_usecs = usec; | 148 | start_usecs = usec; |
149 | |||
150 | start_usecs -= skew / UM_NSEC_PER_USEC; | ||
105 | tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, | 151 | tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, |
106 | .tv_usec = start_usecs % UM_USEC_PER_SEC }); | 152 | .tv_usec = start_usecs % UM_USEC_PER_SEC }); |
107 | interval = ((struct itimerval) { { 0, usec }, tv }); | 153 | interval = ((struct itimerval) { { 0, usec }, tv }); |
@@ -113,8 +159,6 @@ static int after_sleep_interval(struct timespec *ts) | |||
113 | } | 159 | } |
114 | #endif | 160 | #endif |
115 | 161 | ||
116 | extern void alarm_handler(int sig, struct sigcontext *sc); | ||
117 | |||
118 | void idle_sleep(unsigned long long nsecs) | 162 | void idle_sleep(unsigned long long nsecs) |
119 | { | 163 | { |
120 | struct timespec ts; | 164 | struct timespec ts; |
@@ -126,10 +170,12 @@ void idle_sleep(unsigned long long nsecs) | |||
126 | */ | 170 | */ |
127 | if (nsecs == 0) | 171 | if (nsecs == 0) |
128 | nsecs = UM_NSEC_PER_SEC / UM_HZ; | 172 | nsecs = UM_NSEC_PER_SEC / UM_HZ; |
173 | |||
174 | nsecs = sleep_time(nsecs); | ||
129 | ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC, | 175 | ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC, |
130 | .tv_nsec = nsecs % UM_NSEC_PER_SEC }); | 176 | .tv_nsec = nsecs % UM_NSEC_PER_SEC }); |
131 | 177 | ||
132 | if (nanosleep(&ts, &ts) == 0) | 178 | if (nanosleep(&ts, &ts) == 0) |
133 | alarm_handler(SIGVTALRM, NULL); | 179 | deliver_alarm(); |
134 | after_sleep_interval(&ts); | 180 | after_sleep_interval(&ts); |
135 | } | 181 | } |