1 /* $NetBSD: linux32_time.c,v 1.28 2009/01/16 13:10:47 njoly Exp $ */
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.28 2009/01/16 13:10:47 njoly Exp $");
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/fstypes.h>
41 #include <sys/signal.h>
42 #include <sys/dirent.h>
43 #include <sys/kauth.h>
44 #include <sys/kernel.h>
45 #include <sys/fcntl.h>
46 #include <sys/namei.h>
47 #include <sys/select.h>
49 #include <sys/resourcevar.h>
50 #include <sys/ucred.h>
52 #include <sys/vfs_syscalls.h>
53 #include <sys/timetc.h>
55 #include <machine/types.h>
57 #include <sys/syscallargs.h>
59 #include <compat/netbsd32/netbsd32.h>
60 #include <compat/netbsd32/netbsd32_conv.h>
61 #include <compat/netbsd32/netbsd32_syscallargs.h>
63 #include <compat/linux/common/linux_types.h>
64 #include <compat/linux/common/linux_signal.h>
65 #include <compat/linux/common/linux_machdep.h>
66 #include <compat/linux/common/linux_misc.h>
67 #include <compat/linux/common/linux_oldolduname.h>
68 #include <compat/linux/common/linux_sched.h>
69 #include <compat/linux/common/linux_ipc.h>
70 #include <compat/linux/common/linux_sem.h>
71 #include <compat/linux/linux_syscallargs.h>
73 #include <compat/linux32/common/linux32_types.h>
74 #include <compat/linux32/common/linux32_signal.h>
75 #include <compat/linux32/common/linux32_machdep.h>
76 #include <compat/linux32/common/linux32_sysctl.h>
77 #include <compat/linux32/common/linux32_socketcall.h>
78 #include <compat/linux32/linux32_syscallargs.h>
80 extern struct timezone linux_sys_tz
;
83 native_to_linux32_timespec(struct linux32_timespec
*, struct timespec
*);
85 linux32_to_native_timespec(struct timespec
*, struct linux32_timespec
*);
88 linux32_sys_gettimeofday(struct lwp
*l
, const struct linux32_sys_gettimeofday_args
*uap
, register_t
*retval
)
91 syscallarg(netbsd32_timeval50p_t) tp;
92 syscallarg(netbsd32_timezonep_t) tzp;
95 struct netbsd32_timeval50 tv32
;
98 if (SCARG_P32(uap
, tp
) != NULL
) {
100 netbsd32_from_timeval50(&tv
, &tv32
);
101 if ((error
= copyout(&tv32
, SCARG_P32(uap
, tp
),
106 /* timezone size does not change */
107 if (SCARG_P32(uap
, tzp
) != NULL
) {
108 if ((error
= copyout(&linux_sys_tz
, SCARG_P32(uap
, tzp
),
109 sizeof(linux_sys_tz
))) != 0)
117 linux32_sys_settimeofday(struct lwp
*l
, const struct linux32_sys_settimeofday_args
*uap
, register_t
*retval
)
120 syscallarg(netbsd32_timeval50p_t) tp;
121 syscallarg(netbsd32_timezonep_t) tzp;
123 struct linux_sys_settimeofday_args ua
;
125 NETBSD32TOP_UAP(tp
, struct timeval50
);
126 NETBSD32TOP_UAP(tzp
, struct timezone
);
128 return linux_sys_settimeofday(l
, &ua
, retval
);
132 linux32_sys_time(struct lwp
*l
, const struct linux32_sys_time_args
*uap
, register_t
*retval
)
135 syscallarg(linux32_timep_t) t;
143 tt
= (linux32_time_t
)atv
.tv_sec
;
145 if (SCARG_P32(uap
, t
) && (error
= copyout(&tt
,
146 SCARG_P32(uap
, t
), sizeof(tt
))))
155 #define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz))
158 linux32_sys_times(struct lwp
*l
, const struct linux32_sys_times_args
*uap
, register_t
*retval
)
161 syscallarg(linux32_tmsp_t) tms;
163 struct proc
*p
= l
->l_proc
;
167 if (SCARG_P32(uap
, tms
)) {
168 struct linux32_tms ltms32
;
171 mutex_enter(p
->p_lock
);
172 calcru(p
, &ru
.ru_utime
, &ru
.ru_stime
, NULL
, NULL
);
173 ltms32
.ltms32_utime
= CONVTCK(ru
.ru_utime
);
174 ltms32
.ltms32_stime
= CONVTCK(ru
.ru_stime
);
175 ltms32
.ltms32_cutime
= CONVTCK(p
->p_stats
->p_cru
.ru_utime
);
176 ltms32
.ltms32_cstime
= CONVTCK(p
->p_stats
->p_cru
.ru_stime
);
177 mutex_exit(p
->p_lock
);
179 error
= copyout(<ms32
, SCARG_P32(uap
, tms
), sizeof(ltms32
));
186 retval
[0] = ((linux32_clock_t
)(CONVTCK(t
)));
193 linux32_sys_stime(struct lwp
*l
, const struct linux32_sys_stime_args
*uap
, register_t
*retval
)
196 syscallarg(linux32_timep_t) t;
202 if ((error
= copyin(SCARG_P32(uap
, t
), &tt32
, sizeof tt32
)) != 0)
205 ts
.tv_sec
= (long)tt32
;
208 return settime(l
->l_proc
, &ts
);
212 linux32_sys_utime(struct lwp
*l
, const struct linux32_sys_utime_args
*uap
, register_t
*retval
)
215 syscallarg(const netbsd32_charp) path;
216 syscallarg(linux32_utimbufp_t) times;
218 struct timeval tv
[2], *tvp
;
219 struct linux32_utimbuf lut
;
222 if (SCARG_P32(uap
, times
) != NULL
) {
223 if ((error
= copyin(SCARG_P32(uap
, times
), &lut
, sizeof lut
)))
226 tv
[0].tv_sec
= (long)lut
.l_actime
;
228 tv
[1].tv_sec
= (long)lut
.l_modtime
;
235 return do_sys_utimes(l
, NULL
, SCARG_P32(uap
, path
), FOLLOW
,
240 native_to_linux32_timespec(struct linux32_timespec
*ltp
, struct timespec
*ntp
)
242 ltp
->tv_sec
= ntp
->tv_sec
;
243 ltp
->tv_nsec
= ntp
->tv_nsec
;
247 linux32_to_native_timespec(struct timespec
*ntp
, struct linux32_timespec
*ltp
)
249 ntp
->tv_sec
= ltp
->tv_sec
;
250 ntp
->tv_nsec
= ltp
->tv_nsec
;
254 linux32_sys_nanosleep(struct lwp
*l
,
255 const struct linux32_sys_nanosleep_args
*uap
, register_t
*retval
)
258 syscallarg(linux32_timespecp_t) rqtp;
259 syscallarg(linux32_timespecp_t) rmtp;
261 struct timespec rqts
, rmts
;
262 struct linux32_timespec lrqts
, lrmts
;
265 error
= copyin(SCARG_P32(uap
, rqtp
), &lrqts
, sizeof(lrqts
));
268 linux32_to_native_timespec(&rqts
, &lrqts
);
270 error
= nanosleep1(l
, &rqts
, SCARG_P32(uap
, rmtp
) ? &rmts
: NULL
);
271 if (SCARG_P32(uap
, rmtp
) == NULL
|| (error
!= 0 && error
!= EINTR
))
274 native_to_linux32_timespec(&lrmts
, &rmts
);
275 error1
= copyout(&lrmts
, SCARG_P32(uap
, rmtp
), sizeof(lrmts
));
276 return error1
? error1
: error
;
280 linux32_sys_clock_settime(struct lwp
*l
,
281 const struct linux32_sys_clock_settime_args
*uap
, register_t
*retval
)
284 syscallarg(clockid_t) which;
285 syscallarg(linux32_timespecp_t) tp;
289 struct linux32_timespec lts
;
291 switch (SCARG(uap
, which
)) {
292 case LINUX_CLOCK_REALTIME
:
298 if ((error
= copyin(SCARG_P32(uap
, tp
), <s
, sizeof lts
)))
301 linux32_to_native_timespec(&ts
, <s
);
302 return settime(l
->l_proc
, &ts
);
306 linux32_sys_clock_gettime(struct lwp
*l
,
307 const struct linux32_sys_clock_gettime_args
*uap
, register_t
*retval
)
310 syscallarg(clockid_t) which;
311 syscallarg(linux32_timespecp_t) tp;
314 struct linux32_timespec lts
;
316 switch (SCARG(uap
, which
)) {
317 case LINUX_CLOCK_REALTIME
:
320 case LINUX_CLOCK_MONOTONIC
:
327 native_to_linux32_timespec(<s
, &ts
);
328 return copyout(<s
, SCARG_P32(uap
, tp
), sizeof lts
);
332 linux32_sys_clock_getres(struct lwp
*l
,
333 const struct linux32_sys_clock_getres_args
*uap
, register_t
*retval
)
336 syscallarg(clockid_t) which;
337 syscallarg(linux32_timespecp_t) tp;
342 struct linux32_timespec lts
;
344 error
= linux_to_native_clockid(&id
, SCARG(uap
, which
));
345 if (error
!= 0 || SCARG_P32(uap
, tp
) == NULL
)
349 ts
.tv_nsec
= 1000000000 / tc_getfrequency();
350 native_to_linux32_timespec(<s
, &ts
);
351 return copyout(<s
, SCARG_P32(uap
, tp
), sizeof lts
);
355 linux32_sys_clock_nanosleep(struct lwp
*l
,
356 const struct linux32_sys_clock_nanosleep_args
*uap
, register_t
*retval
)
359 syscallarg(clockid_t) which;
360 syscallarg(int) flags;
361 syscallarg(linux32_timespecp_t) rqtp;
362 syscallarg(linux32_timespecp_t) rmtp;
364 struct linux32_timespec lrqts
, lrmts
;
365 struct timespec rqts
, rmts
;
368 if (SCARG(uap
, flags
) != 0)
369 return EINVAL
; /* XXX deal with TIMER_ABSTIME */
370 if (SCARG(uap
, which
) != LINUX_CLOCK_REALTIME
)
373 error
= copyin(SCARG_P32(uap
, rqtp
), &lrqts
, sizeof lrqts
);
376 linux32_to_native_timespec(&rqts
, &lrqts
);
378 error
= nanosleep1(l
, &rqts
, SCARG_P32(uap
, rmtp
) ? &rmts
: 0);
379 if (SCARG_P32(uap
, rmtp
) == NULL
|| (error
!= 0 && error
!= EINTR
))
382 native_to_linux32_timespec(&lrmts
, &rmts
);
383 error1
= copyout(&lrmts
, SCARG_P32(uap
, rmtp
), sizeof lrmts
);
384 return error1
? error1
: error
;