qemu

Форк
0
/
aio_notify_bug.promela 
140 строк · 4.1 Кб
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
 */
23

24
int notify_me;
25
bool event;
26
bool req;
27
bool notifier_done;
28

29
#ifdef CHECK_REQ
30
#define USE_NOTIFY_ME 1
31
#else
32
#define USE_NOTIFY_ME 0
33
#endif
34

35
active proctype notifier()
36
{
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;
48
}
49

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
81

82
active proctype waiter()
83
{
84
    do
85
       :: true -> AIO_POLL;
86
    od;
87
}
88

89
/* Same as waiter(), but disappears after a while.  */
90
active proctype temporary_waiter()
91
{
92
    do
93
       :: true -> AIO_POLL;
94
       :: true -> break;
95
    od;
96
}
97

98
#ifdef CHECK_REQ
99
never {
100
    do
101
        :: req -> goto accept_if_req_not_eventually_false;
102
        :: true -> skip;
103
    od;
104

105
accept_if_req_not_eventually_false:
106
    if
107
        :: req -> goto accept_if_req_not_eventually_false;
108
    fi;
109
    assert(0);
110
}
111

112
#else
113
/* There must be infinitely many transitions of event as long
114
 * as the notifier does not exit.
115
 *
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;
126

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

134
accept_if_event_not_eventually_false:
135
    if
136
        :: event     -> goto accept_if_event_not_eventually_false;
137
    fi;
138
    assert(0);
139
}
140
#endif
141

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

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

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

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