Skip to content

Commit 4c6a9fc

Browse files
committed
pthread_cond_wait may return spuriously
The man page states: "In general, whenever a condition wait returns, the thread has to re-evaluate the predicate associated with the condition wait to determine whether it can safely proceed, should wait again, or should declare a timeout. A return from the wait does not imply that the associated predicate is either true or false." The regression test is based on pthread-divine/condvar_spurious_wakeup_false-unreach-call.c from SV-COMP.
1 parent b994da4 commit 4c6a9fc

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,32 @@
11
#include <assert.h>
2-
#include <pthread_lib.h>
2+
#include <pthread.h>
3+
4+
pthread_mutex_t lock;
5+
pthread_cond_t cond;
6+
7+
// only accessed in critical section guarded by mutex, so there is no need to
8+
// make this variable atomic or volatile
9+
int x;
10+
11+
void *thread(void *arg)
12+
{
13+
(void)arg;
14+
pthread_mutex_lock(&lock);
15+
pthread_cond_wait(&cond, &lock);
16+
// may fail: pthread_cond_wait can be waken up spuriously (see man
17+
// pthread_cond_wait)
18+
assert(x == 1);
19+
pthread_mutex_unlock(&lock);
20+
return NULL;
21+
}
322

423
int main()
524
{
6-
pthread_cond_wait();
7-
assert(0);
8-
return 0;
25+
pthread_t t;
26+
pthread_mutex_init(&lock, 0);
27+
pthread_cond_init(&cond, 0);
28+
pthread_create(&t, NULL, thread, NULL);
29+
x = 1;
30+
pthread_cond_broadcast(&cond);
31+
pthread_join(t, NULL);
932
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
KNOWNBUG pthread
1+
CORE pthread
22
main.c
3-
--pointer-check --bounds-check
4-
^EXIT=0$
3+
--bounds-check
4+
^EXIT=10$
55
^SIGNAL=0$
6-
^VERIFICATION SUCCESSFUL$
6+
^\*\* 1 of 2 failed
7+
^VERIFICATION FAILED$
78
--
89
^warning: ignoring

src/ansi-c/library/pthread_lib.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -636,8 +636,8 @@ inline int pthread_cond_wait(
636636
#endif
637637

638638
__CPROVER_atomic_begin();
639-
__CPROVER_assume(*((unsigned *)cond));
640-
(*((unsigned *)cond))--;
639+
if(*((unsigned *)cond))
640+
(*((unsigned *)cond))--;
641641
__CPROVER_atomic_end();
642642

643643
return 0; // we never fail

0 commit comments

Comments
 (0)