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:
David Xu 2008-04-29 03:48:48 +00:00
parent e3085308be
commit 727158f6f6
2 changed files with 71 additions and 19 deletions

View File

@ -948,7 +948,7 @@ do_unlock_umtx32(struct thread *td, uint32_t *m, uint32_t id)
*/
static int
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 timespec ts, ts2, ts3;
@ -957,8 +957,8 @@ do_wait(struct thread *td, void *addr, u_long id,
int error = 0;
uq = td->td_umtxq;
if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT, AUTO_SHARE,
&uq->uq_key)) != 0)
if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT,
is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0)
return (error);
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.
*/
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;
int ret;
if ((ret = umtx_key_get(uaddr, TYPE_SIMPLE_WAIT, AUTO_SHARE,
&key)) != 0)
if ((ret = umtx_key_get(uaddr, TYPE_SIMPLE_WAIT,
is_private ? THREAD_SHARE : AUTO_SHARE, &key)) != 0)
return (ret);
umtxq_lock(&key);
ret = umtxq_signal(&key, n_wake);
@ -2745,7 +2745,7 @@ __umtx_op_wait(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
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
@ -2765,13 +2765,39 @@ __umtx_op_wait_uint(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
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
__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
@ -2920,7 +2946,9 @@ static _umtx_op_func op_table[] = {
__umtx_op_wait_uint, /* UMTX_OP_WAIT_UINT */
__umtx_op_rw_rdlock, /* UMTX_OP_RW_RDLOCK */
__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
@ -3010,7 +3038,7 @@ __umtx_op_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
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
@ -3101,6 +3129,26 @@ __umtx_op_rw_wrlock_compat32(struct thread *td, struct _umtx_op_args *uap)
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[] = {
__umtx_op_lock_umtx_compat32, /* UMTX_OP_LOCK */
__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_rw_rdlock_compat32, /* UMTX_OP_RW_RDLOCK */
__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

View File

@ -99,7 +99,9 @@ struct urwlock {
#define UMTX_OP_RW_RDLOCK 12
#define UMTX_OP_RW_WRLOCK 13
#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 */
#define UMTX_CHECK_UNPARKING 0x01
@ -190,11 +192,11 @@ struct thread;
struct umtx_q *umtxq_alloc(void);
void umtxq_free(struct umtx_q *);
int kern_umtx_wake(struct thread *td, void *uaddr, int n_wake);
void umtx_pi_adjust(struct thread *td, u_char oldpri);
void umtx_thread_init(struct thread *td);
void umtx_thread_fini(struct thread *td);
void umtx_thread_alloc(struct thread *td);
void umtx_thread_exit(struct thread *td);
int kern_umtx_wake(struct thread *, void *, int, int);
void umtx_pi_adjust(struct thread *, u_char);
void umtx_thread_init(struct thread *);
void umtx_thread_fini(struct thread *);
void umtx_thread_alloc(struct thread *);
void umtx_thread_exit(struct thread *);
#endif /* !_KERNEL */
#endif /* !_SYS_UMTX_H_ */