linux(4): Implement futex_time64 system call.
MFC after: 2 weeks
This commit is contained in:
parent
25b09d6f39
commit
2e46d0c3d9
@ -80,5 +80,4 @@ DUMMY(mq_timedsend_time64);
|
||||
DUMMY(mq_timedreceive_time64);
|
||||
DUMMY(semtimedop_time64);
|
||||
DUMMY(rt_sigtimedwait_time64);
|
||||
DUMMY(futex_time64);
|
||||
DUMMY(sched_rr_get_interval_time64);
|
||||
|
@ -2415,7 +2415,14 @@
|
||||
int linux_rt_sigtimedwait_time64(void);
|
||||
}
|
||||
422 AUE_NULL STD {
|
||||
int linux_futex_time64(void);
|
||||
int linux_sys_futex_time64(
|
||||
uint32_t *uaddr,
|
||||
l_int op,
|
||||
uint32_t val,
|
||||
struct l_timespec64 *timeout,
|
||||
uint32_t *uaddr2,
|
||||
uint32_t val3
|
||||
);
|
||||
}
|
||||
423 AUE_NULL STD {
|
||||
int linux_sched_rr_get_interval_time64(void);
|
||||
|
@ -117,29 +117,29 @@ LIN_SDT_PROBE_DEFINE4(futex, futex_atomic_op, decoded_op, "int", "int", "int",
|
||||
LIN_SDT_PROBE_DEFINE0(futex, futex_atomic_op, missing_access_check);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_op, "int");
|
||||
LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_cmp, "int");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_clockswitch);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, copyin_error, "int");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, invalid_cmp_requeue_use);
|
||||
LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wait, "uint32_t *",
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_clockswitch);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, linux_futex, copyin_error, "int");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, invalid_cmp_requeue_use);
|
||||
LIN_SDT_PROBE_DEFINE3(futex, linux_futex, debug_wait, "uint32_t *",
|
||||
"uint32_t", "uint32_t");
|
||||
LIN_SDT_PROBE_DEFINE4(futex, linux_sys_futex, debug_wait_value_neq,
|
||||
LIN_SDT_PROBE_DEFINE4(futex, linux_futex, debug_wait_value_neq,
|
||||
"uint32_t *", "uint32_t", "int", "uint32_t");
|
||||
LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wake, "uint32_t *",
|
||||
LIN_SDT_PROBE_DEFINE3(futex, linux_futex, debug_wake, "uint32_t *",
|
||||
"uint32_t", "uint32_t");
|
||||
LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_cmp_requeue, "uint32_t *",
|
||||
LIN_SDT_PROBE_DEFINE5(futex, linux_futex, debug_cmp_requeue, "uint32_t *",
|
||||
"uint32_t", "uint32_t", "uint32_t *", "struct l_timespec *");
|
||||
LIN_SDT_PROBE_DEFINE2(futex, linux_sys_futex, debug_cmp_requeue_value_neq,
|
||||
LIN_SDT_PROBE_DEFINE2(futex, linux_futex, debug_cmp_requeue_value_neq,
|
||||
"uint32_t", "int");
|
||||
LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_wake_op, "uint32_t *",
|
||||
LIN_SDT_PROBE_DEFINE5(futex, linux_futex, debug_wake_op, "uint32_t *",
|
||||
"int", "uint32_t", "uint32_t *", "uint32_t");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unhandled_efault);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_lock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_unlock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_trylock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, deprecated_requeue);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_wait_requeue_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_cmp_requeue_pi);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, unknown_operation, "int");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unhandled_efault);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_lock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_unlock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_trylock_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, deprecated_requeue);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_wait_requeue_pi);
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_futex, unimplemented_cmp_requeue_pi);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, linux_futex, unknown_operation, "int");
|
||||
LIN_SDT_PROBE_DEFINE0(futex, linux_set_robust_list, size_error);
|
||||
LIN_SDT_PROBE_DEFINE1(futex, linux_get_robust_list, copyout_error, "int");
|
||||
LIN_SDT_PROBE_DEFINE1(futex, handle_futex_death, copyin_error, "int");
|
||||
@ -215,8 +215,6 @@ static int futex_get(uint32_t *, struct waiting_proc **, struct futex **,
|
||||
static int futex_sleep(struct futex *, struct waiting_proc *, struct timespec *);
|
||||
static int futex_wake(struct futex *, int, uint32_t);
|
||||
static int futex_requeue(struct futex *, int, struct futex *, int);
|
||||
static int futex_copyin_timeout(int, struct l_timespec *, int,
|
||||
struct timespec *);
|
||||
static int futex_wait(struct futex *, struct waiting_proc *, struct timespec *,
|
||||
uint32_t);
|
||||
static void futex_lock(struct futex *);
|
||||
@ -227,30 +225,17 @@ static int handle_futex_death(struct linux_emuldata *, uint32_t *,
|
||||
static int fetch_robust_entry(struct linux_robust_list **,
|
||||
struct linux_robust_list **, unsigned int *);
|
||||
|
||||
static int
|
||||
futex_copyin_timeout(int op, struct l_timespec *luts, int clockrt,
|
||||
struct timespec *ts)
|
||||
{
|
||||
struct l_timespec lts;
|
||||
struct timespec kts;
|
||||
int error;
|
||||
struct linux_futex_args {
|
||||
uint32_t *uaddr;
|
||||
int32_t op;
|
||||
uint32_t val;
|
||||
struct timespec *ts;
|
||||
uint32_t *uaddr2;
|
||||
uint32_t val3;
|
||||
struct timespec kts;
|
||||
};
|
||||
|
||||
error = copyin(luts, <s, sizeof(lts));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
error = linux_to_native_timespec(ts, <s);
|
||||
if (error)
|
||||
return (error);
|
||||
if (clockrt) {
|
||||
nanotime(&kts);
|
||||
timespecsub(ts, &kts, ts);
|
||||
} else if (op == LINUX_FUTEX_WAIT_BITSET) {
|
||||
nanouptime(&kts);
|
||||
timespecsub(ts, &kts, ts);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
static int linux_futex(struct thread *, struct linux_futex_args *);
|
||||
|
||||
static void
|
||||
futex_put(struct futex *f, struct waiting_proc *wp)
|
||||
@ -430,19 +415,17 @@ futex_unlock(struct futex *f)
|
||||
static int
|
||||
futex_sleep(struct futex *f, struct waiting_proc *wp, struct timespec *ts)
|
||||
{
|
||||
struct timespec uts;
|
||||
sbintime_t sbt, prec, tmp;
|
||||
time_t over;
|
||||
int error;
|
||||
|
||||
FUTEX_ASSERT_LOCKED(f);
|
||||
if (ts != NULL) {
|
||||
uts = *ts;
|
||||
if (uts.tv_sec > INT32_MAX / 2) {
|
||||
over = uts.tv_sec - INT32_MAX / 2;
|
||||
uts.tv_sec -= over;
|
||||
if (ts->tv_sec > INT32_MAX / 2) {
|
||||
over = ts->tv_sec - INT32_MAX / 2;
|
||||
ts->tv_sec -= over;
|
||||
}
|
||||
tmp = tstosbt(uts);
|
||||
tmp = tstosbt(*ts);
|
||||
if (TIMESEL(&sbt, tmp))
|
||||
sbt += tc_tick_sbt;
|
||||
sbt += tmp;
|
||||
@ -655,14 +638,14 @@ futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
static int
|
||||
linux_futex(struct thread *td, struct linux_futex_args *args)
|
||||
{
|
||||
int clockrt, nrwake, nrrequeue, op_ret, ret;
|
||||
struct linux_pemuldata *pem;
|
||||
struct waiting_proc *wp;
|
||||
struct futex *f, *f2;
|
||||
struct timespec uts, *ts;
|
||||
struct timespec kts;
|
||||
int error, save;
|
||||
uint32_t flags, val;
|
||||
|
||||
@ -682,7 +665,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
args->op = args->op & ~LINUX_FUTEX_CLOCK_REALTIME;
|
||||
if (clockrt && args->op != LINUX_FUTEX_WAIT_BITSET &&
|
||||
args->op != LINUX_FUTEX_WAIT_REQUEUE_PI) {
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_clockswitch);
|
||||
return (ENOSYS);
|
||||
}
|
||||
@ -696,22 +679,20 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case LINUX_FUTEX_WAIT_BITSET:
|
||||
LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wait, args->uaddr,
|
||||
LIN_SDT_PROBE3(futex, linux_futex, debug_wait, args->uaddr,
|
||||
args->val, args->val3);
|
||||
LINUX_CTR3(sys_futex, "WAIT uaddr %p val 0x%x bitset 0x%x",
|
||||
args->uaddr, args->val, args->val3);
|
||||
|
||||
if (args->timeout != NULL) {
|
||||
error = futex_copyin_timeout(args->op, args->timeout,
|
||||
clockrt, &uts);
|
||||
if (error) {
|
||||
LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error,
|
||||
error);
|
||||
return (error);
|
||||
if (args->ts != NULL) {
|
||||
if (clockrt) {
|
||||
nanotime(&kts);
|
||||
timespecsub(args->ts, &kts, args->ts);
|
||||
} else if (args->op == LINUX_FUTEX_WAIT_BITSET) {
|
||||
nanouptime(&kts);
|
||||
timespecsub(args->ts, &kts, args->ts);
|
||||
}
|
||||
ts = &uts;
|
||||
} else
|
||||
ts = NULL;
|
||||
}
|
||||
|
||||
retry0:
|
||||
error = futex_get(args->uaddr, &wp, &f,
|
||||
@ -725,14 +706,14 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
error = copyin(args->uaddr, &val, sizeof(val));
|
||||
if (error == 0)
|
||||
goto retry0;
|
||||
LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error,
|
||||
LIN_SDT_PROBE1(futex, linux_futex, copyin_error,
|
||||
error);
|
||||
LINUX_CTR1(sys_futex, "WAIT copyin failed %d",
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
if (val != args->val) {
|
||||
LIN_SDT_PROBE4(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE4(futex, linux_futex,
|
||||
debug_wait_value_neq, args->uaddr, args->val, val,
|
||||
args->val3);
|
||||
LINUX_CTR3(sys_futex,
|
||||
@ -742,7 +723,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
return (EWOULDBLOCK);
|
||||
}
|
||||
|
||||
error = futex_wait(f, wp, ts, args->val3);
|
||||
error = futex_wait(f, wp, args->ts, args->val3);
|
||||
break;
|
||||
|
||||
case LINUX_FUTEX_WAKE:
|
||||
@ -750,7 +731,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case LINUX_FUTEX_WAKE_BITSET:
|
||||
LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wake, args->uaddr,
|
||||
LIN_SDT_PROBE3(futex, linux_futex, debug_wake, args->uaddr,
|
||||
args->val, args->val3);
|
||||
LINUX_CTR3(sys_futex, "WAKE uaddr %p nrwake 0x%x bitset 0x%x",
|
||||
args->uaddr, args->val, args->val3);
|
||||
@ -769,25 +750,25 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
break;
|
||||
|
||||
case LINUX_FUTEX_CMP_REQUEUE:
|
||||
LIN_SDT_PROBE5(futex, linux_sys_futex, debug_cmp_requeue,
|
||||
LIN_SDT_PROBE5(futex, linux_futex, debug_cmp_requeue,
|
||||
args->uaddr, args->val, args->val3, args->uaddr2,
|
||||
args->timeout);
|
||||
args->ts);
|
||||
LINUX_CTR5(sys_futex, "CMP_REQUEUE uaddr %p "
|
||||
"nrwake 0x%x uval 0x%x uaddr2 %p nrequeue 0x%x",
|
||||
args->uaddr, args->val, args->val3, args->uaddr2,
|
||||
args->timeout);
|
||||
args->ts);
|
||||
|
||||
/*
|
||||
* Linux allows this, we would not, it is an incorrect
|
||||
* usage of declared ABI, so return EINVAL.
|
||||
*/
|
||||
if (args->uaddr == args->uaddr2) {
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
invalid_cmp_requeue_use);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
nrrequeue = (int)(unsigned long)args->timeout;
|
||||
nrrequeue = (int)(unsigned long)args->ts;
|
||||
nrwake = args->val;
|
||||
/*
|
||||
* Sanity check to prevent signed integer overflow,
|
||||
@ -823,14 +804,14 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
error = copyin(args->uaddr, &val, sizeof(val));
|
||||
if (error == 0)
|
||||
goto retry1;
|
||||
LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error,
|
||||
LIN_SDT_PROBE1(futex, linux_futex, copyin_error,
|
||||
error);
|
||||
LINUX_CTR1(sys_futex, "CMP_REQUEUE copyin failed %d",
|
||||
error);
|
||||
return (error);
|
||||
}
|
||||
if (val != args->val3) {
|
||||
LIN_SDT_PROBE2(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE2(futex, linux_futex,
|
||||
debug_cmp_requeue_value_neq, args->val, val);
|
||||
LINUX_CTR2(sys_futex, "CMP_REQUEUE val 0x%x != uval 0x%x",
|
||||
args->val, val);
|
||||
@ -845,12 +826,12 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
break;
|
||||
|
||||
case LINUX_FUTEX_WAKE_OP:
|
||||
LIN_SDT_PROBE5(futex, linux_sys_futex, debug_wake_op,
|
||||
LIN_SDT_PROBE5(futex, linux_futex, debug_wake_op,
|
||||
args->uaddr, args->op, args->val, args->uaddr2, args->val3);
|
||||
LINUX_CTR5(sys_futex, "WAKE_OP "
|
||||
"uaddr %p nrwake 0x%x uaddr2 %p op 0x%x nrwake2 0x%x",
|
||||
args->uaddr, args->val, args->uaddr2, args->val3,
|
||||
args->timeout);
|
||||
args->ts);
|
||||
|
||||
if (args->uaddr == args->uaddr2)
|
||||
return (EINVAL);
|
||||
@ -893,7 +874,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
|
||||
if (op_ret > 0) {
|
||||
op_ret = 0;
|
||||
nrwake = (int)(unsigned long)args->timeout;
|
||||
nrwake = (int)(unsigned long)args->ts;
|
||||
|
||||
if (f2 != NULL)
|
||||
op_ret += futex_wake(f2, nrwake, args->val3);
|
||||
@ -913,7 +894,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XUNSUP_FUTEXPIOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_LOCK_PI");
|
||||
pem->flags |= LINUX_XUNSUP_FUTEXPIOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_lock_pi);
|
||||
}
|
||||
return (ENOSYS);
|
||||
@ -924,7 +905,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XUNSUP_FUTEXPIOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_UNLOCK_PI");
|
||||
pem->flags |= LINUX_XUNSUP_FUTEXPIOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_unlock_pi);
|
||||
}
|
||||
return (ENOSYS);
|
||||
@ -935,7 +916,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XUNSUP_FUTEXPIOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_TRYLOCK_PI");
|
||||
pem->flags |= LINUX_XUNSUP_FUTEXPIOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_trylock_pi);
|
||||
}
|
||||
return (ENOSYS);
|
||||
@ -951,7 +932,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XDEPR_REQUEUEOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_REQUEUE");
|
||||
pem->flags |= LINUX_XDEPR_REQUEUEOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
deprecated_requeue);
|
||||
}
|
||||
return (EINVAL);
|
||||
@ -962,7 +943,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XUNSUP_FUTEXPIOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_WAIT_REQUEUE_PI");
|
||||
pem->flags |= LINUX_XUNSUP_FUTEXPIOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_wait_requeue_pi);
|
||||
}
|
||||
return (ENOSYS);
|
||||
@ -973,14 +954,14 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
if ((pem->flags & LINUX_XUNSUP_FUTEXPIOP) == 0) {
|
||||
linux_msg(td, "unsupported FUTEX_CMP_REQUEUE_PI");
|
||||
pem->flags |= LINUX_XUNSUP_FUTEXPIOP;
|
||||
LIN_SDT_PROBE0(futex, linux_sys_futex,
|
||||
LIN_SDT_PROBE0(futex, linux_futex,
|
||||
unimplemented_cmp_requeue_pi);
|
||||
}
|
||||
return (ENOSYS);
|
||||
|
||||
default:
|
||||
linux_msg(td, "unsupported futex op %d", args->op);
|
||||
LIN_SDT_PROBE1(futex, linux_sys_futex, unknown_operation,
|
||||
LIN_SDT_PROBE1(futex, linux_futex, unknown_operation,
|
||||
args->op);
|
||||
return (ENOSYS);
|
||||
}
|
||||
@ -988,6 +969,75 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
|
||||
{
|
||||
struct linux_futex_args fargs = {
|
||||
.uaddr = args->uaddr,
|
||||
.op = args->op,
|
||||
.val = args->val,
|
||||
.ts = NULL,
|
||||
.uaddr2 = args->uaddr2,
|
||||
.val3 = args->val3,
|
||||
};
|
||||
struct l_timespec lts;
|
||||
int error;
|
||||
|
||||
switch (args->op & LINUX_FUTEX_CMD_MASK) {
|
||||
case LINUX_FUTEX_WAIT:
|
||||
case LINUX_FUTEX_WAIT_BITSET:
|
||||
if (args->timeout != NULL) {
|
||||
error = copyin(args->timeout, <s, sizeof(lts));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_timespec(&fargs.kts, <s);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
fargs.ts = &fargs.kts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fargs.ts = PTRIN(args->timeout);
|
||||
}
|
||||
return (linux_futex(td, &fargs));
|
||||
}
|
||||
|
||||
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
|
||||
int
|
||||
linux_sys_futex_time64(struct thread *td,
|
||||
struct linux_sys_futex_time64_args *args)
|
||||
{
|
||||
struct linux_futex_args fargs = {
|
||||
.uaddr = args->uaddr,
|
||||
.op = args->op,
|
||||
.val = args->val,
|
||||
.ts = NULL,
|
||||
.uaddr2 = args->uaddr2,
|
||||
.val3 = args->val3,
|
||||
};
|
||||
struct l_timespec64 lts;
|
||||
int error;
|
||||
|
||||
switch (args->op & LINUX_FUTEX_CMD_MASK) {
|
||||
case LINUX_FUTEX_WAIT:
|
||||
case LINUX_FUTEX_WAIT_BITSET:
|
||||
if (args->timeout != NULL) {
|
||||
error = copyin(args->timeout, <s, sizeof(lts));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = linux_to_native_timespec64(&fargs.kts, <s);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
fargs.ts = &fargs.kts;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fargs.ts = PTRIN(args->timeout);
|
||||
}
|
||||
return (linux_futex(td, &fargs));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
linux_set_robust_list(struct thread *td, struct linux_set_robust_list_args *args)
|
||||
{
|
||||
|
@ -55,6 +55,9 @@
|
||||
#define LINUX_FUTEX_PRIVATE_FLAG 128
|
||||
#define LINUX_FUTEX_CLOCK_REALTIME 256
|
||||
|
||||
#define LINUX_FUTEX_CMD_MASK ~(LINUX_FUTEX_PRIVATE_FLAG | \
|
||||
LINUX_FUTEX_CLOCK_REALTIME)
|
||||
|
||||
#define FUTEX_OP_SET 0 /* *(int *)UADDR2 = OPARG; */
|
||||
#define FUTEX_OP_ADD 1 /* *(int *)UADDR2 += OPARG; */
|
||||
#define FUTEX_OP_OR 2 /* *(int *)UADDR2 |= OPARG; */
|
||||
|
@ -82,5 +82,4 @@ DUMMY(mq_timedsend_time64);
|
||||
DUMMY(mq_timedreceive_time64);
|
||||
DUMMY(semtimedop_time64);
|
||||
DUMMY(rt_sigtimedwait_time64);
|
||||
DUMMY(futex_time64);
|
||||
DUMMY(sched_rr_get_interval_time64);
|
||||
|
@ -2433,7 +2433,14 @@
|
||||
int linux_rt_sigtimedwait_time64(void);
|
||||
}
|
||||
422 AUE_NULL STD {
|
||||
int linux_futex_time64(void);
|
||||
int linux_sys_futex_time64(
|
||||
uint32_t *uaddr,
|
||||
l_int op,
|
||||
uint32_t val,
|
||||
struct l_timespec64 *timeout,
|
||||
uint32_t *uaddr2,
|
||||
uint32_t val3
|
||||
);
|
||||
}
|
||||
423 AUE_NULL STD {
|
||||
int linux_sched_rr_get_interval_time64(void);
|
||||
|
Loading…
Reference in New Issue
Block a user