105 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Promela
		
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Promela
		
	
	
	
/*
 | 
						|
 * This model describes the interaction between aio_set_dispatching()
 | 
						|
 * and aio_notify().
 | 
						|
 *
 | 
						|
 * Author: Paolo Bonzini <pbonzini@redhat.com>
 | 
						|
 *
 | 
						|
 * This file is in the public domain.  If you really want a license,
 | 
						|
 * the WTFPL will do.
 | 
						|
 *
 | 
						|
 * To simulate it:
 | 
						|
 *     spin -p docs/aio_notify.promela
 | 
						|
 *
 | 
						|
 * To verify it:
 | 
						|
 *     spin -a docs/aio_notify.promela
 | 
						|
 *     gcc -O2 pan.c
 | 
						|
 *     ./a.out -a
 | 
						|
 */
 | 
						|
 | 
						|
#define MAX   4
 | 
						|
#define LAST  (1 << (MAX - 1))
 | 
						|
#define FINAL ((LAST << 1) - 1)
 | 
						|
 | 
						|
bool dispatching;
 | 
						|
bool event;
 | 
						|
 | 
						|
int req, done;
 | 
						|
 | 
						|
active proctype waiter()
 | 
						|
{
 | 
						|
     int fetch, blocking;
 | 
						|
 | 
						|
     do
 | 
						|
        :: done != FINAL -> {
 | 
						|
            // Computing "blocking" is separate from execution of the
 | 
						|
            // "bottom half"
 | 
						|
            blocking = (req == 0);
 | 
						|
 | 
						|
            // This is our "bottom half"
 | 
						|
            atomic { fetch = req; req = 0; }
 | 
						|
            done = done | fetch;
 | 
						|
 | 
						|
            // Wait for a nudge from the other side
 | 
						|
            do
 | 
						|
                :: event == 1 -> { event = 0; break; }
 | 
						|
                :: !blocking  -> break;
 | 
						|
            od;
 | 
						|
 | 
						|
            dispatching = 1;
 | 
						|
 | 
						|
            // If you are simulating this model, you may want to add
 | 
						|
            // something like this here:
 | 
						|
            //
 | 
						|
            //      int foo; foo++; foo++; foo++;
 | 
						|
            //
 | 
						|
            // This only wastes some time and makes it more likely
 | 
						|
            // that the notifier process hits the "fast path".
 | 
						|
 | 
						|
            dispatching = 0;
 | 
						|
        }
 | 
						|
        :: else -> break;
 | 
						|
    od
 | 
						|
}
 | 
						|
 | 
						|
active proctype notifier()
 | 
						|
{
 | 
						|
    int next = 1;
 | 
						|
    int sets = 0;
 | 
						|
 | 
						|
    do
 | 
						|
        :: next <= LAST -> {
 | 
						|
            // generate a request
 | 
						|
            req = req | next;
 | 
						|
            next = next << 1;
 | 
						|
 | 
						|
            // aio_notify
 | 
						|
            if
 | 
						|
                :: dispatching == 0 -> sets++; event = 1;
 | 
						|
                :: else             -> skip;
 | 
						|
            fi;
 | 
						|
 | 
						|
            // Test both synchronous and asynchronous delivery
 | 
						|
            if
 | 
						|
                :: 1 -> do
 | 
						|
                            :: req == 0 -> break;
 | 
						|
                        od;
 | 
						|
                :: 1 -> skip;
 | 
						|
            fi;
 | 
						|
        }
 | 
						|
        :: else -> break;
 | 
						|
    od;
 | 
						|
    printf("Skipped %d event_notifier_set\n", MAX - sets);
 | 
						|
}
 | 
						|
 | 
						|
#define p (done == FINAL)
 | 
						|
 | 
						|
never  {
 | 
						|
    do
 | 
						|
        :: 1                      // after an arbitrarily long prefix
 | 
						|
        :: p -> break             // p becomes true
 | 
						|
    od;
 | 
						|
    do
 | 
						|
        :: !p -> accept: break    // it then must remains true forever after
 | 
						|
    od
 | 
						|
}
 |