Date: Wed, 31 Jul 2019 02:27:14 +0300 From: Konstantin Belousov <kostikbel@gmail.com> To: Bryan Drewery <bdrewery@FreeBSD.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r350005 - head/sys/kern Message-ID: <20190730232714.GM2731@kib.kiev.ua> In-Reply-To: <20190730231256.GL2731@kib.kiev.ua> References: <201907151918.x6FJIPFo077975@repo.freebsd.org> <d281e1dc-1931-20a5-9f41-7c1f66d4f667@FreeBSD.org> <20190730231256.GL2731@kib.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20190730232714.GM2731>