summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux
diff options
context:
space:
mode:
authordchagin <dchagin@FreeBSD.org>2017-05-01 06:42:39 +0000
committerdchagin <dchagin@FreeBSD.org>2017-05-01 06:42:39 +0000
commitb13bdd10aae1b3772574414ad11309354d8bba6f (patch)
treec31df49cc76014457a6b472296269932694fd113 /sys/compat/linux
parentebdc0abc89aed8dee01bd57e38e078ae868d5f33 (diff)
downloadFreeBSD-src-b13bdd10aae1b3772574414ad11309354d8bba6f.zip
FreeBSD-src-b13bdd10aae1b3772574414ad11309354d8bba6f.tar.gz
MFC r316426:
Use the kern_clock_nanosleep() to implement Linux clock_nanosleep() with the proper handling of the TIMER_ABSTIME flag.
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_time.c36
-rw-r--r--sys/compat/linux/linux_timer.h2
2 files changed, 27 insertions, 11 deletions
diff --git a/sys/compat/linux/linux_time.c b/sys/compat/linux/linux_time.c
index 84c62dc..be059a6 100644
--- a/sys/compat/linux/linux_time.c
+++ b/sys/compat/linux/linux_time.c
@@ -231,6 +231,18 @@ linux_to_native_clockid(clockid_t *n, clockid_t l)
}
int
+linux_to_native_timerflags(int *nflags, int flags)
+{
+
+ if (flags & ~LINUX_TIMER_ABSTIME)
+ return (EINVAL);
+ *nflags = 0;
+ if (flags & LINUX_TIMER_ABSTIME)
+ *nflags |= TIMER_ABSTIME;
+ return (0);
+}
+
+int
linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
{
struct l_timespec lts;
@@ -543,24 +555,26 @@ linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args
struct timespec *rmtp;
struct l_timespec lrqts, lrmts;
struct timespec rqts, rmts;
- int error, error2;
+ int error, error2, flags;
+ clockid_t clockid;
LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
args->flags, args->rqtp, args->rmtp);
- if (args->flags != 0) {
- /* XXX deal with TIMER_ABSTIME */
+ error = linux_to_native_timerflags(&flags, args->flags);
+ if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
args->flags);
- LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
- return (EINVAL); /* XXX deal with TIMER_ABSTIME */
+ LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
+ return (error);
}
- if (args->which != LINUX_CLOCK_REALTIME) {
+ error = linux_to_native_clockid(&clockid, args->which);
+ if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
args->which);
- LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
- return (EINVAL);
+ LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
+ return (error);
}
error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
@@ -583,9 +597,9 @@ linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args
LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
return (error);
}
- error = kern_nanosleep(td, &rqts, rmtp);
- if (error == EINTR && args->rmtp != NULL) {
- /* XXX. Not for TIMER_ABSTIME */
+ error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp);
+ if (error == EINTR && (flags & TIMER_ABSTIME) == 0 &&
+ args->rmtp != NULL) {
error2 = native_to_linux_timespec(&lrmts, rmtp);
if (error2 != 0)
return (error2);
diff --git a/sys/compat/linux/linux_timer.h b/sys/compat/linux/linux_timer.h
index 4092dc6..f06c216 100644
--- a/sys/compat/linux/linux_timer.h
+++ b/sys/compat/linux/linux_timer.h
@@ -72,6 +72,7 @@
#define LINUX_CPUCLOCK_PERTHREAD(clock) \
(((clock) & (clockid_t) LINUX_CPUCLOCK_PERTHREAD_MASK) != 0)
+#define LINUX_TIMER_ABSTIME 0x01
#define L_SIGEV_SIGNAL 0
#define L_SIGEV_NONE 1
@@ -120,5 +121,6 @@ int native_to_linux_itimerspec(struct l_itimerspec *,
struct itimerspec *);
int linux_to_native_itimerspec(struct itimerspec *,
struct l_itimerspec *);
+int linux_to_native_timerflags(int *, int);
#endif /* _LINUX_TIMER_H */
OpenPOWER on IntegriCloud