Introduce command UMTX_OP_WAIT_UINT_PRIVATE and UMTX_OP_WAKE_PRIVATE
to allow userland to specify that an address is not shared by multiple processes.
This commit is contained in:
parent
e3085308be
commit
727158f6f6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=178646
@ -948,7 +948,7 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
do_wait(struct thread *td, void *addr, u_long id,
|
do_wait(struct thread *td, void *addr, u_long id,
|
||||||
struct timespec *timeout, int compat32)
|
struct timespec *timeout, int compat32, int is_private)
|
||||||
{
|
{
|
||||||
struct umtx_q *uq;
|
struct umtx_q *uq;
|
||||||
struct timespec ts, ts2, ts3;
|
struct timespec ts, ts2, ts3;
|
||||||
@ -957,8 +957,8 @@ do_wait(struct thread *td, void *addr, u_long id,
|
|||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
uq = td->td_umtxq;
|
uq = td->td_umtxq;
|
||||||
if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT, AUTO_SHARE,
|
if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT,
|
||||||
&uq->uq_key)) != 0)
|
is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
umtxq_lock(&uq->uq_key);
|
umtxq_lock(&uq->uq_key);
|
||||||
@ -1013,13 +1013,13 @@ do_wait(struct thread *td, void *addr, u_long id,
|
|||||||
* Wake up threads sleeping on the specified address.
|
* Wake up threads sleeping on the specified address.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
kern_umtx_wake(struct thread *td, void *uaddr, int n_wake)
|
kern_umtx_wake(struct thread *td, void *uaddr, int n_wake, int is_private)
|
||||||
{
|
{
|
||||||
struct umtx_key key;
|
struct umtx_key key;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((ret = umtx_key_get(uaddr, TYPE_SIMPLE_WAIT, AUTO_SHARE,
|
if ((ret = umtx_key_get(uaddr, TYPE_SIMPLE_WAIT,
|
||||||
&key)) != 0)
|
is_private ? THREAD_SHARE : AUTO_SHARE, &key)) != 0)
|
||||||
return (ret);
|
return (ret);
|
||||||
umtxq_lock(&key);
|
umtxq_lock(&key);
|
||||||
ret = umtxq_signal(&key, n_wake);
|
ret = umtxq_signal(&key, n_wake);
|
||||||
@ -2745,7 +2745,7 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 0);
|
return do_wait(td, uap->obj, uap->val, ts, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2765,13 +2765,39 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1);
|
return do_wait(td, uap->obj, uap->val, ts, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
__umtx_op_wait_uint_private(struct thread *td, struct _umtx_op_args *uap)
|
||||||
|
{
|
||||||
|
struct timespec *ts, timeout;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (uap->uaddr2 == NULL)
|
||||||
|
ts = NULL;
|
||||||
|
else {
|
||||||
|
error = copyin(uap->uaddr2, &timeout, sizeof(timeout));
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
if (timeout.tv_nsec >= 1000000000 ||
|
||||||
|
timeout.tv_nsec < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
ts = &timeout;
|
||||||
|
}
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
__umtx_op_wake(struct thread *td, struct _umtx_op_args *uap)
|
__umtx_op_wake(struct thread *td, struct _umtx_op_args *uap)
|
||||||
{
|
{
|
||||||
return (kern_umtx_wake(td, uap->obj, uap->val));
|
return (kern_umtx_wake(td, uap->obj, uap->val, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
__umtx_op_wake_private(struct thread *td, struct _umtx_op_args *uap)
|
||||||
|
{
|
||||||
|
return (kern_umtx_wake(td, uap->obj, uap->val, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2920,7 +2946,9 @@ static _umtx_op_func op_table[] = {
|
|||||||
__umtx_op_wait_uint, /* UMTX_OP_WAIT_UINT */
|
__umtx_op_wait_uint, /* UMTX_OP_WAIT_UINT */
|
||||||
__umtx_op_rw_rdlock, /* UMTX_OP_RW_RDLOCK */
|
__umtx_op_rw_rdlock, /* UMTX_OP_RW_RDLOCK */
|
||||||
__umtx_op_rw_wrlock, /* UMTX_OP_RW_WRLOCK */
|
__umtx_op_rw_wrlock, /* UMTX_OP_RW_WRLOCK */
|
||||||
__umtx_op_rw_unlock /* UMTX_OP_RW_UNLOCK */
|
__umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
|
||||||
|
__umtx_op_wait_uint_private, /* UMTX_OP_WAIT_UINT_PRIVATE */
|
||||||
|
__umtx_op_wake_private /* UMTX_OP_WAKE_PRIVATE */
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -3010,7 +3038,7 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return do_wait(td, uap->obj, uap->val, ts, 1);
|
return do_wait(td, uap->obj, uap->val, ts, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -3101,6 +3129,26 @@ __umtx_op_rw_wrlock_compat32(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
__umtx_op_wait_uint_private_compat32(struct thread *td, struct _umtx_op_args *uap)
|
||||||
|
{
|
||||||
|
struct timespec *ts, timeout;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
if (uap->uaddr2 == NULL)
|
||||||
|
ts = NULL;
|
||||||
|
else {
|
||||||
|
error = copyin_timeout32(uap->uaddr2, &timeout);
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
if (timeout.tv_nsec >= 1000000000 ||
|
||||||
|
timeout.tv_nsec < 0)
|
||||||
|
return (EINVAL);
|
||||||
|
ts = &timeout;
|
||||||
|
}
|
||||||
|
return do_wait(td, uap->obj, uap->val, ts, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static _umtx_op_func op_table_compat32[] = {
|
static _umtx_op_func op_table_compat32[] = {
|
||||||
__umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */
|
__umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */
|
||||||
__umtx_op_unlock_umtx_compat32, /* UMTX_OP_UNLOCK */
|
__umtx_op_unlock_umtx_compat32, /* UMTX_OP_UNLOCK */
|
||||||
@ -3116,7 +3164,9 @@ static _umtx_op_func op_table_compat32[] = {
|
|||||||
__umtx_op_wait_compat32, /* UMTX_OP_WAIT_UINT */
|
__umtx_op_wait_compat32, /* UMTX_OP_WAIT_UINT */
|
||||||
__umtx_op_rw_rdlock_compat32, /* UMTX_OP_RW_RDLOCK */
|
__umtx_op_rw_rdlock_compat32, /* UMTX_OP_RW_RDLOCK */
|
||||||
__umtx_op_rw_wrlock_compat32, /* UMTX_OP_RW_WRLOCK */
|
__umtx_op_rw_wrlock_compat32, /* UMTX_OP_RW_WRLOCK */
|
||||||
__umtx_op_rw_unlock /* UMTX_OP_RW_UNLOCK */
|
__umtx_op_rw_unlock, /* UMTX_OP_RW_UNLOCK */
|
||||||
|
__umtx_op_wait_uint_private_compat32, /* UMTX_OP_WAIT_UINT_PRIVATE */
|
||||||
|
__umtx_op_wake_private /* UMTX_OP_WAKE_PRIVATE */
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -99,7 +99,9 @@ struct urwlock {
|
|||||||
#define UMTX_OP_RW_RDLOCK 12
|
#define UMTX_OP_RW_RDLOCK 12
|
||||||
#define UMTX_OP_RW_WRLOCK 13
|
#define UMTX_OP_RW_WRLOCK 13
|
||||||
#define UMTX_OP_RW_UNLOCK 14
|
#define UMTX_OP_RW_UNLOCK 14
|
||||||
#define UMTX_OP_MAX 15
|
#define UMTX_OP_WAIT_UINT_PRIVATE 15
|
||||||
|
#define UMTX_OP_WAKE_PRIVATE 16
|
||||||
|
#define UMTX_OP_MAX 17
|
||||||
|
|
||||||
/* flags for UMTX_OP_CV_WAIT */
|
/* flags for UMTX_OP_CV_WAIT */
|
||||||
#define UMTX_CHECK_UNPARKING 0x01
|
#define UMTX_CHECK_UNPARKING 0x01
|
||||||
@ -190,11 +192,11 @@ struct thread;
|
|||||||
|
|
||||||
struct umtx_q *umtxq_alloc(void);
|
struct umtx_q *umtxq_alloc(void);
|
||||||
void umtxq_free(struct umtx_q *);
|
void umtxq_free(struct umtx_q *);
|
||||||
int kern_umtx_wake(struct thread *td, void *uaddr, int n_wake);
|
int kern_umtx_wake(struct thread *, void *, int, int);
|
||||||
void umtx_pi_adjust(struct thread *td, u_char oldpri);
|
void umtx_pi_adjust(struct thread *, u_char);
|
||||||
void umtx_thread_init(struct thread *td);
|
void umtx_thread_init(struct thread *);
|
||||||
void umtx_thread_fini(struct thread *td);
|
void umtx_thread_fini(struct thread *);
|
||||||
void umtx_thread_alloc(struct thread *td);
|
void umtx_thread_alloc(struct thread *);
|
||||||
void umtx_thread_exit(struct thread *td);
|
void umtx_thread_exit(struct thread *);
|
||||||
#endif /* !_KERNEL */
|
#endif /* !_KERNEL */
|
||||||
#endif /* !_SYS_UMTX_H_ */
|
#endif /* !_SYS_UMTX_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user