mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
linux(4): Implement timerfd_settime64 syscall.
MFC after: 2weeks
This commit is contained in:
parent
f4228fbb4e
commit
b1f0b08d93
@ -69,7 +69,6 @@ DUMMY(arch_prctl);
|
||||
/* Linux 5.0: */
|
||||
DUMMY(clock_adjtime64);
|
||||
DUMMY(timerfd_gettime64);
|
||||
DUMMY(timerfd_settime64);
|
||||
DUMMY(io_pgetevents_time64);
|
||||
DUMMY(recvmmsg_time64);
|
||||
DUMMY(mq_timedsend_time64);
|
||||
|
@ -932,28 +932,20 @@ linux_timerfd_gettime(struct thread *td, struct linux_timerfd_gettime_args *args
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args)
|
||||
static int
|
||||
linux_timerfd_settime_common(struct thread *td, int fd, int flags,
|
||||
struct itimerspec *nts, struct itimerspec *oval)
|
||||
{
|
||||
struct l_itimerspec lots;
|
||||
struct itimerspec nts, ots;
|
||||
struct timespec cts, ts;
|
||||
struct timerfd *tfd;
|
||||
struct timeval tv;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
if ((args->flags & ~LINUX_TFD_SETTIME_FLAGS) != 0)
|
||||
if ((flags & ~LINUX_TFD_SETTIME_FLAGS) != 0)
|
||||
return (EINVAL);
|
||||
|
||||
error = copyin(args->new_value, &lots, sizeof(lots));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_itimerspec(&nts, &lots);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = fget(td, args->fd, &cap_write_rights, &fp);
|
||||
error = fget(td, fd, &cap_write_rights, &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
tfd = fp->f_data;
|
||||
@ -963,17 +955,17 @@ linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args
|
||||
}
|
||||
|
||||
mtx_lock(&tfd->tfd_lock);
|
||||
if (!timespecisset(&nts.it_value))
|
||||
timespecclear(&nts.it_interval);
|
||||
if (args->old_value != NULL)
|
||||
linux_timerfd_curval(tfd, &ots);
|
||||
if (!timespecisset(&nts->it_value))
|
||||
timespecclear(&nts->it_interval);
|
||||
if (oval != NULL)
|
||||
linux_timerfd_curval(tfd, oval);
|
||||
|
||||
tfd->tfd_time = nts;
|
||||
bcopy(nts, &tfd->tfd_time, sizeof(*nts));
|
||||
tfd->tfd_count = 0;
|
||||
if (timespecisset(&nts.it_value)) {
|
||||
if (timespecisset(&nts->it_value)) {
|
||||
linux_timerfd_clocktime(tfd, &cts);
|
||||
ts = nts.it_value;
|
||||
if ((args->flags & LINUX_TFD_TIMER_ABSTIME) == 0) {
|
||||
ts = nts->it_value;
|
||||
if ((flags & LINUX_TFD_TIMER_ABSTIME) == 0) {
|
||||
timespecadd(&tfd->tfd_time.it_value, &cts,
|
||||
&tfd->tfd_time.it_value);
|
||||
} else {
|
||||
@ -989,17 +981,61 @@ linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args
|
||||
}
|
||||
mtx_unlock(&tfd->tfd_lock);
|
||||
|
||||
if (args->old_value != NULL) {
|
||||
error = native_to_linux_itimerspec(&lots, &ots);
|
||||
if (error == 0)
|
||||
error = copyout(&lots, args->old_value, sizeof(lots));
|
||||
}
|
||||
|
||||
out:
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args)
|
||||
{
|
||||
struct l_itimerspec lots;
|
||||
struct itimerspec nts, ots, *pots;
|
||||
int error;
|
||||
|
||||
error = copyin(args->new_value, &lots, sizeof(lots));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_itimerspec(&nts, &lots);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
pots = (args->old_value != NULL ? &ots : NULL);
|
||||
error = linux_timerfd_settime_common(td, args->fd, args->flags,
|
||||
&nts, pots);
|
||||
if (error == 0 && args->old_value != NULL) {
|
||||
error = native_to_linux_itimerspec(&lots, &ots);
|
||||
if (error == 0)
|
||||
error = copyout(&lots, args->old_value, sizeof(lots));
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
|
||||
int
|
||||
linux_timerfd_settime64(struct thread *td, struct linux_timerfd_settime64_args *args)
|
||||
{
|
||||
struct l_itimerspec64 lots;
|
||||
struct itimerspec nts, ots, *pots;
|
||||
int error;
|
||||
|
||||
error = copyin(args->new_value, &lots, sizeof(lots));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_itimerspec64(&nts, &lots);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
pots = (args->old_value != NULL ? &ots : NULL);
|
||||
error = linux_timerfd_settime_common(td, args->fd, args->flags,
|
||||
&nts, pots);
|
||||
if (error == 0 && args->old_value != NULL) {
|
||||
error = native_to_linux_itimerspec64(&lots, &ots);
|
||||
if (error == 0)
|
||||
error = copyout(&lots, args->old_value, sizeof(lots));
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
linux_timerfd_expire(void *arg)
|
||||
{
|
||||
|
@ -71,7 +71,6 @@ DUMMY(arch_prctl);
|
||||
/* Linux 5.0: */
|
||||
DUMMY(clock_adjtime64);
|
||||
DUMMY(timerfd_gettime64);
|
||||
DUMMY(timerfd_settime64);
|
||||
DUMMY(io_pgetevents_time64);
|
||||
DUMMY(recvmmsg_time64);
|
||||
DUMMY(mq_timedsend_time64);
|
||||
|
Loading…
Reference in New Issue
Block a user