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:
David Xu 2006-12-04 14:15:12 +00:00
parent 02f3691e93
commit 745fbd3a72
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=164876
4 changed files with 25 additions and 5 deletions

View File

@ -402,6 +402,12 @@ kern_thr_suspend(struct thread *td, struct timespec *tsp)
TIMESPEC_TO_TIMEVAL(&tv, tsp);
hz = tvtohz(&tv);
}
if (td->td_pflags & TDP_WAKEUP) {
td->td_pflags &= ~TDP_WAKEUP;
return (0);
}
PROC_LOCK(td->td_proc);
if ((td->td_flags & TDF_THRWAKEUP) == 0)
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 thread *ttd;
if (uap->id == td->td_tid) {
td->td_pflags |= TDP_WAKEUP;
return (0);
}
p = td->td_proc;
PROC_LOCK(p);
ttd = thread_find(p, uap->id);

View File

@ -2170,7 +2170,7 @@ do_unlock_umutex(struct thread *td, struct umutex *m)
static int
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 timeval tv;
@ -2202,7 +2202,11 @@ do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m,
umtxq_lock(&uq->uq_key);
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);
} else {
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
* can not avoid it.
*/
umtxq_signal(&uq->uq_key, 1);
if (!umtxq_signal(&uq->uq_key, 1))
error = 0;
}
if (error == ERESTART)
error = EINTR;
@ -2431,7 +2436,7 @@ __umtx_op_cv_wait(struct thread *td, struct _umtx_op_args *uap)
}
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
@ -2592,7 +2597,7 @@ __umtx_op_cv_wait_compat32(struct thread *td, struct _umtx_op_args *uap)
return (EINVAL);
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[] = {

View File

@ -455,6 +455,7 @@ struct thread {
#define TDP_GEOM 0x00010000 /* Settle GEOM before finishing syscall */
#define TDP_SOFTDEP 0x00020000 /* Stuck processing softdep worklist */
#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.

View File

@ -80,6 +80,9 @@ struct ucond {
#define UMTX_OP_CV_BROADCAST 10
#define UMTX_OP_MAX 11
/* flags for UMTX_OP_CV_WAIT */
#define UMTX_CHECK_UNPARKING 0x01
#ifndef _KERNEL
int _umtx_op(void *obj, int op, u_long val, void *uaddr, void *uaddr2);