diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2017-06-07 18:24:08 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2017-06-07 18:24:08 +0100 |
commit | bbfa326fc8028e275eddf8c9965c2a1b59405b2e (patch) | |
tree | 18462ee41801d922e941ee50e1e4a54a96324464 /docs/spin/aio_notify_bug.promela | |
parent | 64175afc695c0672876fbbfc31b299c86d562cb4 (diff) | |
parent | ac06724a715864942e2b5e28f92d5d5421f0a0b0 (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* virtio-scsi use-after-free fix (Fam)
* SMM fixes and improvements for TCG (myself, Mihail)
* irqchip and AddressSpaceDispatch cleanups and fixes (Peter)
* Coverity fix (Stefano)
* NBD cleanups and fixes (Vladimir, Eric, myself)
* RTC accuracy improvements and code cleanups (Guangrong+Yunfang)
* socket error reporting improvement (Daniel)
* GDB XML description for SSE registers (Abdallah)
* kvmclock update fix (Denis)
* SMM memory savings (Gonglei)
* -cpu 486 fix (myself)
* various bugfixes (Roman, Peter, myself, Thomas)
* rtc-test improvement (Guangrong)
* migration throttling fix (Felipe)
* create docs/ subdirectories (myself)
# gpg: Signature made Wed 07 Jun 2017 17:22:07 BST
# gpg: using RSA key 0xBFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>"
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (31 commits)
docs: create config/, devel/ and spin/ subdirectories
cpus: reset throttle_thread_scheduled after sleep
kvm: don't register smram_listener when smm is off
nbd: make it thread-safe, fix qcow2 over nbd
target/i386: Add GDB XML description for SSE registers
i386/kvm: do not zero out segment flags if segment is unusable or not present
edu: fix memory leak on msi_broken platforms
linuxboot_dma: compile for i486
kvmclock: update system_time_msr address forcibly
nbd: Fully initialize client in case of failed negotiation
sockets: improve error reporting if UNIX socket path is too long
i386: fix read/write cr with icount option
target/i386: use multiple CPU AddressSpaces
target/i386: enable A20 automatically in system management mode
virtio-scsi: Unset hotplug handler when unrealize
exec: simplify phys_page_find() params
nbd/client.c: use errp instead of LOG
nbd: add errp to read_sync, write_sync and drop_sync
nbd: add errp parameter to nbd_wr_syncv()
nbd: read_sync and friends: return 0 on success
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'docs/spin/aio_notify_bug.promela')
-rw-r--r-- | docs/spin/aio_notify_bug.promela | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/docs/spin/aio_notify_bug.promela b/docs/spin/aio_notify_bug.promela new file mode 100644 index 0000000000..b3bfca1ca4 --- /dev/null +++ b/docs/spin/aio_notify_bug.promela @@ -0,0 +1,140 @@ +/* + * 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 |