| @@ -1,296 +1,297 @@ | | | @@ -1,296 +1,297 @@ |
1 | /* $NetBSD: linux_time.c,v 1.28 2009/01/11 02:45:48 christos Exp $ */ | | 1 | /* $NetBSD: linux_time.c,v 1.29 2009/07/21 18:42:56 njoly Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Emmanuel Dreyfus. | | 8 | * by Emmanuel Dreyfus. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.28 2009/01/11 02:45:48 christos Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.29 2009/07/21 18:42:56 njoly Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/ucred.h> | | 36 | #include <sys/ucred.h> |
37 | #include <sys/kauth.h> | | 37 | #include <sys/kauth.h> |
38 | #include <sys/mount.h> | | 38 | #include <sys/mount.h> |
39 | #include <sys/signal.h> | | 39 | #include <sys/signal.h> |
40 | #include <sys/stdint.h> | | 40 | #include <sys/stdint.h> |
41 | #include <sys/time.h> | | 41 | #include <sys/time.h> |
42 | #include <sys/timetc.h> | | 42 | #include <sys/timetc.h> |
43 | #include <sys/systm.h> | | 43 | #include <sys/systm.h> |
44 | #include <sys/sched.h> | | 44 | #include <sys/sched.h> |
45 | #include <sys/syscallargs.h> | | 45 | #include <sys/syscallargs.h> |
46 | #include <sys/lwp.h> | | 46 | #include <sys/lwp.h> |
47 | #include <sys/proc.h> | | 47 | #include <sys/proc.h> |
48 | | | 48 | |
49 | #include <compat/linux/common/linux_types.h> | | 49 | #include <compat/linux/common/linux_types.h> |
50 | #include <compat/linux/common/linux_signal.h> | | 50 | #include <compat/linux/common/linux_signal.h> |
51 | #include <compat/linux/common/linux_machdep.h> | | 51 | #include <compat/linux/common/linux_machdep.h> |
52 | #include <compat/linux/common/linux_sched.h> | | 52 | #include <compat/linux/common/linux_sched.h> |
53 | #include <compat/linux/common/linux_ipc.h> | | 53 | #include <compat/linux/common/linux_ipc.h> |
54 | #include <compat/linux/common/linux_sem.h> | | 54 | #include <compat/linux/common/linux_sem.h> |
55 | | | 55 | |
56 | #include <compat/linux/linux_syscallargs.h> | | 56 | #include <compat/linux/linux_syscallargs.h> |
57 | | | 57 | |
58 | #include <compat/common/compat_util.h> | | 58 | #include <compat/common/compat_util.h> |
59 | | | 59 | |
60 | void native_to_linux_timespec(struct linux_timespec *, struct timespec *); | | 60 | void native_to_linux_timespec(struct linux_timespec *, struct timespec *); |
61 | void linux_to_native_timespec(struct timespec *, struct linux_timespec *); | | 61 | void linux_to_native_timespec(struct timespec *, struct linux_timespec *); |
62 | /* | | 62 | /* |
63 | * This is not implemented for alpha yet | | 63 | * This is not implemented for alpha yet |
64 | */ | | 64 | */ |
65 | #if defined (__i386__) || defined (__m68k__) || \ | | 65 | #if defined (__i386__) || defined (__m68k__) || \ |
66 | defined (__powerpc__) || defined (__mips__) || \ | | 66 | defined (__powerpc__) || defined (__mips__) || \ |
67 | defined(__arm__) || defined(__amd64__) | | 67 | defined(__arm__) || defined(__amd64__) |
68 | | | 68 | |
69 | /* | | 69 | /* |
70 | * Linux keeps track of a system timezone in the kernel. It is readen | | 70 | * Linux keeps track of a system timezone in the kernel. It is readen |
71 | * by gettimeofday and set by settimeofday. This emulates this behavior | | 71 | * by gettimeofday and set by settimeofday. This emulates this behavior |
72 | * See linux/kernel/time.c | | 72 | * See linux/kernel/time.c |
73 | */ | | 73 | */ |
74 | struct timezone linux_sys_tz; | | 74 | struct timezone linux_sys_tz; |
75 | | | 75 | |
76 | int | | 76 | int |
77 | linux_sys_gettimeofday(struct lwp *l, const struct linux_sys_gettimeofday_args *uap, register_t *retval) | | 77 | linux_sys_gettimeofday(struct lwp *l, const struct linux_sys_gettimeofday_args *uap, register_t *retval) |
78 | { | | 78 | { |
79 | /* { | | 79 | /* { |
80 | syscallarg(struct timeval50 *) tz; | | 80 | syscallarg(struct timeval50 *) tz; |
81 | syscallarg(struct timezone *) tzp; | | 81 | syscallarg(struct timezone *) tzp; |
82 | } */ | | 82 | } */ |
83 | int error = 0; | | 83 | int error = 0; |
84 | | | 84 | |
85 | if (SCARG(uap, tp)) { | | 85 | if (SCARG(uap, tp)) { |
86 | error = compat_50_sys_gettimeofday(l, (const void *)uap, retval); | | 86 | error = compat_50_sys_gettimeofday(l, (const void *)uap, retval); |
87 | if (error) | | 87 | if (error) |
88 | return (error); | | 88 | return (error); |
89 | } | | 89 | } |
90 | | | 90 | |
91 | if (SCARG(uap, tzp)) { | | 91 | if (SCARG(uap, tzp)) { |
92 | error = copyout(&linux_sys_tz, SCARG(uap, tzp), sizeof(linux_sys_tz)); | | 92 | error = copyout(&linux_sys_tz, SCARG(uap, tzp), sizeof(linux_sys_tz)); |
93 | if (error) | | 93 | if (error) |
94 | return (error); | | 94 | return (error); |
95 | } | | 95 | } |
96 | | | 96 | |
97 | return (0); | | 97 | return (0); |
98 | } | | 98 | } |
99 | | | 99 | |
100 | int | | 100 | int |
101 | linux_sys_settimeofday(struct lwp *l, const struct linux_sys_settimeofday_args *uap, register_t *retval) | | 101 | linux_sys_settimeofday(struct lwp *l, const struct linux_sys_settimeofday_args *uap, register_t *retval) |
102 | { | | 102 | { |
103 | /* { | | 103 | /* { |
104 | syscallarg(struct timeval50 *) tp; | | 104 | syscallarg(struct timeval50 *) tp; |
105 | syscallarg(struct timezone *) tzp; | | 105 | syscallarg(struct timezone *) tzp; |
106 | } */ | | 106 | } */ |
107 | int error = 0; | | 107 | int error = 0; |
108 | | | 108 | |
109 | if (SCARG(uap, tp)) { | | 109 | if (SCARG(uap, tp)) { |
110 | error = compat_50_sys_settimeofday(l, (const void *)uap, retval); | | 110 | error = compat_50_sys_settimeofday(l, (const void *)uap, retval); |
111 | if (error) | | 111 | if (error) |
112 | return (error); | | 112 | return (error); |
113 | } | | 113 | } |
114 | | | 114 | |
115 | /* | | 115 | /* |
116 | * If user is not the superuser, we returned | | 116 | * If user is not the superuser, we returned |
117 | * after the sys_settimeofday() call. | | 117 | * after the sys_settimeofday() call. |
118 | */ | | 118 | */ |
119 | if (SCARG(uap, tzp)) { | | 119 | if (SCARG(uap, tzp)) { |
120 | error = copyin(SCARG(uap, tzp), &linux_sys_tz, sizeof(linux_sys_tz)); | | 120 | error = copyin(SCARG(uap, tzp), &linux_sys_tz, sizeof(linux_sys_tz)); |
121 | if (error) | | 121 | if (error) |
122 | return (error); | | 122 | return (error); |
123 | } | | 123 | } |
124 | | | 124 | |
125 | return (0); | | 125 | return (0); |
126 | } | | 126 | } |
127 | | | 127 | |
128 | #endif /* __i386__ || __m68k__ || __powerpc__ || __mips__ || __arm__ */ | | 128 | #endif /* __i386__ || __m68k__ || __powerpc__ || __mips__ || __arm__ */ |
129 | | | 129 | |
130 | void | | 130 | void |
131 | native_to_linux_timespec(struct linux_timespec *ltp, struct timespec *ntp) | | 131 | native_to_linux_timespec(struct linux_timespec *ltp, struct timespec *ntp) |
132 | { | | 132 | { |
133 | ltp->tv_sec = ntp->tv_sec; | | 133 | ltp->tv_sec = ntp->tv_sec; |
134 | ltp->tv_nsec = ntp->tv_nsec; | | 134 | ltp->tv_nsec = ntp->tv_nsec; |
135 | } | | 135 | } |
136 | | | 136 | |
137 | void | | 137 | void |
138 | linux_to_native_timespec(struct timespec *ntp, struct linux_timespec *ltp) | | 138 | linux_to_native_timespec(struct timespec *ntp, struct linux_timespec *ltp) |
139 | { | | 139 | { |
140 | ntp->tv_sec = ltp->tv_sec; | | 140 | ntp->tv_sec = ltp->tv_sec; |
141 | ntp->tv_nsec = ltp->tv_nsec; | | 141 | ntp->tv_nsec = ltp->tv_nsec; |
142 | } | | 142 | } |
143 | | | 143 | |
144 | int | | 144 | int |
145 | linux_sys_nanosleep(struct lwp *l, const struct linux_sys_nanosleep_args *uap, | | 145 | linux_sys_nanosleep(struct lwp *l, const struct linux_sys_nanosleep_args *uap, |
146 | register_t *retval) | | 146 | register_t *retval) |
147 | { | | 147 | { |
148 | /* { | | 148 | /* { |
149 | syscallarg(struct linux_timespec *) rqtp; | | 149 | syscallarg(struct linux_timespec *) rqtp; |
150 | syscallarg(struct linux_timespec *) rmtp; | | 150 | syscallarg(struct linux_timespec *) rmtp; |
151 | } */ | | 151 | } */ |
152 | struct timespec rqts, rmts; | | 152 | struct timespec rqts, rmts; |
153 | struct linux_timespec lrqts, lrmts; | | 153 | struct linux_timespec lrqts, lrmts; |
154 | int error, error1; | | 154 | int error, error1; |
155 | | | 155 | |
156 | error = copyin(SCARG(uap, rqtp), &lrqts, sizeof(lrqts)); | | 156 | error = copyin(SCARG(uap, rqtp), &lrqts, sizeof(lrqts)); |
157 | if (error != 0) | | 157 | if (error != 0) |
158 | return error; | | 158 | return error; |
159 | linux_to_native_timespec(&rqts, &lrqts); | | 159 | linux_to_native_timespec(&rqts, &lrqts); |
160 | | | 160 | |
161 | error = nanosleep1(l, &rqts, SCARG(uap, rmtp) ? &rmts : NULL); | | 161 | error = nanosleep1(l, &rqts, SCARG(uap, rmtp) ? &rmts : NULL); |
162 | if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) | | 162 | if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) |
163 | return error; | | 163 | return error; |
164 | | | 164 | |
165 | native_to_linux_timespec(&lrmts, &rmts); | | 165 | native_to_linux_timespec(&lrmts, &rmts); |
166 | error1 = copyout(&lrmts, SCARG(uap, rmtp), sizeof(lrmts)); | | 166 | error1 = copyout(&lrmts, SCARG(uap, rmtp), sizeof(lrmts)); |
167 | return error1 ? error1 : error; | | 167 | return error1 ? error1 : error; |
168 | } | | 168 | } |
169 | | | 169 | |
170 | int | | 170 | int |
171 | linux_to_native_clockid(clockid_t *n, clockid_t l) | | 171 | linux_to_native_clockid(clockid_t *n, clockid_t l) |
172 | { | | 172 | { |
173 | switch (l) { | | 173 | switch (l) { |
174 | case LINUX_CLOCK_REALTIME: | | 174 | case LINUX_CLOCK_REALTIME: |
175 | *n = CLOCK_REALTIME; | | 175 | *n = CLOCK_REALTIME; |
176 | break; | | 176 | break; |
177 | case LINUX_CLOCK_MONOTONIC: | | 177 | case LINUX_CLOCK_MONOTONIC: |
178 | *n = CLOCK_MONOTONIC; | | 178 | *n = CLOCK_MONOTONIC; |
179 | break; | | 179 | break; |
180 | case LINUX_CLOCK_PROCESS_CPUTIME_ID: | | 180 | case LINUX_CLOCK_PROCESS_CPUTIME_ID: |
181 | case LINUX_CLOCK_THREAD_CPUTIME_ID: | | 181 | case LINUX_CLOCK_THREAD_CPUTIME_ID: |
182 | case LINUX_CLOCK_REALTIME_HR: | | 182 | case LINUX_CLOCK_REALTIME_HR: |
183 | case LINUX_CLOCK_MONOTONIC_HR: | | 183 | case LINUX_CLOCK_MONOTONIC_HR: |
| | | 184 | default: |
184 | return EINVAL; | | 185 | return EINVAL; |
185 | } | | 186 | } |
186 | | | 187 | |
187 | return 0; | | 188 | return 0; |
188 | } | | 189 | } |
189 | | | 190 | |
190 | int | | 191 | int |
191 | linux_sys_clock_gettime(struct lwp *l, const struct linux_sys_clock_gettime_args *uap, register_t *retval) | | 192 | linux_sys_clock_gettime(struct lwp *l, const struct linux_sys_clock_gettime_args *uap, register_t *retval) |
192 | { | | 193 | { |
193 | /* { | | 194 | /* { |
194 | syscallarg(clockid_t) which; | | 195 | syscallarg(clockid_t) which; |
195 | syscallarg(struct linux_timespec *)tp; | | 196 | syscallarg(struct linux_timespec *)tp; |
196 | } */ | | 197 | } */ |
197 | struct timespec ts; | | 198 | struct timespec ts; |
198 | struct linux_timespec lts; | | 199 | struct linux_timespec lts; |
199 | | | 200 | |
200 | switch (SCARG(uap, which)) { | | 201 | switch (SCARG(uap, which)) { |
201 | case LINUX_CLOCK_REALTIME: | | 202 | case LINUX_CLOCK_REALTIME: |
202 | nanotime(&ts); | | 203 | nanotime(&ts); |
203 | break; | | 204 | break; |
204 | case LINUX_CLOCK_MONOTONIC: | | 205 | case LINUX_CLOCK_MONOTONIC: |
205 | nanouptime(&ts); | | 206 | nanouptime(&ts); |
206 | break; | | 207 | break; |
207 | default: | | 208 | default: |
208 | return EINVAL; | | 209 | return EINVAL; |
209 | } | | 210 | } |
210 | | | 211 | |
211 | native_to_linux_timespec(<s, &ts); | | 212 | native_to_linux_timespec(<s, &ts); |
212 | return copyout(<s, SCARG(uap, tp), sizeof lts); | | 213 | return copyout(<s, SCARG(uap, tp), sizeof lts); |
213 | } | | 214 | } |
214 | | | 215 | |
215 | int | | 216 | int |
216 | linux_sys_clock_settime(struct lwp *l, const struct linux_sys_clock_settime_args *uap, register_t *retval) | | 217 | linux_sys_clock_settime(struct lwp *l, const struct linux_sys_clock_settime_args *uap, register_t *retval) |
217 | { | | 218 | { |
218 | /* { | | 219 | /* { |
219 | syscallarg(clockid_t) which; | | 220 | syscallarg(clockid_t) which; |
220 | syscallarg(struct linux_timespec *)tp; | | 221 | syscallarg(struct linux_timespec *)tp; |
221 | } */ | | 222 | } */ |
222 | struct timespec ts; | | 223 | struct timespec ts; |
223 | struct linux_timespec lts; | | 224 | struct linux_timespec lts; |
224 | int error; | | 225 | int error; |
225 | | | 226 | |
226 | switch (SCARG(uap, which)) { | | 227 | switch (SCARG(uap, which)) { |
227 | case LINUX_CLOCK_REALTIME: | | 228 | case LINUX_CLOCK_REALTIME: |
228 | break; | | 229 | break; |
229 | default: | | 230 | default: |
230 | return EINVAL; | | 231 | return EINVAL; |
231 | } | | 232 | } |
232 | | | 233 | |
233 | error = copyin(SCARG(uap, tp), <s, sizeof lts); | | 234 | error = copyin(SCARG(uap, tp), <s, sizeof lts); |
234 | if (error != 0) | | 235 | if (error != 0) |
235 | return error; | | 236 | return error; |
236 | | | 237 | |
237 | linux_to_native_timespec(&ts, <s); | | 238 | linux_to_native_timespec(&ts, <s); |
238 | | | 239 | |
239 | return settime(l->l_proc, &ts); | | 240 | return settime(l->l_proc, &ts); |
240 | } | | 241 | } |
241 | | | 242 | |
242 | int | | 243 | int |
243 | linux_sys_clock_getres(struct lwp *l, const struct linux_sys_clock_getres_args *uap, register_t *retval) | | 244 | linux_sys_clock_getres(struct lwp *l, const struct linux_sys_clock_getres_args *uap, register_t *retval) |
244 | { | | 245 | { |
245 | /* { | | 246 | /* { |
246 | syscallarg(clockid_t) which; | | 247 | syscallarg(clockid_t) which; |
247 | syscallarg(struct linux_timespec *)tp; | | 248 | syscallarg(struct linux_timespec *)tp; |
248 | } */ | | 249 | } */ |
249 | struct timespec ts; | | 250 | struct timespec ts; |
250 | struct linux_timespec lts; | | 251 | struct linux_timespec lts; |
251 | int error; | | 252 | int error; |
252 | clockid_t nwhich = 0; /* XXX: GCC */ | | 253 | clockid_t nwhich = 0; /* XXX: GCC */ |
253 | | | 254 | |
254 | error = linux_to_native_clockid(&nwhich, SCARG(uap, which)); | | 255 | error = linux_to_native_clockid(&nwhich, SCARG(uap, which)); |
255 | if (error != 0 || SCARG(uap, tp) == NULL) | | 256 | if (error != 0 || SCARG(uap, tp) == NULL) |
256 | return error; | | 257 | return error; |
257 | | | 258 | |
258 | ts.tv_sec = 0; | | 259 | ts.tv_sec = 0; |
259 | ts.tv_nsec = 1000000000 / tc_getfrequency(); | | 260 | ts.tv_nsec = 1000000000 / tc_getfrequency(); |
260 | native_to_linux_timespec(<s, &ts); | | 261 | native_to_linux_timespec(<s, &ts); |
261 | return copyout(<s, SCARG(uap, tp), sizeof lts); | | 262 | return copyout(<s, SCARG(uap, tp), sizeof lts); |
262 | } | | 263 | } |
263 | | | 264 | |
264 | int | | 265 | int |
265 | linux_sys_clock_nanosleep(struct lwp *l, const struct linux_sys_clock_nanosleep_args *uap, register_t *retval) | | 266 | linux_sys_clock_nanosleep(struct lwp *l, const struct linux_sys_clock_nanosleep_args *uap, register_t *retval) |
266 | { | | 267 | { |
267 | /* { | | 268 | /* { |
268 | syscallarg(clockid_t) which; | | 269 | syscallarg(clockid_t) which; |
269 | syscallarg(int) flags; | | 270 | syscallarg(int) flags; |
270 | syscallarg(struct linux_timespec) *rqtp; | | 271 | syscallarg(struct linux_timespec) *rqtp; |
271 | syscallarg(struct linux_timespec) *rmtp; | | 272 | syscallarg(struct linux_timespec) *rmtp; |
272 | } */ | | 273 | } */ |
273 | struct linux_timespec lrqts, lrmts; | | 274 | struct linux_timespec lrqts, lrmts; |
274 | struct timespec rqts, rmts; | | 275 | struct timespec rqts, rmts; |
275 | int error, error1; | | 276 | int error, error1; |
276 | | | 277 | |
277 | if (SCARG(uap, flags) != 0) | | 278 | if (SCARG(uap, flags) != 0) |
278 | return EINVAL; /* XXX deal with TIMER_ABSTIME */ | | 279 | return EINVAL; /* XXX deal with TIMER_ABSTIME */ |
279 | | | 280 | |
280 | if (SCARG(uap, which) != LINUX_CLOCK_REALTIME) | | 281 | if (SCARG(uap, which) != LINUX_CLOCK_REALTIME) |
281 | return EINVAL; | | 282 | return EINVAL; |
282 | | | 283 | |
283 | error = copyin(SCARG(uap, rqtp), &lrqts, sizeof lrqts); | | 284 | error = copyin(SCARG(uap, rqtp), &lrqts, sizeof lrqts); |
284 | if (error != 0) | | 285 | if (error != 0) |
285 | return error; | | 286 | return error; |
286 | | | 287 | |
287 | linux_to_native_timespec(&rqts, &lrqts); | | 288 | linux_to_native_timespec(&rqts, &lrqts); |
288 | | | 289 | |
289 | error = nanosleep1(l, &rqts, SCARG(uap, rmtp) ? &rmts : 0); | | 290 | error = nanosleep1(l, &rqts, SCARG(uap, rmtp) ? &rmts : 0); |
290 | if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) | | 291 | if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) |
291 | return error; | | 292 | return error; |
292 | | | 293 | |
293 | native_to_linux_timespec(&lrmts, &rmts); | | 294 | native_to_linux_timespec(&lrmts, &rmts); |
294 | error1 = copyout(&lrmts, SCARG(uap, rmtp), sizeof lrmts); | | 295 | error1 = copyout(&lrmts, SCARG(uap, rmtp), sizeof lrmts); |
295 | return error1 ? error1 : error; | | 296 | return error1 ? error1 : error; |
296 | } | | 297 | } |