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
 |