Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160404' into...
[qemu.git] / docs / aio_notify_bug.promela
blobb3bfca1ca4f52f73365c413af97c0bd739be922d
1 /*
2  * This model describes a bug in aio_notify.  If ctx->notifier is
3  * cleared too late, a wakeup could be lost.
4  *
5  * Author: Paolo Bonzini <pbonzini@redhat.com>
6  *
7  * This file is in the public domain.  If you really want a license,
8  * the WTFPL will do.
9  *
10  * To verify the buggy version:
11  *     spin -a -DBUG docs/aio_notify_bug.promela
12  *     gcc -O2 pan.c
13  *     ./a.out -a -f
14  *
15  * To verify the fixed version:
16  *     spin -a docs/aio_notify_bug.promela
17  *     gcc -O2 pan.c
18  *     ./a.out -a -f
19  *
20  * Add -DCHECK_REQ to test an alternative invariant and the
21  * "notify_me" optimization.
22  */
24 int notify_me;
25 bool event;
26 bool req;
27 bool notifier_done;
29 #ifdef CHECK_REQ
30 #define USE_NOTIFY_ME 1
31 #else
32 #define USE_NOTIFY_ME 0
33 #endif
35 active proctype notifier()
37     do
38         :: true -> {
39             req = 1;
40             if
41                :: !USE_NOTIFY_ME || notify_me -> event = 1;
42                :: else -> skip;
43             fi
44         }
45         :: true -> break;
46     od;
47     notifier_done = 1;
50 #ifdef BUG
51 #define AIO_POLL                                                    \
52     notify_me++;                                                    \
53     if                                                              \
54         :: !req -> {                                                \
55             if                                                      \
56                 :: event -> skip;                                   \
57             fi;                                                     \
58         }                                                           \
59         :: else -> skip;                                            \
60     fi;                                                             \
61     notify_me--;                                                    \
62                                                                     \
63     req = 0;                                                        \
64     event = 0;
65 #else
66 #define AIO_POLL                                                    \
67     notify_me++;                                                    \
68     if                                                              \
69         :: !req -> {                                                \
70             if                                                      \
71                 :: event -> skip;                                   \
72             fi;                                                     \
73         }                                                           \
74         :: else -> skip;                                            \
75     fi;                                                             \
76     notify_me--;                                                    \
77                                                                     \
78     event = 0;                                                      \
79     req = 0;
80 #endif
82 active proctype waiter()
84     do
85        :: true -> AIO_POLL;
86     od;
89 /* Same as waiter(), but disappears after a while.  */
90 active proctype temporary_waiter()
92     do
93        :: true -> AIO_POLL;
94        :: true -> break;
95     od;
98 #ifdef CHECK_REQ
99 never {
100     do
101         :: req -> goto accept_if_req_not_eventually_false;
102         :: true -> skip;
103     od;
105 accept_if_req_not_eventually_false:
106     if
107         :: req -> goto accept_if_req_not_eventually_false;
108     fi;
109     assert(0);
112 #else
113 /* There must be infinitely many transitions of event as long
114  * as the notifier does not exit.
116  * If event stayed always true, the waiters would be busy looping.
117  * If event stayed always false, the waiters would be sleeping
118  * forever.
119  */
120 never {
121     do
122         :: !event    -> goto accept_if_event_not_eventually_true;
123         :: event     -> goto accept_if_event_not_eventually_false;
124         :: true      -> skip;
125     od;
127 accept_if_event_not_eventually_true:
128     if
129         :: !event && notifier_done  -> do :: true -> skip; od;
130         :: !event && !notifier_done -> goto accept_if_event_not_eventually_true;
131     fi;
132     assert(0);
134 accept_if_event_not_eventually_false:
135     if
136         :: event     -> goto accept_if_event_not_eventually_false;
137     fi;
138     assert(0);
140 #endif