diff options
Diffstat (limited to 'arch/um/os-Linux/time.c')
-rw-r--r-- | arch/um/os-Linux/time.c | 131 |
1 files changed, 119 insertions, 12 deletions
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index cf30a39bc484..6f7626775acb 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c | |||
@@ -1,21 +1,128 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
1 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include <unistd.h> | ||
9 | #include <time.h> | ||
2 | #include <sys/time.h> | 10 | #include <sys/time.h> |
11 | #include <signal.h> | ||
12 | #include <errno.h> | ||
13 | #include "user_util.h" | ||
14 | #include "kern_util.h" | ||
15 | #include "user.h" | ||
16 | #include "process.h" | ||
17 | #include "kern_constants.h" | ||
18 | #include "os.h" | ||
19 | |||
20 | /* XXX This really needs to be declared and initialized in a kernel file since | ||
21 | * it's in <linux/time.h> | ||
22 | */ | ||
23 | extern struct timespec wall_to_monotonic; | ||
24 | |||
25 | static void set_interval(int timer_type) | ||
26 | { | ||
27 | int usec = 1000000/hz(); | ||
28 | struct itimerval interval = ((struct itimerval) { { 0, usec }, | ||
29 | { 0, usec } }); | ||
30 | |||
31 | if(setitimer(timer_type, &interval, NULL) == -1) | ||
32 | panic("setitimer failed - errno = %d\n", errno); | ||
33 | } | ||
34 | |||
35 | void enable_timer(void) | ||
36 | { | ||
37 | set_interval(ITIMER_VIRTUAL); | ||
38 | } | ||
39 | |||
40 | void disable_timer(void) | ||
41 | { | ||
42 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | ||
43 | if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || | ||
44 | (setitimer(ITIMER_REAL, &disable, NULL) < 0)) | ||
45 | printk("disnable_timer - setitimer failed, errno = %d\n", | ||
46 | errno); | ||
47 | /* If there are signals already queued, after unblocking ignore them */ | ||
48 | set_handler(SIGALRM, SIG_IGN, 0, -1); | ||
49 | set_handler(SIGVTALRM, SIG_IGN, 0, -1); | ||
50 | } | ||
51 | |||
52 | void switch_timers(int to_real) | ||
53 | { | ||
54 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | ||
55 | struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, | ||
56 | { 0, 1000000/hz() }}); | ||
57 | int old, new; | ||
58 | |||
59 | if(to_real){ | ||
60 | old = ITIMER_VIRTUAL; | ||
61 | new = ITIMER_REAL; | ||
62 | } | ||
63 | else { | ||
64 | old = ITIMER_REAL; | ||
65 | new = ITIMER_VIRTUAL; | ||
66 | } | ||
67 | |||
68 | if((setitimer(old, &disable, NULL) < 0) || | ||
69 | (setitimer(new, &enable, NULL))) | ||
70 | printk("switch_timers - setitimer failed, errno = %d\n", | ||
71 | errno); | ||
72 | } | ||
3 | 73 | ||
4 | unsigned long long os_usecs(void) | 74 | void uml_idle_timer(void) |
75 | { | ||
76 | if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) | ||
77 | panic("Couldn't unset SIGVTALRM handler"); | ||
78 | |||
79 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | ||
80 | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); | ||
81 | set_interval(ITIMER_REAL); | ||
82 | } | ||
83 | |||
84 | extern void ktime_get_ts(struct timespec *ts); | ||
85 | #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) | ||
86 | |||
87 | void time_init(void) | ||
88 | { | ||
89 | struct timespec now; | ||
90 | |||
91 | if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) | ||
92 | panic("Couldn't set SIGVTALRM handler"); | ||
93 | set_interval(ITIMER_VIRTUAL); | ||
94 | |||
95 | do_posix_clock_monotonic_gettime(&now); | ||
96 | wall_to_monotonic.tv_sec = -now.tv_sec; | ||
97 | wall_to_monotonic.tv_nsec = -now.tv_nsec; | ||
98 | } | ||
99 | |||
100 | unsigned long long os_nsecs(void) | ||
5 | { | 101 | { |
6 | struct timeval tv; | 102 | struct timeval tv; |
7 | 103 | ||
8 | gettimeofday(&tv, NULL); | 104 | gettimeofday(&tv, NULL); |
9 | return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); | 105 | return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); |
10 | } | 106 | } |
11 | 107 | ||
12 | /* | 108 | void idle_sleep(int secs) |
13 | * Overrides for Emacs so that we follow Linus's tabbing style. | 109 | { |
14 | * Emacs will notice this stuff at the end of the file and automatically | 110 | struct timespec ts; |
15 | * adjust the settings for this buffer only. This must remain at the end | 111 | |
16 | * of the file. | 112 | ts.tv_sec = secs; |
17 | * --------------------------------------------------------------------------- | 113 | ts.tv_nsec = 0; |
18 | * Local variables: | 114 | nanosleep(&ts, NULL); |
19 | * c-file-style: "linux" | 115 | } |
20 | * End: | 116 | |
21 | */ | 117 | /* XXX This partly duplicates init_irq_signals */ |
118 | |||
119 | void user_time_init(void) | ||
120 | { | ||
121 | set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, | ||
122 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, | ||
123 | SIGALRM, SIGUSR2, -1); | ||
124 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | ||
125 | SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, | ||
126 | SIGVTALRM, SIGUSR2, -1); | ||
127 | set_interval(ITIMER_VIRTUAL); | ||
128 | } | ||