svn commit: r350005 - head/sys/kern
Konstantin Belousov
kostikbel at gmail.com
Tue Jul 30 23:27:22 UTC 2019
On Wed, Jul 31, 2019 at 02:13:02AM +0300, Konstantin Belousov wrote:
> On Tue, Jul 30, 2019 at 03:04:57PM -0700, Bryan Drewery wrote:
> > On 7/15/2019 12:18 PM, Konstantin Belousov wrote:
> > > Author: kib
> > > Date: Mon Jul 15 19:18:25 2019
> > > New Revision: 350005
> > > URL: https://svnweb.freebsd.org/changeset/base/350005
> > >
> > > Log:
> > > In do_sem2_wait(), balance umtx_key_get() with umtx_key_release() on retry.
> > >
> >
> > Is this also needed in do_sem_wait()? A similar pattern seems to be there.
> No, I do not think do_sem_wait() has similar issue, because the again label
> does not re-get the key.
>
> >
> > I ask because of what I referenced on IRC. I have some processes stuck
> > in here from a 10.4 jail.
> >
> > > ~/git/poudriere # procstat -kk 1498
> > > PID TID COMM TDNAME KSTACK
> > > 1498 100710 python2.7 - mi_switch+0x174 sleepq_switch+0x110 sleepq_catch_signals+0x417 sleepq_wait_sig+0xf _sleep+0x2d0 umtxq_sleep+0x153 do_sem_wait+0x42c __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 1498 101575 python2.7 - mi_switch+0x174 sleepq_switch+0x110 sleepq_catch_signals+0x417 sleepq_wait_sig+0xf _sleep+0x2d0 umtxq_sleep+0x153 do_sem_wait+0x42c __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 1498 101657 python2.7 - <running>
> > ...
> > > ~/git/poudriere # procstat -kk 1498
> > > PID TID COMM TDNAME KSTACK
> > > 1498 100710 python2.7 - mi_switch+0x174 sleepq_switch+0x110 sleepq_catch_signals+0x417 sleepq_wait_sig+0xf _sleep+0x2d0 umtxq_sleep+0x153 do_sem_wait+0x42c __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 1498 101575 python2.7 - mi_switch+0x174 sleepq_switch+0x110 sleepq_catch_signals+0x417 sleepq_wait_sig+0xf _sleep+0x2d0 umtxq_sleep+0x153 do_sem_wait+0x42c __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 1498 101657 python2.7 - do_sem_wait+0x1b6 __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > ...
> > > ~/git/poudriere # procstat -kk 94392
> > > PID TID COMM TDNAME KSTACK
> > > 94392 101815 python2.7 - mi_switch+0x174 sleepq_switch+0x110 sleepq_catch_signals+0x417 sleepq_wait_sig+0xf _sleep+0x2d0 umtxq_sleep+0x153 do_sem_wait+0x42c __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 94392 101816 python2.7 - __mtx_lock_sleep+0x118 __mtx_lock_flags+0x102 _sleep+0x334 umtxq_busy+0xb7 do_sem_wait+0x161 __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
> > > 94392 102076 python2.7 - __mtx_lock_flags+0x94 do_sem_wait+0x228 __umtx_op_sem_wait+0x6e amd64_syscall+0x2bb fast_syscall_common+0x101
>
> Try this. We should only retry casueword if it failed spuriously.
>
> diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
> index bb998457975..6c914ab6f3e 100644
> --- a/sys/kern/kern_umtx.c
> +++ b/sys/kern/kern_umtx.c
> @@ -3229,7 +3229,8 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout)
> rv = casueword32(&sem->_has_waiters, 0, &count1, 1);
> if (rv == 0)
> rv1 = fueword32(&sem->_count, &count);
> - if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) || rv == 1) {
> + if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) ||
> + (rv == 1 && count1 == 0)) {
> umtxq_lock(&uq->uq_key);
> umtxq_unbusy(&uq->uq_key);
> umtxq_remove(uq);
I think there is another problem, since even despite our intent of looping
just because of casueword returned 1, the umtxq_check_susp() should have
terminated the loop. I believe the following update would fix that.
If you have time, can you please apply only the umtxq_check_susp() chunk
and see if it helps as well ? [Both chunks are needed for correctness, but
the umtxq_check_susp() is almost impossible to test in combination]
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index bb998457975..08bdd1a1a9a 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -723,13 +723,11 @@ umtxq_check_susp(struct thread *td, bool sleep)
error = 0;
p = td->td_proc;
PROC_LOCK(p);
- if (P_SHOULDSTOP(p) ||
- ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_SUSPEND))) {
- if (p->p_flag & P_SINGLE_EXIT)
- error = EINTR;
- else
- error = sleep ? thread_suspend_check(0) : ERESTART;
- }
+ if (p->p_flag & P_SINGLE_EXIT)
+ error = EINTR;
+ else if (P_SHOULDSTOP(p) ||
+ ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_SUSPEND)))
+ error = sleep ? thread_suspend_check(0) : ERESTART;
PROC_UNLOCK(p);
return (error);
}
@@ -3229,7 +3227,8 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout)
rv = casueword32(&sem->_has_waiters, 0, &count1, 1);
if (rv == 0)
rv1 = fueword32(&sem->_count, &count);
- if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) || rv == 1) {
+ if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) ||
+ (rv == 1 && count1 == 0)) {
umtxq_lock(&uq->uq_key);
umtxq_unbusy(&uq->uq_key);
umtxq_remove(uq);
More information about the svn-src-head
mailing list