1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- /*
- * This model describes the implementation of QemuEvent in
- * util/qemu-thread-win32.c.
- *
- * 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 it:
- * spin -a docs/event.promela
- * gcc -O2 pan.c -DSAFETY
- * ./a.out
- */
- bool event;
- int value;
- /* Primitives for a Win32 event */
- #define RAW_RESET event = false
- #define RAW_SET event = true
- #define RAW_WAIT do :: event -> break; od
- #if 0
- /* Basic sanity checking: test the Win32 event primitives */
- #define RESET RAW_RESET
- #define SET RAW_SET
- #define WAIT RAW_WAIT
- #else
- /* Full model: layer a userspace-only fast path on top of the RAW_*
- * primitives. SET/RESET/WAIT have exactly the same semantics as
- * RAW_SET/RAW_RESET/RAW_WAIT, but try to avoid invoking them.
- */
- #define EV_SET 0
- #define EV_FREE 1
- #define EV_BUSY -1
- int state = EV_FREE;
- int xchg_result;
- #define SET if :: state != EV_SET -> \
- atomic { /* xchg_result=xchg(state, EV_SET) */ \
- xchg_result = state; \
- state = EV_SET; \
- } \
- if :: xchg_result == EV_BUSY -> RAW_SET; \
- :: else -> skip; \
- fi; \
- :: else -> skip; \
- fi
- #define RESET if :: state == EV_SET -> atomic { state = state | EV_FREE; } \
- :: else -> skip; \
- fi
- int tmp1, tmp2;
- #define WAIT tmp1 = state; \
- if :: tmp1 != EV_SET -> \
- if :: tmp1 == EV_FREE -> \
- RAW_RESET; \
- atomic { /* tmp2=cas(state, EV_FREE, EV_BUSY) */ \
- tmp2 = state; \
- if :: tmp2 == EV_FREE -> state = EV_BUSY; \
- :: else -> skip; \
- fi; \
- } \
- if :: tmp2 == EV_SET -> tmp1 = EV_SET; \
- :: else -> tmp1 = EV_BUSY; \
- fi; \
- :: else -> skip; \
- fi; \
- assert(tmp1 != EV_FREE); \
- if :: tmp1 == EV_BUSY -> RAW_WAIT; \
- :: else -> skip; \
- fi; \
- :: else -> skip; \
- fi
- #endif
- active proctype waiter()
- {
- if
- :: !value ->
- RESET;
- if
- :: !value -> WAIT;
- :: else -> skip;
- fi;
- :: else -> skip;
- fi;
- assert(value);
- }
- active proctype notifier()
- {
- value = true;
- SET;
- }
|