Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Nov 2017 18:16:11 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Mateusz Guzik <mjg@freebsd.org>, src-committers@freebsd.org,  svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r325734 - head/sys/amd64/amd64
Message-ID:  <20171112175214.X1521@besplex.bde.org>
In-Reply-To: <20171112151145.Q1144@besplex.bde.org>
References:  <201711120313.vAC3D1o4074273@repo.freebsd.org> <20171112151145.Q1144@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 12 Nov 2017, Bruce Evans wrote:

> On Sun, 12 Nov 2017, Mateusz Guzik wrote:
>
>> Log:
>>  amd64: stop nesting preemption counter in spinlock_enter
>> 
>>  Discussed with:	jhb
>
> This seems to break it.  i386 still has the old code.
> ...
> The main broken case is:
> - both levels initially 0
> - disable interrupts
> - raise spinlock count to 1
> - bad race window until critical_enter() is called.  Disabling hardware
>  interrupts doesn't prevent exceptions like debugger traps or NMIs.
>  Debuuger trap handlers shouldn't use critical sections or (spin)
>  mutexes, but NMI handlers might.  When an exception handler calls
>  spinlock_enter(), this no longer gives a critical section and bad
>  things like context switches occur if the handler calls critical_enter/
>  exit().
> ...
> I don't like this change.  The nested counting is easier to understand,
> and the nested case is very rare and the critical section part of it is
> very efficient (then critical_exit() is just lowering the level).  Old
> ...
> I think the nested case is only for recursive spinlocks.  So NMI handlers
> should not use any spinlocks and the new bug is small (NMI handlers should
> not use non-recursive spinlocks since they would deadlock, and should not
> use recursive spinlocks since they don't work).  NMI handlers aren't that
> careful.  They call printf(), and even the message buffer has been broken
> to use non-recursive spinlocks.

Actually, it is valid for NMI handlers to use spinlocks via mtx_trylock_spin()
in the non-kdb non-panic case, and that is what my fixes for printf() do.

I had confused "nesting preemption counter" (td_critnest) with interrupt
nesting (the bogus td_intr_nesting_level).  td_critnest was incremented
for every concurrently held spinlock, so it could grow quite large without
any interrupt/exception recursion.  So the micro-optimization of td_critnest
is useful if it is faster and fixed to work.

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20171112175214.X1521>