if a thread blocked on userland condition variable is
pthread_cancel()ed, it is expected that the thread will not consume a pthread_cond_signal(), therefor, we use thr_wake() to mark a flag, the flag tells a thread calling do_cv_wait() in umtx code to not block on a condition variable. Thread library is expected that once a thread detected itself is in pthread_cond_wait, it will call the thr_wake() for itself in its SIGCANCEL handler.
This commit is contained in:
parent
02f3691e93
commit
745fbd3a72
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=164876
@ -402,6 +402,12 @@ kern_thr_suspend(struct thread *td, struct timespec *tsp)
|
|||||||
TIMESPEC_TO_TIMEVAL(&tv, tsp);
|
TIMESPEC_TO_TIMEVAL(&tv, tsp);
|
||||||
hz = tvtohz(&tv);
|
hz = tvtohz(&tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (td->td_pflags & TDP_WAKEUP) {
|
||||||
|
td->td_pflags &= ~TDP_WAKEUP;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
PROC_LOCK(td->td_proc);
|
PROC_LOCK(td->td_proc);
|
||||||
if ((td->td_flags & TDF_THRWAKEUP) == 0)
|
if ((td->td_flags & TDF_THRWAKEUP) == 0)
|
||||||
error = msleep((void *)td, &td->td_proc->p_mtx, PCATCH, "lthr",
|
error = msleep((void *)td, &td->td_proc->p_mtx, PCATCH, "lthr",
|
||||||
@ -430,6 +436,11 @@ thr_wake(struct thread *td, struct thr_wake_args *uap)
|
|||||||
struct proc *p;
|
struct proc *p;
|
||||||
struct thread *ttd;
|
struct thread *ttd;
|
||||||
|
|
||||||
|
if (uap->id == td->td_tid) {
|
||||||
|
td->td_pflags |= TDP_WAKEUP;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
p = td->td_proc;
|
p = td->td_proc;
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
ttd = thread_find(p, uap->id);
|
ttd = thread_find(p, uap->id);
|
||||||
|
@ -2170,7 +2170,7 @@ do_unlock_umutex(struct thread *td, struct umutex *m)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
|
do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
|
||||||
struct timespec *timeout)
|
struct timespec *timeout, u_long wflags)
|
||||||
{
|
{
|
||||||
struct umtx_q *uq;
|
struct umtx_q *uq;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -2202,7 +2202,11 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
|
|||||||
|
|
||||||
umtxq_lock(&uq->uq_key);
|
umtxq_lock(&uq->uq_key);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
if (timeout == NULL) {
|
if ((wflags & UMTX_CHECK_UNPARKING) &&
|
||||||
|
(td->td_pflags & TDP_WAKEUP)) {
|
||||||
|
td->td_pflags &= ~TDP_WAKEUP;
|
||||||
|
error = EINTR;
|
||||||
|
} else if (timeout == NULL) {
|
||||||
error = umtxq_sleep(uq, "ucond", 0);
|
error = umtxq_sleep(uq, "ucond", 0);
|
||||||
} else {
|
} else {
|
||||||
getnanouptime(&ets);
|
getnanouptime(&ets);
|
||||||
@ -2236,7 +2240,8 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
|
|||||||
* occur, and indeed a kernel based implementation
|
* occur, and indeed a kernel based implementation
|
||||||
* can not avoid it.
|
* can not avoid it.
|
||||||
*/
|
*/
|
||||||
umtxq_signal(&uq->uq_key, 1);
|
if (!umtxq_signal(&uq->uq_key, 1))
|
||||||
|
error = 0;
|
||||||
}
|
}
|
||||||
if (error == ERESTART)
|
if (error == ERESTART)
|
||||||
error = EINTR;
|
error = EINTR;
|
||||||
@ -2431,7 +2436,7 @@ __umtx_op_cv_wait(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
}
|
}
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return (do_cv_wait(td, uap->obj, uap->uaddr1, ts));
|
return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2592,7 +2597,7 @@ __umtx_op_cv_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
ts = &timeout;
|
ts = &timeout;
|
||||||
}
|
}
|
||||||
return (do_cv_wait(td, uap->obj, uap->uaddr1, ts));
|
return (do_cv_wait(td, uap->obj, uap->uaddr1, ts, uap->val));
|
||||||
}
|
}
|
||||||
|
|
||||||
static _umtx_op_func op_table_compat32[] = {
|
static _umtx_op_func op_table_compat32[] = {
|
||||||
|
@ -455,6 +455,7 @@ struct thread {
|
|||||||
#define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */
|
#define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */
|
||||||
#define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */
|
#define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */
|
||||||
#define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */
|
#define TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */
|
||||||
|
#define TDP_WAKEUP 0x00080000 /* Don't sleep in umtx cond_wait */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reasons that the current thread can not be run yet.
|
* Reasons that the current thread can not be run yet.
|
||||||
|
@ -80,6 +80,9 @@ struct ucond {
|
|||||||
#define UMTX_OP_CV_BROADCAST 10
|
#define UMTX_OP_CV_BROADCAST 10
|
||||||
#define UMTX_OP_MAX 11
|
#define UMTX_OP_MAX 11
|
||||||
|
|
||||||
|
/* flags for UMTX_OP_CV_WAIT */
|
||||||
|
#define UMTX_CHECK_UNPARKING 0x01
|
||||||
|
|
||||||
#ifndef _KERNEL
|
#ifndef _KERNEL
|
||||||
|
|
||||||
int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
|
int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);
|
||||||
|
Loading…
Reference in New Issue
Block a user