Developer documentation should be its own manual. As a start, move all developer-oriented files to a separate directory. Also move non-text files to their own directories: docs/config/ for QEMU -readconfig input, and docs/spin/ for formal models to be used with the SPIN model checker. Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Promela
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Promela
		
	
	
	
	
	
/*
 | 
						|
 * This model describes a bug in aio_notify.  If ctx->notifier is
 | 
						|
 * cleared too late, a wakeup could be lost.
 | 
						|
 *
 | 
						|
 * Author: Paolo Bonzini <pbonzini@redhat.com>
 | 
						|
 *
 | 
						|
 * This file is in the public domain.  If you really want a license,
 | 
						|
 * the WTFPL will do.
 | 
						|
 *
 | 
						|
 * To verify the buggy version:
 | 
						|
 *     spin -a -DBUG docs/aio_notify_bug.promela
 | 
						|
 *     gcc -O2 pan.c
 | 
						|
 *     ./a.out -a -f
 | 
						|
 *
 | 
						|
 * To verify the fixed version:
 | 
						|
 *     spin -a docs/aio_notify_bug.promela
 | 
						|
 *     gcc -O2 pan.c
 | 
						|
 *     ./a.out -a -f
 | 
						|
 *
 | 
						|
 * Add -DCHECK_REQ to test an alternative invariant and the
 | 
						|
 * "notify_me" optimization.
 | 
						|
 */
 | 
						|
 | 
						|
int notify_me;
 | 
						|
bool event;
 | 
						|
bool req;
 | 
						|
bool notifier_done;
 | 
						|
 | 
						|
#ifdef CHECK_REQ
 | 
						|
#define USE_NOTIFY_ME 1
 | 
						|
#else
 | 
						|
#define USE_NOTIFY_ME 0
 | 
						|
#endif
 | 
						|
 | 
						|
active proctype notifier()
 | 
						|
{
 | 
						|
    do
 | 
						|
        :: true -> {
 | 
						|
            req = 1;
 | 
						|
            if
 | 
						|
               :: !USE_NOTIFY_ME || notify_me -> event = 1;
 | 
						|
               :: else -> skip;
 | 
						|
            fi
 | 
						|
        }
 | 
						|
        :: true -> break;
 | 
						|
    od;
 | 
						|
    notifier_done = 1;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef BUG
 | 
						|
#define AIO_POLL                                                    \
 | 
						|
    notify_me++;                                                    \
 | 
						|
    if                                                              \
 | 
						|
        :: !req -> {                                                \
 | 
						|
            if                                                      \
 | 
						|
                :: event -> skip;                                   \
 | 
						|
            fi;                                                     \
 | 
						|
        }                                                           \
 | 
						|
        :: else -> skip;                                            \
 | 
						|
    fi;                                                             \
 | 
						|
    notify_me--;                                                    \
 | 
						|
                                                                    \
 | 
						|
    req = 0;                                                        \
 | 
						|
    event = 0;
 | 
						|
#else
 | 
						|
#define AIO_POLL                                                    \
 | 
						|
    notify_me++;                                                    \
 | 
						|
    if                                                              \
 | 
						|
        :: !req -> {                                                \
 | 
						|
            if                                                      \
 | 
						|
                :: event -> skip;                                   \
 | 
						|
            fi;                                                     \
 | 
						|
        }                                                           \
 | 
						|
        :: else -> skip;                                            \
 | 
						|
    fi;                                                             \
 | 
						|
    notify_me--;                                                    \
 | 
						|
                                                                    \
 | 
						|
    event = 0;                                                      \
 | 
						|
    req = 0;
 | 
						|
#endif
 | 
						|
 | 
						|
active proctype waiter()
 | 
						|
{
 | 
						|
    do
 | 
						|
       :: true -> AIO_POLL;
 | 
						|
    od;
 | 
						|
}
 | 
						|
 | 
						|
/* Same as waiter(), but disappears after a while.  */
 | 
						|
active proctype temporary_waiter()
 | 
						|
{
 | 
						|
    do
 | 
						|
       :: true -> AIO_POLL;
 | 
						|
       :: true -> break;
 | 
						|
    od;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef CHECK_REQ
 | 
						|
never {
 | 
						|
    do
 | 
						|
        :: req -> goto accept_if_req_not_eventually_false;
 | 
						|
        :: true -> skip;
 | 
						|
    od;
 | 
						|
 | 
						|
accept_if_req_not_eventually_false:
 | 
						|
    if
 | 
						|
        :: req -> goto accept_if_req_not_eventually_false;
 | 
						|
    fi;
 | 
						|
    assert(0);
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
/* There must be infinitely many transitions of event as long
 | 
						|
 * as the notifier does not exit.
 | 
						|
 *
 | 
						|
 * If event stayed always true, the waiters would be busy looping.
 | 
						|
 * If event stayed always false, the waiters would be sleeping
 | 
						|
 * forever.
 | 
						|
 */
 | 
						|
never {
 | 
						|
    do
 | 
						|
        :: !event    -> goto accept_if_event_not_eventually_true;
 | 
						|
        :: event     -> goto accept_if_event_not_eventually_false;
 | 
						|
        :: true      -> skip;
 | 
						|
    od;
 | 
						|
 | 
						|
accept_if_event_not_eventually_true:
 | 
						|
    if
 | 
						|
        :: !event && notifier_done  -> do :: true -> skip; od;
 | 
						|
        :: !event && !notifier_done -> goto accept_if_event_not_eventually_true;
 | 
						|
    fi;
 | 
						|
    assert(0);
 | 
						|
 | 
						|
accept_if_event_not_eventually_false:
 | 
						|
    if
 | 
						|
        :: event     -> goto accept_if_event_not_eventually_false;
 | 
						|
    fi;
 | 
						|
    assert(0);
 | 
						|
}
 | 
						|
#endif
 |