diff options
Diffstat (limited to 'arch/um/kernel/time.c')
-rw-r--r-- | arch/um/kernel/time.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c new file mode 100644 index 000000000000..c40c86a3f918 --- /dev/null +++ b/arch/um/kernel/time.c | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <unistd.h> | ||
9 | #include <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 "signal_user.h" | ||
18 | #include "time_user.h" | ||
19 | #include "kern_constants.h" | ||
20 | |||
21 | /* XXX This really needs to be declared and initialized in a kernel file since | ||
22 | * it's in <linux/time.h> | ||
23 | */ | ||
24 | extern struct timespec wall_to_monotonic; | ||
25 | |||
26 | extern struct timeval xtime; | ||
27 | |||
28 | struct timeval local_offset = { 0, 0 }; | ||
29 | |||
30 | void timer(void) | ||
31 | { | ||
32 | gettimeofday(&xtime, NULL); | ||
33 | timeradd(&xtime, &local_offset, &xtime); | ||
34 | } | ||
35 | |||
36 | void set_interval(int timer_type) | ||
37 | { | ||
38 | int usec = 1000000/hz(); | ||
39 | struct itimerval interval = ((struct itimerval) { { 0, usec }, | ||
40 | { 0, usec } }); | ||
41 | |||
42 | if(setitimer(timer_type, &interval, NULL) == -1) | ||
43 | panic("setitimer failed - errno = %d\n", errno); | ||
44 | } | ||
45 | |||
46 | void enable_timer(void) | ||
47 | { | ||
48 | int usec = 1000000/hz(); | ||
49 | struct itimerval enable = ((struct itimerval) { { 0, usec }, | ||
50 | { 0, usec }}); | ||
51 | if(setitimer(ITIMER_VIRTUAL, &enable, NULL)) | ||
52 | printk("enable_timer - setitimer failed, errno = %d\n", | ||
53 | errno); | ||
54 | } | ||
55 | |||
56 | void disable_timer(void) | ||
57 | { | ||
58 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | ||
59 | if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || | ||
60 | (setitimer(ITIMER_REAL, &disable, NULL) < 0)) | ||
61 | printk("disnable_timer - setitimer failed, errno = %d\n", | ||
62 | errno); | ||
63 | /* If there are signals already queued, after unblocking ignore them */ | ||
64 | set_handler(SIGALRM, SIG_IGN, 0, -1); | ||
65 | set_handler(SIGVTALRM, SIG_IGN, 0, -1); | ||
66 | } | ||
67 | |||
68 | void switch_timers(int to_real) | ||
69 | { | ||
70 | struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); | ||
71 | struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, | ||
72 | { 0, 1000000/hz() }}); | ||
73 | int old, new; | ||
74 | |||
75 | if(to_real){ | ||
76 | old = ITIMER_VIRTUAL; | ||
77 | new = ITIMER_REAL; | ||
78 | } | ||
79 | else { | ||
80 | old = ITIMER_REAL; | ||
81 | new = ITIMER_VIRTUAL; | ||
82 | } | ||
83 | |||
84 | if((setitimer(old, &disable, NULL) < 0) || | ||
85 | (setitimer(new, &enable, NULL))) | ||
86 | printk("switch_timers - setitimer failed, errno = %d\n", | ||
87 | errno); | ||
88 | } | ||
89 | |||
90 | void uml_idle_timer(void) | ||
91 | { | ||
92 | if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) | ||
93 | panic("Couldn't unset SIGVTALRM handler"); | ||
94 | |||
95 | set_handler(SIGALRM, (__sighandler_t) alarm_handler, | ||
96 | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); | ||
97 | set_interval(ITIMER_REAL); | ||
98 | } | ||
99 | |||
100 | extern int do_posix_clock_monotonic_gettime(struct timespec *tp); | ||
101 | |||
102 | void time_init(void) | ||
103 | { | ||
104 | struct timespec now; | ||
105 | |||
106 | if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) | ||
107 | panic("Couldn't set SIGVTALRM handler"); | ||
108 | set_interval(ITIMER_VIRTUAL); | ||
109 | |||
110 | do_posix_clock_monotonic_gettime(&now); | ||
111 | wall_to_monotonic.tv_sec = -now.tv_sec; | ||
112 | wall_to_monotonic.tv_nsec = -now.tv_nsec; | ||
113 | } | ||
114 | |||
115 | /* Declared in linux/time.h, which can't be included here */ | ||
116 | extern void clock_was_set(void); | ||
117 | |||
118 | void do_gettimeofday(struct timeval *tv) | ||
119 | { | ||
120 | unsigned long flags; | ||
121 | |||
122 | flags = time_lock(); | ||
123 | gettimeofday(tv, NULL); | ||
124 | timeradd(tv, &local_offset, tv); | ||
125 | time_unlock(flags); | ||
126 | clock_was_set(); | ||
127 | } | ||
128 | |||
129 | int do_settimeofday(struct timespec *tv) | ||
130 | { | ||
131 | struct timeval now; | ||
132 | unsigned long flags; | ||
133 | struct timeval tv_in; | ||
134 | |||
135 | if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC) | ||
136 | return -EINVAL; | ||
137 | |||
138 | tv_in.tv_sec = tv->tv_sec; | ||
139 | tv_in.tv_usec = tv->tv_nsec / 1000; | ||
140 | |||
141 | flags = time_lock(); | ||
142 | gettimeofday(&now, NULL); | ||
143 | timersub(&tv_in, &now, &local_offset); | ||
144 | time_unlock(flags); | ||
145 | |||
146 | return(0); | ||
147 | } | ||
148 | |||
149 | void idle_sleep(int secs) | ||
150 | { | ||
151 | struct timespec ts; | ||
152 | |||
153 | ts.tv_sec = secs; | ||
154 | ts.tv_nsec = 0; | ||
155 | nanosleep(&ts, NULL); | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
160 | * Emacs will notice this stuff at the end of the file and automatically | ||
161 | * adjust the settings for this buffer only. This must remain at the end | ||
162 | * of the file. | ||
163 | * --------------------------------------------------------------------------- | ||
164 | * Local variables: | ||
165 | * c-file-style: "linux" | ||
166 | * End: | ||
167 | */ | ||