qemu

Форк
0
/
aio_notify_accept.promela 
152 строки · 4.0 Кб
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
 */
24

25
int notify_me;
26
bool notified;
27
bool event;
28
bool req;
29
bool notifier_done;
30

31
#ifdef CHECK_REQ
32
#define USE_NOTIFY_ME 1
33
#else
34
#define USE_NOTIFY_ME 0
35
#endif
36

37
#ifdef BUG
38
#error Please define BUG1 or BUG2 instead.
39
#endif
40

41
active proctype notifier()
42
{
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;
68
}
69

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;
89

90
active proctype waiter()
91
{
92
    bool old;
93

94
    do
95
       :: true -> AIO_POLL;
96
    od;
97
}
98

99
/* Same as waiter(), but disappears after a while.  */
100
active proctype temporary_waiter()
101
{
102
    bool old;
103

104
    do
105
       :: true -> AIO_POLL;
106
       :: true -> break;
107
    od;
108
}
109

110
#ifdef CHECK_REQ
111
never {
112
    do
113
        :: req -> goto accept_if_req_not_eventually_false;
114
        :: true -> skip;
115
    od;
116

117
accept_if_req_not_eventually_false:
118
    if
119
        :: req -> goto accept_if_req_not_eventually_false;
120
    fi;
121
    assert(0);
122
}
123

124
#else
125
/* There must be infinitely many transitions of event as long
126
 * as the notifier does not exit.
127
 *
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;
138

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);
145

146
accept_if_event_not_eventually_false:
147
    if
148
        :: event     -> goto accept_if_event_not_eventually_false;
149
    fi;
150
    assert(0);
151
}
152
#endif
153

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.