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;
+}

Reply via email to