-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlocktest.c
161 lines (139 loc) · 3.79 KB
/
locktest.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/****************************************************************
* Using locks
*
* Copyright Alastair Reid 2020
* SPDX-Licence-Identifier: BSD-3-Clause
****************************************************************/
#include "prelude.h"
#include "mylock.h"
#include "threading.h"
// A container for some data with atomic update
// (The update is not interesting - just something I can write
// an invariant for.)
struct pair {
int a;
int b;
struct mylock lock;
};
/*@
// Use this for uninitialized pairs
predicate pair_raw(struct pair *p;) =
p->a |-> _
&*& p->b |-> _
&*& mylock_raw(&p->lock)
// &*& struct_pair_padding(p)
;
// Invariant for a pair that should hold whenever the pair is locked
// is locked.
//
// Note that it does not mention the lock itself because that
// would require a cyclic reference to this invariant
predicate_ctor pair_invariant(struct pair *p)() =
p->a |-> ?a
&*& p->b |-> ?b
&*& a < b
;
// A pair that is currently locked.
//
// Note that it does not say anything about l->a or l->b because
// they are not accessible until you acquire the lock.
//
// Note that (unlike standard VeriFast examples), this does
// not require "malloc_block_pair(l)" so it is possible to
// use this with stack-allocated and global paires.
predicate pair(struct pair *p;) =
mylock(&p->lock, pair_invariant(p))
;
@*/
// initialize a previously allocated pair object
void pair_init(struct pair* p)
//@ requires pair_raw(p);
//@ ensures pair(p);
{
p->a = 0;
p->b = 10;
//@ close create_mylock_ghost_arg(pair_invariant(p));
//@ close pair_invariant(p)();
mylock_init(&p->lock);
}
// finalize a pair - making it ready to deallocate
void pair_fini(struct pair* p)
//@ requires pair(p);
//@ ensures pair_raw(p);
{
mylock_fini(&p->lock);
//@ open pair_invariant(p)();
}
void pair_inc(struct pair* p)
//@ requires [?f]pair(p);
//@ ensures [f]pair(p);
{
mylock_acquire(&p->lock);
//@ open pair_invariant(p)();
p->a++;
if (p->a == p->b) {
p->a = p->b - 1;
}
//@ close pair_invariant(p)();
mylock_release(&p->lock);
}
/****************************************************************
* Sequential tests
****************************************************************/
// Sequential test code
void test_pair_sequential()
//@ requires true;
//@ ensures true;
{
struct pair p;
pair_init(&p);
pair_inc(&p);
pair_inc(&p);
pair_inc(&p);
pair_fini(&p);
}
/****************************************************************
* Concurrent tests
****************************************************************/
/*@
predicate_family_instance thread_run_pre(test_thread)(struct pair *p, any info) = [1/4]pair(p);
predicate_family_instance thread_run_post(test_thread)(struct pair *p, any info) = [1/4]pair(p);
@*/
void test_thread(struct pair *p) //@ : thread_run_joinable
//@ requires thread_run_pre(test_thread)(p, ?info);
//@ ensures thread_run_post(test_thread)(p, info);
{
//@ open thread_run_pre(test_thread)(p, info);
pair_inc(p);
//@ close thread_run_post(test_thread)(p, info);
}
struct thread *start_thread(struct pair *p)
//@ requires [1/4]pair(p);
//@ ensures thread(result, test_thread, p, _);
{
//@ close thread_run_pre(test_thread)(p, unit);
return thread_start_joinable(test_thread, p);
}
void join_thread(struct thread *t)
//@ requires thread(t, test_thread, ?p, _);
//@ ensures [1/4]pair(p);
{
thread_join(t);
//@ open thread_run_post(test_thread)(p, _);
}
// Concurrent test function
void test_pair_concurrent()
//@ requires true;
//@ ensures true;
{
struct pair p;
pair_init(&p);
struct thread *t1 = start_thread(&p);
struct thread *t2 = start_thread(&p);
join_thread(t1);
join_thread(t2);
pair_fini(&p);
}
/****************************************************************
* End
****************************************************************/