Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / docs / spin / aio_notify_accept.promela
blob9cef2c955dd0059270c14289d121f6c3cf7d1ce8
1 /*
2  * This model describes the interaction between ctx->notified
3  * and ctx->notifier.
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 -DBUG1 docs/aio_notify_bug.promela
12  *     gcc -O2 pan.c
13  *     ./a.out -a -f
14  * (or -DBUG2)
15  *
16  * To verify the fixed version:
17  *     spin -a docs/aio_notify_bug.promela
18  *     gcc -O2 pan.c
19  *     ./a.out -a -f
20  *
21  * Add -DCHECK_REQ to test an alternative invariant and the
22  * "notify_me" optimization.
23  */
25 int notify_me;
26 bool notified;
27 bool event;
28 bool req;
29 bool notifier_done;
31 #ifdef CHECK_REQ
32 #define USE_NOTIFY_ME 1
33 #else
34 #define USE_NOTIFY_ME 0
35 #endif
37 #ifdef BUG
38 #error Please define BUG1 or BUG2 instead.
39 #endif
41 active proctype notifier()
43     do
44         :: true -> {
45             req = 1;
46             if
47                :: !USE_NOTIFY_ME || notify_me ->
48 #if defined BUG1
49                    /* CHECK_REQ does not detect this bug! */
50                    notified = 1;
51                    event = 1;
52 #elif defined BUG2
53                    if
54                       :: !notified -> event = 1;
55                       :: else -> skip;
56                    fi;
57                    notified = 1;
58 #else
59                    event = 1;
60                    notified = 1;
61 #endif
62                :: else -> skip;
63             fi
64         }
65         :: true -> break;
66     od;
67     notifier_done = 1;
70 #define AIO_POLL                                                    \
71     notify_me++;                                                    \
72     if                                                              \
73         :: !req -> {                                                \
74             if                                                      \
75                 :: event -> skip;                                   \
76             fi;                                                     \
77         }                                                           \
78         :: else -> skip;                                            \
79     fi;                                                             \
80     notify_me--;                                                    \
81                                                                     \
82     atomic { old = notified; notified = 0; }                        \
83     if                                                              \
84        :: old -> event = 0;                                         \
85        :: else -> skip;                                             \
86     fi;                                                             \
87                                                                     \
88     req = 0;
90 active proctype waiter()
92     bool old;
94     do
95        :: true -> AIO_POLL;
96     od;
99 /* Same as waiter(), but disappears after a while.  */
100 active proctype temporary_waiter()
102     bool old;
104     do
105        :: true -> AIO_POLL;
106        :: true -> break;
107     od;
110 #ifdef CHECK_REQ
111 never {
112     do
113         :: req -> goto accept_if_req_not_eventually_false;
114         :: true -> skip;
115     od;
117 accept_if_req_not_eventually_false:
118     if
119         :: req -> goto accept_if_req_not_eventually_false;
120     fi;
121     assert(0);
124 #else
125 /* There must be infinitely many transitions of event as long
126  * as the notifier does not exit.
128  * If event stayed always true, the waiters would be busy looping.
129  * If event stayed always false, the waiters would be sleeping
130  * forever.
131  */
132 never {
133     do
134         :: !event    -> goto accept_if_event_not_eventually_true;
135         :: event     -> goto accept_if_event_not_eventually_false;
136         :: true      -> skip;
137     od;
139 accept_if_event_not_eventually_true:
140     if
141         :: !event && notifier_done  -> do :: true -> skip; od;
142         :: !event && !notifier_done -> goto accept_if_event_not_eventually_true;
143     fi;
144     assert(0);
146 accept_if_event_not_eventually_false:
147     if
148         :: event     -> goto accept_if_event_not_eventually_false;
149     fi;
150     assert(0);
152 #endif