On Mon, Nov 24, 2014 at 03:50:58PM -0800, Paul E. McKenney wrote:
> On Mon, Nov 24, 2014 at 03:35:55PM -0800, Andy Lutomirski wrote:
> > On Mon, Nov 24, 2014 at 3:31 PM, Paul E. McKenney
> > <paul...@linux.vnet.ibm.com> wrote:
> > > On Mon, Nov 24, 2014 at 02:57:54PM -0800, Paul E. McKenney wrote:
> > >> On Mon, Nov 24, 2014 at 02:36:18PM -0800, Andy Lutomirski wrote:
> > >> > On Mon, Nov 24, 2014 at 2:34 PM, Paul E. McKenney
> > >> > <paul...@linux.vnet.ibm.com> wrote:
> > >> > > On Mon, Nov 24, 2014 at 01:35:01PM -0800, Paul E. McKenney wrote:
> > >>
> > >> [ . . . ]
> > >>
> > >> > > And the following Promela model claims that your approach works.
> > >> > > Should I trust it?  ;-)
> > >> > >
> > >> >
> > >> > I think so.

OK, I added some coverage checks and also injected bugs, all of which
it detected, so I am feeling at least a bit more confident in the model,
the updated version of which is included below, along with the script
that runs it.

                                                        Thanx, Paul

------------------------------------------------------------------------
rcu_nmi.spin
------------------------------------------------------------------------

/*
 * Promela model for Andy Lutomirski's suggested change to rcu_nmi_enter()
 * that allows nesting.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 * Copyright IBM Corporation, 2014
 *
 * Author: Paul E. McKenney <paul...@linux.vnet.ibm.com>
 */

byte dynticks_nmi_nesting = 0;
byte dynticks = 0;
#define BUSY_INCBY 2 /* set to 1 to force failure. */

/*
 * Promela verision of rcu_nmi_enter().
 */
inline rcu_nmi_enter()
{
        byte incby;
        byte tmp;

        incby = BUSY_INCBY;
        assert(dynticks_nmi_nesting >= 0);
        if
        :: (dynticks & 1) == 0 ->
                atomic {
                        dynticks = dynticks + 1;
                }
                assert((dynticks & 1) == 1);
                incby = 1;
        :: else ->
                skip;
        fi;
        tmp = dynticks_nmi_nesting;
        tmp = tmp + incby;
        dynticks_nmi_nesting = tmp;
        assert(dynticks_nmi_nesting >= 1);
}

/*
 * Promela verision of rcu_nmi_exit().
 */
inline rcu_nmi_exit()
{
        byte tmp;

        assert(dynticks_nmi_nesting > 0);
        assert((dynticks & 1) != 0);
        if
        :: dynticks_nmi_nesting != 1 ->
                tmp = dynticks_nmi_nesting;
                tmp = tmp - BUSY_INCBY;
                dynticks_nmi_nesting = tmp;
        :: else ->
                dynticks_nmi_nesting = 0;
                atomic {
                        dynticks = dynticks + 1;
                }
                assert((dynticks & 1) == 0);
        fi;
}

/*
 * Base-level NMI runs non-atomically.  Crudely emulates process-level
 * dynticks-idle entry/exit.
 */
proctype base_NMI()
{
        byte busy;

        busy = 0;
        do
        ::      /* Emulate base-level dynticks and not. */
                if
                :: 1 -> atomic {
                                dynticks = dynticks + 1;
                        }
                        busy = 1;
                :: 1 -> skip;
                fi;

                /* Verify that we only sometimes have base-level dynticks. */
                if
                :: busy == 0 -> skip;
                :: busy == 1 -> skip;
                fi;

                /* Model RCU's NMI entry and exit actions. */
                rcu_nmi_enter();
                assert((dynticks & 1) == 1);
                rcu_nmi_exit();

                /* Emulated re-entering base-level dynticks and not. */
                if
                :: !busy -> skip;
                :: busy ->
                        atomic {
                                dynticks = dynticks + 1;
                        }
                        busy = 0;
                fi;

                /* We had better now be in dyntick-idle mode. */
                assert((dynticks & 1) == 0);
        od;
}

/*
 * Nested NMI runs atomically to emulate interrupting base_level().
 */
proctype nested_NMI()
{
        do
        ::      /*
                 * Use an atomic section to model a nested NMI.  This is
                 * guaranteed to interleave into base_NMI() between a pair
                 * of base_NMI() statements, just as a nested NMI would.
                 */
                atomic {
                        /* Verify that we only sometimes are in dynticks. */
                        if
                        :: (dynticks & 1) == 0 -> skip;
                        :: (dynticks & 1) == 1 -> skip;
                        fi;

                        /* Model RCU's NMI entry and exit actions. */
                        rcu_nmi_enter();
                        assert((dynticks & 1) == 1);
                        rcu_nmi_exit();
                }
        od;
}

init {
        run base_NMI();
        run nested_NMI();
}

------------------------------------------------------------------------
rcu_nmi.sh
------------------------------------------------------------------------

if ! spin -a rcu_nmi.spin
then
        echo Spin errors!!!
        exit 1
fi
if ! cc -DSAFETY -o pan pan.c
then
        echo Compilation errors!!!
        exit 1
fi
./pan -m100000
# For errors: spin -p -l -g -t rcu_nmi.spin < rcu_nmi.spin.trail

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to