summaryrefslogtreecommitdiff
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2013-10-25 04:51:40 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2013-10-25 04:51:40 +0000
commita871924952f06ea52df5cb0134d210587b460a43 (patch)
tree78d7f384c54e3713ad73f57485bbe672048d8891 /sys/compat/linux
parent9d7e1c14c7bcddb5321ba8a7cb4eec235e427315 (diff)
Start to deal with the time_t change's effect on compat/linux:
- add Linux versions of struct rusage, timeval, and itimerval and conversion functions for them - add Linux versions of getrusage(), gettimeofday(), {set,get}itimer(), and nanosleep() - fix various inconsistencies in naming of Linux versions of types and conversion functions - add mappings for LINUX_CLOCK_{PROCESS,THREAD}_CPUTIME_ID to the native versions Originally written months ago as part of the time_t work; long memory, prodding, and ok from pirofti@
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_futex.c6
-rw-r--r--sys/compat/linux/linux_misc.c150
-rw-r--r--sys/compat/linux/linux_misc.h30
-rw-r--r--sys/compat/linux/linux_time.c244
-rw-r--r--sys/compat/linux/linux_time.h31
-rw-r--r--sys/compat/linux/linux_types.h32
-rw-r--r--sys/compat/linux/syscalls.master35
7 files changed, 412 insertions, 116 deletions
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index 31fabdadba4..8b92876d083 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_futex.c,v 1.14 2013/04/10 13:17:41 pirofti Exp $ */
+/* $OpenBSD: linux_futex.c,v 1.15 2013/10/25 04:51:38 guenther Exp $ */
/* $NetBSD: linux_futex.c,v 1.26 2010/07/07 01:30:35 chs Exp $ */
/*-
@@ -118,7 +118,7 @@ linux_sys_futex(struct proc *p, void *v, register_t *retval)
syscallarg(int) val3;
} */ *uap = v;
- struct l_timespec lts;
+ struct linux_timespec lts;
struct timespec ts = {0, 0};
int error;
@@ -128,7 +128,7 @@ linux_sys_futex(struct proc *p, void *v, register_t *retval)
&lts, sizeof(lts))) != 0) {
return error;
}
- linux_to_native_timespec(&ts, &lts);
+ linux_to_bsd_timespec(&ts, &lts);
}
return linux_do_futex(p, uap, retval, &ts);
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index d78c56f9989..48d41a20c6e 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_misc.c,v 1.81 2013/08/13 05:52:21 guenther Exp $ */
+/* $OpenBSD: linux_misc.c,v 1.82 2013/10/25 04:51:39 guenther Exp $ */
/* $NetBSD: linux_misc.c,v 1.27 1996/05/20 01:59:21 fvdl Exp $ */
/*-
@@ -70,6 +70,7 @@
#include <uvm/uvm_extern.h>
#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_time.h>
#include <compat/linux/linux_fcntl.h>
#include <compat/linux/linux_misc.h>
#include <compat/linux/linux_mmap.h>
@@ -83,12 +84,16 @@
#include <compat/common/compat_dir.h>
/* linux_misc.c */
-static void bsd_to_linux_statfs(struct statfs *, struct linux_statfs *);
+void bsd_to_linux_statfs(const struct statfs *, struct linux_statfs *);
+void bsd_to_linux_statfs64(const struct statfs *, struct linux_statfs64 *);
int linux_select1(struct proc *, register_t *, int, fd_set *,
- fd_set *, fd_set *, struct timeval *);
-static int getdents_common(struct proc *, void *, register_t *, int);
-static void linux_to_bsd_mmap_args(struct sys_mmap_args *,
- const struct linux_sys_mmap2_args *);
+ fd_set *, fd_set *, struct linux_timeval *);
+int getdents_common(struct proc *, void *, register_t *, int);
+void linux_to_bsd_mmap_args(struct sys_mmap_args *,
+ const struct linux_sys_mmap2_args *);
+void bsd_to_linux_rusage(struct linux_rusage *, const struct rusage *);
+void bsd_to_linux_wstat(int *);
+
/*
* The information on a terminated (or stopped) process needs
@@ -109,6 +114,20 @@ bsd_to_linux_wstat(status)
}
/*
+ * Convert an rusage to Linux format: small time_t in the timevals
+ */
+void
+bsd_to_linux_rusage(struct linux_rusage *lrup, const struct rusage *rup)
+{
+ bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime);
+ bsd_to_linux_timeval(&lrup->ru_utime, &rup->ru_utime);
+ memcpy(&lrup->ru_maxrss, &rup->ru_maxrss,
+ offsetof(struct rusage, ru_nivcsw) -
+ offsetof(struct rusage, ru_maxrss) +
+ sizeof(lrup->ru_nivcsw));
+}
+
+/*
* waitpid(2). Just forward on to linux_sys_wait4 with a NULL rusage.
*/
int
@@ -133,9 +152,8 @@ linux_sys_waitpid(p, v, retval)
}
/*
- * wait4(2). Passed on to the OpenBSD call, surrounded by code to reserve
- * some space for an OpenBSD-style wait status, and converting it to what
- * Linux wants.
+ * wait4(2): handle conversion of the options on entry and status and rusage
+ * on return.
*/
int
linux_sys_wait4(p, v, retval)
@@ -147,17 +165,10 @@ linux_sys_wait4(p, v, retval)
syscallarg(int) pid;
syscallarg(int *) status;
syscallarg(int) options;
- syscallarg(struct rusage *) rusage;
+ syscallarg(struct linux_rusage *) rusage;
} */ *uap = v;
- struct sys_wait4_args w4a;
- int error, *status, tstat, linux_options, options;
- caddr_t sg;
-
- if (SCARG(uap, status) != NULL) {
- sg = stackgap_init(p->p_emul);
- status = (int *) stackgap_alloc(&sg, sizeof *status);
- } else
- status = NULL;
+ struct rusage ru;
+ int error, status, linux_options, options;
linux_options = SCARG(uap, options);
options = 0;
@@ -172,27 +183,55 @@ linux_sys_wait4(p, v, retval)
if (linux_options & LINUX_WAIT4_WCLONE)
options |= WALTSIG;
- SCARG(&w4a, pid) = SCARG(uap, pid);
- SCARG(&w4a, status) = status;
- SCARG(&w4a, options) = options;
- SCARG(&w4a, rusage) = SCARG(uap, rusage);
-
- if ((error = sys_wait4(p, &w4a, retval)))
+ if ((error = dowait4(p, SCARG(uap, pid),
+ SCARG(uap, status) ? &status : NULL, options,
+ SCARG(uap, rusage) ? &ru : NULL, retval)))
return error;
atomic_clearbits_int(&p->p_siglist, sigmask(SIGCHLD));
- if (status != NULL) {
- if ((error = copyin(status, &tstat, sizeof tstat)))
- return error;
+ if (SCARG(uap, rusage) != NULL) {
+ struct linux_rusage lru;
- bsd_to_linux_wstat(&tstat);
- return copyout(&tstat, SCARG(uap, status), sizeof tstat);
+ bsd_to_linux_rusage(&lru, &ru);
+ if ((error = copyout(&lru, SCARG(uap, rusage), sizeof lru)))
+ return error;
+ }
+ if (SCARG(uap, status) != NULL) {
+ bsd_to_linux_wstat(&status);
+ return copyout(&status, SCARG(uap, status), sizeof status);
}
return 0;
}
+/*
+ * getrusage(2): convert rusage on return
+ */
+int
+linux_sys_getrusage(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct linux_sys_getrusage_args /* {
+ syscallarg(int) who;
+ syscallarg(struct linux_rusage *) rusage;
+ } */ *uap = v;
+ struct rusage ru;
+ int error;
+
+ error = dogetrusage(p, SCARG(uap, who), &ru);
+ if (error == 0) {
+ struct linux_rusage lru;
+
+ bsd_to_linux_rusage(&lru, &ru);
+ error = copyout(&lru, SCARG(uap, rusage), sizeof lru);
+ }
+ return error;
+}
+
+
int
linux_sys_setresgid16(p, v, retval)
struct proc *p;
@@ -365,8 +404,8 @@ linux_sys_time(p, v, retval)
* the length of a name in a dir entry in a field, which
* we fake (probably the wrong way).
*/
-static void
-bsd_to_linux_statfs(struct statfs *bsp, struct linux_statfs *lsp)
+void
+bsd_to_linux_statfs(const struct statfs *bsp, struct linux_statfs *lsp)
{
/*
@@ -447,8 +486,8 @@ linux_sys_statfs(p, v, retval)
return copyout((caddr_t) &ltmp, (caddr_t) SCARG(uap, sp), sizeof ltmp);
}
-static void
-bsd_to_linux_statfs64(struct statfs *bsp, struct linux_statfs64 *lsp)
+void
+bsd_to_linux_statfs64(const struct statfs *bsp, struct linux_statfs64 *lsp)
{
/*
@@ -763,7 +802,7 @@ linux_sys_mmap2(p, v, retval)
return sys_mmap(p, &cma, retval);
}
-static void
+void
linux_to_bsd_mmap_args(cma, uap)
struct sys_mmap_args *cma;
const struct linux_sys_mmap2_args *uap;
@@ -853,7 +892,7 @@ linux_sys_times(p, v, retval)
register_t *retval;
{
struct linux_sys_times_args /* {
- syscallarg(struct times *) tms;
+ syscallarg(struct linux_tms *) tms;
} */ *uap = v;
struct timeval t, ut, st;
struct linux_tms ltms;
@@ -1135,7 +1174,7 @@ linux_sys_getdents(p, v, retval)
return getdents_common(p, v, retval, 0);
}
-static int
+int
getdents_common(p, v, retval, is64bit)
struct proc *p;
void *v;
@@ -1222,7 +1261,7 @@ linux_sys_select(p, v, retval)
syscallarg(fd_set *) readfds;
syscallarg(fd_set *) writefds;
syscallarg(fd_set *) exceptfds;
- syscallarg(struct timeval *) timeout;
+ syscallarg(struct linux_timeval *) timeout;
} */ *uap = v;
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
@@ -1236,14 +1275,11 @@ linux_sys_select(p, v, retval)
* 2) select never returns ERESTART on Linux, always return EINTR
*/
int
-linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
- struct proc *p;
- register_t *retval;
- int nfds;
- fd_set *readfds, *writefds, *exceptfds;
- struct timeval *timeout;
+linux_select1(struct proc *p, register_t *retval, int nfds, fd_set *readfds,
+ fd_set *writefds, fd_set *exceptfds, struct linux_timeval *timeout)
{
struct sys_select_args bsa;
+ struct linux_timeval lutv;
struct timeval tv0, tv1, utv, *tvp;
caddr_t sg;
int error;
@@ -1252,22 +1288,20 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
SCARG(&bsa, in) = readfds;
SCARG(&bsa, ou) = writefds;
SCARG(&bsa, ex) = exceptfds;
- SCARG(&bsa, tv) = timeout;
/*
* Store current time for computation of the amount of
* time left.
*/
if (timeout) {
- if ((error = copyin(timeout, &utv, sizeof(utv))))
+ if ((error = copyin(timeout, &lutv, sizeof(lutv))))
return error;
+ linux_to_bsd_timeval(&utv, &lutv);
if (itimerfix(&utv)) {
/*
* The timeval was invalid. Convert it to something
* valid that will act as it does under Linux.
*/
- sg = stackgap_init(p->p_emul);
- tvp = stackgap_alloc(&sg, sizeof(utv));
utv.tv_sec += utv.tv_usec / 1000000;
utv.tv_usec %= 1000000;
if (utv.tv_usec < 0) {
@@ -1276,12 +1310,16 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
}
if (utv.tv_sec < 0)
timerclear(&utv);
- if ((error = copyout(&utv, tvp, sizeof(utv))))
- return error;
- SCARG(&bsa, tv) = tvp;
}
+
+ sg = stackgap_init(p->p_emul);
+ tvp = stackgap_alloc(&sg, sizeof(utv));
+ if ((error = copyout(&utv, tvp, sizeof(utv))))
+ return error;
+ SCARG(&bsa, tv) = tvp;
microtime(&tv0);
- }
+ } else
+ SCARG(&bsa, tv) = NULL;
error = sys_select(p, &bsa, retval);
if (error) {
@@ -1291,7 +1329,8 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
*/
if (error == ERESTART)
error = EINTR;
- return error;
+ else if (error != EINTR)
+ return error;
}
if (timeout) {
@@ -1309,11 +1348,12 @@ linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
timerclear(&utv);
} else
timerclear(&utv);
- if ((error = copyout(&utv, timeout, sizeof(utv))))
+ bsd_to_linux_timeval(&lutv, &utv); /* can't fail */
+ if ((error = copyout(&lutv, timeout, sizeof(lutv))))
return error;
}
- return 0;
+ return (error);
}
/*
diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h
index a556cba3159..c4e5924d4c8 100644
--- a/sys/compat/linux/linux_misc.h
+++ b/sys/compat/linux/linux_misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_misc.h,v 1.6 2011/12/14 08:33:18 robert Exp $ */
+/* $OpenBSD: linux_misc.h,v 1.7 2013/10/25 04:51:39 guenther Exp $ */
/* $NetBSD: linux_misc.h,v 1.3 1999/05/13 00:31:57 thorpej Exp $ */
/*-
@@ -64,6 +64,26 @@ struct linux_sysinfo {
char _f[20-2*sizeof(long)-sizeof(int)];
};
+struct linux_rusage {
+ struct linux_timeval ru_utime; /* user time used */
+ struct linux_timeval ru_stime; /* system time used */
+ long ru_maxrss; /* max resident set size */
+ long ru_ixrss; /* integral shared text memory size */
+ long ru_idrss; /* integral unshared data " */
+ long ru_isrss; /* integral unshared stack " */
+ long ru_minflt; /* page reclaims */
+ long ru_majflt; /* page faults */
+ long ru_nswap; /* swaps */
+ long ru_inblock; /* block input operations */
+ long ru_oublock; /* block output operations */
+ long ru_msgsnd; /* messages sent */
+ long ru_msgrcv; /* messages received */
+ long ru_nsignals; /* signals received */
+ long ru_nvcsw; /* voluntary context switches */
+ long ru_nivcsw; /* involuntary " */
+};
+
+
/*
* Options passed to the Linux wait4() system call.
*/
@@ -71,12 +91,4 @@ struct linux_sysinfo {
#define LINUX_WAIT4_WUNTRACED 0x00000002
#define LINUX_WAIT4_WCLONE 0x80000000
-#ifdef _KERNEL
-__BEGIN_DECLS
-void bsd_to_linux_wstat(int *);
-int linux_select1(struct proc *, register_t *, int, fd_set *, fd_set *,
- fd_set *, struct timeval *);
-__END_DECLS
-#endif /* !_KERNEL */
-
#endif /* !_LINUX_MISC_H_ */
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 5f66d7d3da8..f60a2ff6926 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_time.c,v 1.4 2013/05/10 10:31:16 pirofti Exp $ */
+/* $OpenBSD: linux_time.c,v 1.5 2013/10/25 04:51:39 guenther Exp $ */
/*
* Copyright (c) 2010, 2011 Paul Irofti <pirofti@openbsd.org>
*
@@ -23,6 +23,7 @@
#include <sys/time.h>
#include <sys/systm.h>
#include <sys/proc.h>
+#include <sys/kernel.h>
#include <sys/syscallargs.h>
@@ -43,11 +44,10 @@
#define LINUX_CLOCK_MONOTONIC 1
#define LINUX_CLOCK_PROCESS_CPUTIME_ID 2
#define LINUX_CLOCK_THREAD_CPUTIME_ID 3
-#define LINUX_CLOCK_REALTIME_HR 4
-#define LINUX_CLOCK_MONOTONIC_HR 5
+
int
-native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
+bsd_to_linux_timespec(struct linux_timespec *ltp, const struct timespec *ntp)
{
if (ntp->tv_sec > LINUX_TIME_MAX)
return EOVERFLOW;
@@ -57,14 +57,34 @@ native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
}
void
-linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
+linux_to_bsd_timespec(struct timespec *ntp, const struct linux_timespec *ltp)
{
ntp->tv_sec = ltp->tv_sec;
ntp->tv_nsec = ltp->tv_nsec;
}
int
-linux_to_native_clockid(clockid_t *n, clockid_t l)
+bsd_to_linux_itimerval(struct linux_itimerval *ltp,
+ const struct itimerval *ntp)
+{
+ int error;
+
+ error = bsd_to_linux_timeval(&ltp->it_interval, &ntp->it_interval);
+ if (error)
+ return (error);
+ return (bsd_to_linux_timeval(&ltp->it_value, &ntp->it_value));
+}
+
+void
+linux_to_bsd_itimerval(struct itimerval *ntp,
+ const struct linux_itimerval *ltp)
+{
+ linux_to_bsd_timeval(&ntp->it_interval, &ltp->it_interval);
+ linux_to_bsd_timeval(&ntp->it_value, &ltp->it_value);
+}
+
+int
+linux_to_bsd_clockid(clockid_t *n, clockid_t l)
{
switch (l) {
case LINUX_CLOCK_REALTIME:
@@ -74,9 +94,11 @@ linux_to_native_clockid(clockid_t *n, clockid_t l)
*n = CLOCK_MONOTONIC;
break;
case LINUX_CLOCK_PROCESS_CPUTIME_ID:
+ *n = CLOCK_PROCESS_CPUTIME_ID;
+ break;
case LINUX_CLOCK_THREAD_CPUTIME_ID:
- case LINUX_CLOCK_REALTIME_HR:
- case LINUX_CLOCK_MONOTONIC_HR:
+ *n = CLOCK_THREAD_CPUTIME_ID;
+ break;
default:
return (EINVAL);
break;
@@ -89,35 +111,34 @@ int
linux_sys_clock_getres(struct proc *p, void *v, register_t *retval)
{
struct linux_sys_clock_getres_args *uap = v;
- struct sys_clock_getres_args cgr;
-
+ struct linux_timespec ltp;
+ clockid_t clockid;
int error;
if (SCARG(uap, tp) == NULL)
return 0;
- error = linux_to_native_clockid(&SCARG(&cgr, clock_id),
- SCARG(uap, which));
+ error = linux_to_bsd_clockid(&clockid, SCARG(uap, which));
if (error != 0)
return error;
- SCARG(&cgr, tp) = (struct timespec *)SCARG(uap, tp);
- return sys_clock_getres(p, &cgr, retval);
+ /* ahhh, just give a good guess */
+ ltp.tv_sec = 0;
+ ltp.tv_nsec = 1000000000 / hz;
+
+ return (copyout(&ltp, SCARG(uap, tp), sizeof ltp));
}
int
linux_sys_clock_gettime(struct proc *p, void *v, register_t *retval)
{
struct linux_sys_clock_gettime_args *uap = v;
-
- clockid_t clockid = 0;
-
struct timespec tp;
- struct l_timespec ltp;
-
+ struct linux_timespec ltp;
+ clockid_t clockid;
int error;
- error = linux_to_native_clockid(&clockid, SCARG(uap, which));
+ error = linux_to_bsd_clockid(&clockid, SCARG(uap, which));
if (error != 0)
return error;
@@ -125,9 +146,190 @@ linux_sys_clock_gettime(struct proc *p, void *v, register_t *retval)
if (error != 0)
return error;
- error = native_to_linux_timespec(&ltp, &tp);
+ error = bsd_to_linux_timespec(&ltp, &tp);
if (error != 0)
return error;
return (copyout(&ltp, SCARG(uap, tp), sizeof ltp));
}
+
+int
+linux_sys_nanosleep(struct proc *p, void *v, register_t *retval)
+{
+ static int nanowait;
+ struct linux_sys_nanosleep_args /* {
+ syscallarg(const struct linux_timespec *) rqtp;
+ syscallarg(struct linux_timespec *) rmtp;
+ } */ *uap = v;
+ struct linux_timespec lts;
+ struct timespec rqt, rmt;
+ struct timespec sts, ets;
+ struct linux_timespec *rmtp;
+ struct timeval tv;
+ int error, error1;
+
+ rmtp = SCARG(uap, rmtp);
+ error = copyin(SCARG(uap, rqtp), &lts, sizeof(lts));
+ if (error)
+ return (error);
+ linux_to_bsd_timespec(&rqt, &lts);
+
+ TIMESPEC_TO_TIMEVAL(&tv, &rqt);
+ if (itimerfix(&tv))
+ return (EINVAL);
+
+ if (rmtp)
+ getnanouptime(&sts);
+
+ error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep",
+ MAX(1, tvtohz(&tv)));
+ if (error == ERESTART)
+ error = EINTR;
+ if (error == EWOULDBLOCK)
+ error = 0;
+
+ if (rmtp) {
+ getnanouptime(&ets);
+
+ timespecsub(&ets, &sts, &sts);
+ timespecsub(&rqt, &sts, &rmt);
+
+ if (rmt.tv_sec < 0)
+ timespecclear(&rmt);
+
+ if ((error1 = bsd_to_linux_timespec(&lts, &rmt)) ||
+ (error1 = copyout(&lts, rmtp, sizeof(lts))))
+ error = error1;
+ }
+
+ return error;
+}
+
+int
+linux_sys_gettimeofday(struct proc *p, void *v, register_t *retval)
+{
+ struct linux_sys_gettimeofday_args /* {
+ syscallarg(struct linux_timeval *) tp;
+ syscallarg(struct timezone *) tzp;
+ } */ *uap = v;
+ struct timeval atv;
+ struct linux_timeval latv;
+ struct linux_timeval *tp;
+ struct timezone *tzp;
+ int error = 0;
+
+ tp = SCARG(uap, tp);
+ tzp = SCARG(uap, tzp);
+
+ if (tp) {
+ microtime(&atv);
+ if ((error = bsd_to_linux_timeval(&latv, &atv)) ||
+ (error = copyout(&latv, tp, sizeof (latv))))
+ return (error);
+ }
+ if (tzp)
+ error = copyout(&tz, tzp, sizeof (tz));
+ return (error);
+}
+
+int
+linux_sys_getitimer(struct proc *p, void *v, register_t *retval)
+{
+ struct linux_sys_getitimer_args /* {
+ syscallarg(int) which;
+ syscallarg(struct linux_itimerval *) itv;
+ } */ *uap = v;
+ struct itimerval aitv;
+ struct linux_itimerval laitv;
+ int s, which, error;
+
+ which = SCARG(uap, which);
+
+ if (which < ITIMER_REAL || which > ITIMER_PROF)
+ return (EINVAL);
+ s = splclock();
+ aitv = p->p_p->ps_timer[which];
+
+ if (which == ITIMER_REAL) {
+ struct timeval now;
+
+ getmicrouptime(&now);
+ /*
+ * Convert from absolute to relative time in .it_value
+ * part of real time timer. If time for real time timer
+ * has passed return 0, else return difference between
+ * current time and time for the timer to go off.
+ */
+ if (timerisset(&aitv.it_value)) {
+ if (timercmp(&aitv.it_value, &now, <))
+ timerclear(&aitv.it_value);
+ else
+ timersub(&aitv.it_value, &now,
+ &aitv.it_value);
+ }
+ }
+ splx(s);
+ if ((error = bsd_to_linux_itimerval(&laitv, &aitv)))
+ return error;
+ return (copyout(&laitv, SCARG(uap, itv), sizeof(laitv)));
+}
+
+int
+linux_sys_setitimer(struct proc *p, void *v, register_t *retval)
+{
+ struct linux_sys_setitimer_args /* {
+ syscallarg(int) which;
+ syscallarg(const struct linux_itimerval *) itv;
+ syscallarg(struct linux_itimerval *) oitv;
+ } */ *uap = v;
+ struct linux_sys_getitimer_args getargs;
+ struct itimerval aitv;
+ struct linux_itimerval laitv;
+ const struct linux_itimerval *itvp;
+ struct linux_itimerval *oitv;
+ struct process *pr = p->p_p;
+ int error;
+ int timo;
+ int which;
+
+ which = SCARG(uap, which);
+ itvp = SCARG(uap, itv);
+ oitv = SCARG(uap, oitv);
+
+ if (which < ITIMER_REAL || which > ITIMER_PROF)
+ return (EINVAL);
+ if (itvp && (error = copyin(itvp, &laitv, sizeof(laitv))))
+ return (error);
+ if (oitv != NULL) {
+ SCARG(&getargs, which) = which;
+ SCARG(&getargs, itv) = oitv;
+ if ((error = linux_sys_getitimer(p, &getargs, retval)))
+ return (error);
+ }
+ if (itvp == 0)
+ return (0);
+ linux_to_bsd_itimerval(&aitv, &laitv);
+ if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
+ return (EINVAL);
+ if (which == ITIMER_REAL) {
+ struct timeval ctv;
+
+ timeout_del(&pr->ps_realit_to);
+ getmicrouptime(&ctv);
+ if (timerisset(&aitv.it_value)) {
+ timo = tvtohz(&aitv.it_value);
+ timeout_add(&pr->ps_realit_to, timo);
+ timeradd(&aitv.it_value, &ctv, &aitv.it_value);
+ }
+ pr->ps_timer[ITIMER_REAL] = aitv;
+ } else {
+ int s;
+
+ itimerround(&aitv.it_interval);
+ s = splclock();
+ pr->ps_timer[which] = aitv;
+ splx(s);
+ }
+
+ return (0);
+}
diff --git a/sys/compat/linux/linux_time.h b/sys/compat/linux/linux_time.h
index 64ab0dda245..875d3b1adf9 100644
--- a/sys/compat/linux/linux_time.h
+++ b/sys/compat/linux/linux_time.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_time.h,v 1.3 2013/05/10 10:31:16 pirofti Exp $ */
+/* $OpenBSD: linux_time.h,v 1.4 2013/10/25 04:51:39 guenther Exp $ */
/*
* Copyright (c) 2011 Paul Irofti <pirofti@openbsd.org>
*
@@ -18,8 +18,31 @@
#ifndef _LINUX_TIME_H_
#define _LINUX_TIME_H_
-int native_to_linux_timespec(struct l_timespec *, struct timespec *);
-void linux_to_native_timespec(struct timespec *, struct l_timespec *);
-int linux_to_native_clockid(clockid_t *, clockid_t);
+/* BSD to linux can fail with EOVERFLOW */
+int bsd_to_linux_timespec(struct linux_timespec *,
+ const struct timespec *);
+int bsd_to_linux_itimerval(struct linux_itimerval *,
+ const struct itimerval *);
+
+/* linux to BSD can't fail for time_t-based stuff, but can for clockid_t */
+void linux_to_bsd_timespec(struct timespec *,
+ const struct linux_timespec *);
+void linux_to_bsd_itimerval(struct itimerval *,
+ const struct linux_itimerval *);
+int linux_to_bsd_clockid(clockid_t *, clockid_t);
+
+
+/* the timespec conversion functions also handle timeval */
+static inline int
+bsd_to_linux_timeval(struct linux_timeval *ltp, const struct timeval *ntp)
+{
+ return (bsd_to_linux_timespec((void *)ltp, (const void *)ntp));
+}
+static inline void
+linux_to_bsd_timeval(struct timeval *ntp, const struct linux_timeval *ltp)
+{
+ linux_to_bsd_timespec((void *)ntp, (const void *)ltp);
+}
+
#endif
diff --git a/sys/compat/linux/linux_types.h b/sys/compat/linux/linux_types.h
index d700a04b906..9f477c780c4 100644
--- a/sys/compat/linux/linux_types.h
+++ b/sys/compat/linux/linux_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_types.h,v 1.12 2013/05/10 10:31:16 pirofti Exp $ */
+/* $OpenBSD: linux_types.h,v 1.13 2013/10/25 04:51:39 guenther Exp $ */
/* $NetBSD: linux_types.h,v 1.5 1996/05/20 01:59:28 fvdl Exp $ */
/*
@@ -68,6 +68,27 @@ typedef int linux_pid_t;
#define LINUX_FSTYPE_UDF 0x15013346
#define LINUX_FSTYPE_AFS 0x5346414f
+/*
+ * Linux version of time-based structures, passed to many system calls
+ */
+struct linux_timespec {
+ linux_time_t tv_sec;
+ long tv_nsec;
+};
+
+struct linux_timeval {
+ linux_time_t tv_sec;
+ long tv_usec;
+};
+
+struct linux_itimerval {
+ struct linux_timeval it_interval;
+ struct linux_timeval it_value;
+};
+
+/*
+ * Passed to the statfs(2) system call family
+ */
struct linux_statfs {
long l_ftype;
long l_fbsize;
@@ -95,7 +116,7 @@ struct linux_statfs64 {
};
/*
- * Structure for uname(2)
+ * Passed to the uname(2) system call
*/
struct linux_utsname {
char l_sysname[65];
@@ -142,7 +163,7 @@ struct linux_select {
fd_set *readfds;
fd_set *writefds;
fd_set *exceptfds;
- struct timeval *timeout;
+ struct linux_timeval *timeout;
};
struct linux_stat {
@@ -225,9 +246,4 @@ struct linux_stat64 {
linux_ino64_t lst_ino;
};
-struct l_timespec {
- linux_time_t tv_sec;
- long tv_nsec;
-};
-
#endif /* !_LINUX_TYPES_H_ */
diff --git a/sys/compat/linux/syscalls.master b/sys/compat/linux/syscalls.master
index 911efc9a464..c8eecd5dd2f 100644
--- a/sys/compat/linux/syscalls.master
+++ b/sys/compat/linux/syscalls.master
@@ -1,4 +1,4 @@
- $OpenBSD: syscalls.master,v 1.72 2013/08/13 05:52:22 guenther Exp $
+ $OpenBSD: syscalls.master,v 1.73 2013/10/25 04:51:39 guenther Exp $
; $NetBSD: syscalls.master,v 1.15 1995/12/18 14:35:10 fvdl Exp $
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
@@ -98,7 +98,7 @@
40 STD { int linux_sys_rmdir(char *path); }
41 NOARGS { int sys_dup(u_int fd); }
42 NOARGS { int sys_pipe(int *fdp); }
-43 STD { int linux_sys_times(struct times *tms); }
+43 STD { int linux_sys_times(struct linux_tms *tms); }
44 STD { int linux_sys_prof(void); }
45 STD { int linux_sys_brk(char *nsize); }
46 NOARGS linux_setgid16 { int sys_setgid(gid_t gid); }
@@ -143,8 +143,9 @@
struct linux_rlimit *rlp); }
76 STD { int linux_sys_getrlimit(u_int which, \
struct linux_rlimit *rlp); }
-77 NOARGS { int sys_getrusage(int who, struct rusage *rusage); }
-78 NOARGS { int t32_sys_gettimeofday(struct timeval *tp, \
+77 STD { int linux_sys_getrusage(int who, \
+ struct linux_rusage *rusage); }
+78 STD { int linux_sys_gettimeofday(struct linux_timeval *tp, \
struct timezone *tzp); }
79 NOARGS { int sys_settimeofday(struct timeval *tp, \
struct timezone *tzp); }
@@ -185,10 +186,11 @@
#endif
102 STD { int linux_sys_socketcall(int what, void *args); }
103 STD { int linux_sys_klog(void); }
-104 NOARGS { int sys_setitimer(u_int which, \
- struct itimerval *itv, struct itimerval *oitv); }
-105 NOARGS { int sys_getitimer(u_int which, \
- struct itimerval *itv); }
+104 STD { int linux_sys_setitimer(u_int which, \
+ struct linux_itimerval *itv, \
+ struct linux_itimerval *oitv); }
+105 STD { int linux_sys_getitimer(u_int which, \
+ struct linux_itimerval *itv); }
106 STD { int linux_sys_stat(char *path, \
struct linux_stat *sp); }
107 STD { int linux_sys_lstat(char *path, \
@@ -204,9 +206,9 @@
112 STD { int linux_sys_idle(void); }
113 STD { int linux_sys_vm86old(void); }
114 STD { int linux_sys_wait4(int pid, int *status, \
- int options, struct rusage *rusage); }
+ int options, struct linux_rusage *rusage); }
115 STD { int linux_sys_swapoff(void); }
-116 STD { int linux_sys_sysinfo(struct linux_sys_sysinfo_args *sysinfo); }
+116 STD { int linux_sys_sysinfo(struct linux_sysinfo *sysinfo); }
117 STD { int linux_sys_ipc(int what, int a1, int a2, int a3, \
caddr_t ptr); }
118 NOARGS { int sys_fsync(int fd); }
@@ -244,7 +246,7 @@
unsigned count); }
142 STD { int linux_sys_select(int nfds, fd_set *readfds, \
fd_set *writefds, fd_set *exceptfds, \
- struct timeval *timeout); }
+ struct linux_timeval *timeout); }
143 NOARGS { int sys_flock(int fd, int how); }
144 NOARGS { int sys_msync(void *addr, int len, int fl); }
145 NOARGS { int sys_readv(int fd, struct iovec *iovp, \
@@ -269,8 +271,9 @@
159 STD { int linux_sys_sched_get_priority_max(int policy); }
160 STD { int linux_sys_sched_get_priority_min(int policy); }
161 STD { int linux_sys_sched_rr_get_interval(void); }
-162 NOARGS { int t32_sys_nanosleep(const struct timespec32 *rqtp, \
- struct timespec32 *rmtp); }
+162 STD { int linux_sys_nanosleep( \
+ const struct linux_timespec *rqtp, \
+ struct linux_timespec *rmtp); }
163 STD { int linux_sys_mremap(void *old_address, \
size_t old_size, size_t new_size, long flags); }
164 STD { int linux_sys_setresuid16(u_int16_t ruid, \
@@ -383,7 +386,7 @@
238 UNIMPL linux_sys_tkill
239 UNIMPL linux_sys_sendfile64
240 STD { int linux_sys_futex(int *uaddr, int op, int val, \
- const struct linux_timespec *timeout, \
+ const struct linux_timespec *timeout, \
int *uaddr2, int val3); }
241 UNIMPL linux_sys_sched_setaffinity
242 UNIMPL linux_sys_sched_getaffinity
@@ -412,9 +415,9 @@
263 UNIMPL linux_sys_timer_delete
264 UNIMPL linux_sys_clock_settime
265 STD { int linux_sys_clock_gettime(clockid_t which, \
- struct l_timespec *tp); }
+ struct linux_timespec *tp); }
266 STD { int linux_sys_clock_getres(clockid_t which, \
- struct l_timespec *tp); }
+ struct linux_timespec *tp); }
267 UNIMPL linux_sys_clock_nanosleep
268 STD { int linux_sys_statfs64(char *path, \
struct linux_statfs64 *sp); }