Module Name: src Committed By: thorpej Date: Thu Dec 17 03:05:32 UTC 2020
Modified Files: src/sys/compat/linux32/arch/amd64 [thorpej-futex]: syscalls.master src/sys/compat/linux32/common [thorpej-futex]: linux32_sched.h linux32_time.c Log Message: Add POSIX timer and timerfd support to COMPAT_LINUX32. To generate a diff of this commit: cvs rdiff -u -r1.71.2.1 -r1.71.2.2 \ src/sys/compat/linux32/arch/amd64/syscalls.master cvs rdiff -u -r1.1 -r1.1.66.1 src/sys/compat/linux32/common/linux32_sched.h cvs rdiff -u -r1.37 -r1.37.50.1 src/sys/compat/linux32/common/linux32_time.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/linux32/arch/amd64/syscalls.master diff -u src/sys/compat/linux32/arch/amd64/syscalls.master:1.71.2.1 src/sys/compat/linux32/arch/amd64/syscalls.master:1.71.2.2 --- src/sys/compat/linux32/arch/amd64/syscalls.master:1.71.2.1 Wed Dec 16 03:07:43 2020 +++ src/sys/compat/linux32/arch/amd64/syscalls.master Thu Dec 17 03:05:32 2020 @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.71.2.1 2020/12/16 03:07:43 thorpej Exp $ + $NetBSD: syscalls.master,v 1.71.2.2 2020/12/17 03:05:32 thorpej Exp $ ; NetBSD i386 COMPAT_LINUX32 system call name/number "master" file. ; (See syscalls.conf to see what it is processed into.) @@ -454,11 +454,15 @@ 256 UNIMPL epoll_wait 257 UNIMPL remap_file_pages 258 STD { int|linux32_sys||set_tid_address(linux32_intp_t tid); } -259 UNIMPL timer_create -260 UNIMPL timer_settime -261 UNIMPL timer_gettime -262 UNIMPL timer_getoverrun -263 UNIMPL timer_delete +259 STD { int|linux32_sys||timer_create(clockid_t clockid, \ + struct linux32_sigevent *evp, timer_t *timerid); } +260 STD { int|linux32_sys||timer_settime(timer_t timerid, \ + int flags, const struct linux32_itimerspec *tim, \ + struct linux32_itimerspec *otim); } +261 STD { int|linux32_sys||timer_gettime(timer_t timerid, \ + struct linux32_itimerspec *tim); } +262 NOARGS { int|sys||timer_getoverrun(timer_t timerid); } +263 NOARGS { int|sys||timer_delete(timer_t timerid); } 264 STD { int|linux32_sys||clock_settime(clockid_t which, \ linux32_timespecp_t tp); } 265 STD { int|linux32_sys||clock_gettime(clockid_t which, \ @@ -546,12 +550,16 @@ 320 STD { int|linux32_sys||utimensat(int fd, netbsd32_charp path, \ linux32_timespecp_t times, int flag); } 321 UNIMPL signalfd -322 UNIMPL timerfd_create +322 NOARGS { int|linux_sys||timerfd_create(clockid_t clock_id, \ + int flags); } 323 STD { int|linux32_sys||eventfd(unsigned int initval); } 324 STD { int|linux32_sys||fallocate(int fd, int mode, \ off_t offset, off_t len); } -325 UNIMPL timerfd_settime -326 UNIMPL timerfd_gettime +325 STD { int|linux32_sys||timerfd_settime(int fd, int flags, \ + const struct linux32_itimerspec *new_value, \ + struct linux32_itimerspec *old_value); } +326 STD { int|linux32_sys||timerfd_gettime(int fd, \ + struct linux32_itimerspec *curr_value); } 327 UNIMPL signalfd4 328 STD { int|linux32_sys||eventfd2(unsigned int initval, \ int flags); } Index: src/sys/compat/linux32/common/linux32_sched.h diff -u src/sys/compat/linux32/common/linux32_sched.h:1.1 src/sys/compat/linux32/common/linux32_sched.h:1.1.66.1 --- src/sys/compat/linux32/common/linux32_sched.h:1.1 Fri Nov 18 04:08:56 2011 +++ src/sys/compat/linux32/common/linux32_sched.h Thu Dec 17 03:05:32 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_sched.h,v 1.1 2011/11/18 04:08:56 christos Exp $ */ +/* $NetBSD: linux32_sched.h,v 1.1.66.1 2020/12/17 03:05:32 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -33,56 +33,28 @@ #ifndef _LINUX32_SCHED_H #define _LINUX32_SCHED_H -/* - * Flags passed to the Linux __clone(2) system call. - */ -#define LINUX32_CLONE_CSIGNAL 0x000000ff /* signal to be sent at exit */ -#define LINUX32_CLONE_VM 0x00000100 /* share address space */ -#define LINUX32_CLONE_FS 0x00000200 /* share "file system" info */ -#define LINUX32_CLONE_FILES 0x00000400 /* share file descriptors */ -#define LINUX32_CLONE_SIGHAND 0x00000800 /* share signal actions */ -#define LINUX32_CLONE_PID 0x00001000 /* share process ID */ -#define LINUX32_CLONE_PTRACE 0x00002000 /* ptrace(2) continues on - child */ -#define LINUX32_CLONE_VFORK 0x00004000 /* parent blocks until child - exits */ -#define LINUX32_CLONE_PARENT 0x00008000 /* want same parent as cloner */ -#define LINUX32_CLONE_THREAD 0x00010000 /* same thread group */ -#define LINUX32_CLONE_NEWNS 0x00020000 /* new namespace group */ -#define LINUX32_CLONE_SYSVSEM 0x00040000 /* share SysV SEM_UNDO */ -#define LINUX32_CLONE_SETTLS 0x00080000 /* create new TLS for child */ -#define LINUX32_CLONE_PARENT_SETTID \ - 0x00100000 /* set TID in the parent */ -#define LINUX32_CLONE_CHILD_CLEARTID \ - 0x00200000 /* clear TID in the child */ -#define LINUX32_CLONE_DETACHED 0x00400000 /* unused */ -#define LINUX32_CLONE_UNTRACED 0x00800000 /* set if parent cannot force CLONE_PTRACE */ -#define LINUX32_CLONE_CHILD_SETTID \ - 0x01000000 /* set TID in the child */ -#define LINUX32_CLONE_STOPPED 0x02000000 /* start in stopped state */ - struct linux32_sched_param { int sched_priority; }; -#define LINUX32_SCHED_OTHER 0 -#define LINUX32_SCHED_FIFO 1 -#define LINUX32_SCHED_RR 2 - struct linux32_timespec { linux32_time_t tv_sec; /* seconds */ int tv_nsec; /* nanoseconds */ }; -#define LINUX32_CLOCK_REALTIME 0 -#define LINUX32_CLOCK_MONOTONIC 1 -#define LINUX32_CLOCK_PROCESS_CPUTIME_ID 2 -#define LINUX32_CLOCK_THREAD_CPUTIME_ID 3 -#define LINUX32_CLOCK_REALTIME_HR 4 -#define LINUX32_CLOCK_MONOTONIC_HR 5 - -int linux32_to_native_clockid(clockid_t *, clockid_t); -void native_to_linux32_timespec(struct linux32_timespec *, struct timespec *); -void linux32_to_native_timespec(struct timespec *, struct linux32_timespec *); +struct linux32_itimerspec { + struct linux32_timespec it_interval; + struct linux32_timespec it_value; +}; + +void native_to_linux32_timespec(struct linux32_timespec *, + const struct timespec *); +void linux32_to_native_timespec(struct timespec *, + const struct linux32_timespec *); + +void native_to_linux32_itimerspec(struct linux32_itimerspec *, + const struct itimerspec *); +void linux32_to_native_itimerspec(struct itimerspec *, + const struct linux32_itimerspec *); #endif /* _LINUX32_SCHED_H */ Index: src/sys/compat/linux32/common/linux32_time.c diff -u src/sys/compat/linux32/common/linux32_time.c:1.37 src/sys/compat/linux32/common/linux32_time.c:1.37.50.1 --- src/sys/compat/linux32/common/linux32_time.c:1.37 Tue Oct 2 01:44:28 2012 +++ src/sys/compat/linux32/common/linux32_time.c Thu Dec 17 03:05:32 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_time.c,v 1.37 2012/10/02 01:44:28 christos Exp $ */ +/* $NetBSD: linux32_time.c,v 1.37.50.1 2020/12/17 03:05:32 thorpej Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.37 2012/10/02 01:44:28 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.37.50.1 2020/12/17 03:05:32 thorpej Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -45,6 +45,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_time #include <sys/fcntl.h> #include <sys/namei.h> #include <sys/select.h> +#include <sys/timerfd.h> #include <sys/proc.h> #include <sys/resourcevar.h> #include <sys/ucred.h> @@ -77,10 +78,9 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_time #include <compat/linux32/common/linux32_sched.h> #include <compat/linux32/linux32_syscallargs.h> -extern struct timezone linux_sys_tz; +CTASSERT(LINUX_TIMER_ABSTIME == TIMER_ABSTIME); -void native_to_linux32_timespec(struct linux32_timespec *, struct timespec *); -void linux32_to_native_timespec(struct timespec *, struct linux32_timespec *); +extern struct timezone linux_sys_tz; int linux32_sys_gettimeofday(struct lwp *l, const struct linux32_sys_gettimeofday_args *uap, register_t *retval) @@ -235,19 +235,37 @@ linux32_sys_utime(struct lwp *l, const s } void -native_to_linux32_timespec(struct linux32_timespec *ltp, struct timespec *ntp) +native_to_linux32_timespec(struct linux32_timespec *ltp, + const struct timespec *ntp) { ltp->tv_sec = ntp->tv_sec; ltp->tv_nsec = ntp->tv_nsec; } void -linux32_to_native_timespec(struct timespec *ntp, struct linux32_timespec *ltp) +linux32_to_native_timespec(struct timespec *ntp, + const struct linux32_timespec *ltp) { ntp->tv_sec = ltp->tv_sec; ntp->tv_nsec = ltp->tv_nsec; } +void +native_to_linux32_itimerspec(struct linux32_itimerspec *litp, + const struct itimerspec *nitp) +{ + native_to_linux32_timespec(&litp->it_interval, &nitp->it_interval); + native_to_linux32_timespec(&litp->it_value, &nitp->it_value); +} + +void +linux32_to_native_itimerspec(struct itimerspec *nitp, + const struct linux32_itimerspec *litp) +{ + linux32_to_native_timespec(&nitp->it_interval, &litp->it_interval); + linux32_to_native_timespec(&nitp->it_value, &litp->it_value); +} + int linux32_sys_nanosleep(struct lwp *l, const struct linux32_sys_nanosleep_args *uap, register_t *retval) @@ -384,3 +402,158 @@ linux32_sys_clock_nanosleep(struct lwp * error1 = copyout(&lrmts, SCARG_P32(uap, rmtp), sizeof lrmts); return error1 ? error1 : error; } + +int +linux32_sys_timer_create(struct lwp *l, + const struct linux32_sys_timer_create_args *uap, register_t *retval) +{ + /* { + syscallarg(clockid_t) clockid; + syscallarg(struct linux32_sigevent *) evp; + syscallarg(timer_t *) timerid; + } */ + clockid_t id; + int error; + + error = linux_to_native_timer_create_clockid(&id, SCARG(uap, clockid)); + if (error == 0) { + error = timer_create1(SCARG(uap, timerid), id, + (void *)SCARG(uap, evp), linux32_sigevent_copyin, l); + } + + return error; +} + +int +linux32_sys_timer_settime(struct lwp *l, + const struct linux32_sys_timer_settime_args *uap, register_t *retval) +{ + /* { + syscallarg(timer_t) timerid; + syscallarg(int) flags; + syscallarg(const struct linux32_itimerspec *) tim; + syscallarg(struct linux32_itimerspec *) otim; + } */ + struct itimerspec value, ovalue, *ovp = NULL; + struct linux32_itimerspec tim, otim; + int error; + + error = copyin(SCARG(uap, tim), &tim, sizeof(tim)); + if (error) { + return error; + } + linux32_to_native_itimerspec(&value, &tim); + + if (SCARG(uap, otim)) { + ovp = &ovalue; + } + + if (SCARG(uap, flags) & ~TIMER_ABSTIME) { + return EINVAL; + } + + error = dotimer_settime(SCARG(uap, timerid), &value, ovp, + SCARG(uap, flags), l->l_proc); + if (error) { + return error; + } + + if (ovp) { + native_to_linux32_itimerspec(&otim, ovp); + error = copyout(&otim, SCARG(uap, otim), sizeof(otim)); + } + + return error; +} + +int +linux32_sys_timer_gettime(struct lwp *l, + const struct linux32_sys_timer_gettime_args *uap, register_t *retval) +{ + /* { + syscallarg(timer_t) timerid; + syscallarg(struct linux32_itimerspec *) tim; + } */ + struct itimerspec its; + struct linux32_itimerspec lits; + int error; + + error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, &its); + if (error == 0) { + native_to_linux32_itimerspec(&lits, &its); + error = copyout(&lits, SCARG(uap, tim), sizeof(lits)); + } + + return error; +} + +/* + * timer_gettoverrun(2) and timer_delete(2) are handled directly + * by the native calls. + */ + +/* + * timerfd_create() is handled by the standard COMPAT_LINUX call. + */ + +int +linux32_sys_timerfd_gettime(struct lwp *l, + const struct linux32_sys_timerfd_gettime_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(struct linux32_itimerspec *) curr_value; + } */ + struct itimerspec its; + struct linux32_itimerspec lits; + int error; + + error = do_timerfd_gettime(l, SCARG(uap, fd), &its, retval); + if (error == 0) { + native_to_linux32_itimerspec(&lits, &its); + error = copyout(&lits, SCARG(uap, curr_value), sizeof(lits)); + } + + return error; +} + +int +linux32_sys_timerfd_settime(struct lwp *l, + const struct linux32_sys_timerfd_settime_args *uap, register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(int) flags; + syscallarg(const struct linux32_itimerspec *) new_value; + syscallarg(struct linux32_itimerspec *) old_value; + } */ + struct itimerspec nits, oits, *oitsp = NULL; + struct linux32_itimerspec lits; + int nflags; + int error; + + error = copyin(SCARG(uap, new_value), &lits, sizeof(lits)); + if (error) { + return error; + } + linux32_to_native_itimerspec(&nits, &lits); + + error = linux_to_native_timerfd_settime_flags(&nflags, + SCARG(uap, flags)); + if (error) { + return error; + } + + if (SCARG(uap, old_value)) { + oitsp = &oits; + } + + error = do_timerfd_settime(l, SCARG(uap, fd), nflags, + &nits, oitsp, retval); + if (error == 0 && oitsp != NULL) { + native_to_linux32_itimerspec(&lits, oitsp); + error = copyout(&lits, SCARG(uap, old_value), sizeof(lits)); + } + + return error; +}