forked from RangeNetworks/CommonLibs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LockTest.cpp
148 lines (125 loc) · 3.37 KB
/
LockTest.cpp
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
/* CommonLibs/LockTest.cpp */
/*-
*
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "Configuration.h"
#include "Threads.h"
using namespace std;
ConfigurationTable *gConfigObject;
// LockTest starts three processes that lock and unlock three mutexes at random, to make sure no deadlock occurs.
struct aprocess {
string id;
Thread t;
Mutex m;
void lockall(int lockOwnerBits);
void runtest();
static void *pstart(void *v);
void start1();
aprocess(string wid) : id(wid) {}
};
aprocess a("a"), b("b"), c("c");
void aprocess::lockall(int lockOwnerBits)
{
if (id == "a") {
ScopedLockMultiple lock(lockOwnerBits, a.m, b.m, c.m, __FILE__, __LINE__);
} else if (id == "b") {
ScopedLockMultiple lock(lockOwnerBits, b.m, a.m, c.m, __FILE__, __LINE__);
} else if (id == "c") {
ScopedLockMultiple lock(lockOwnerBits, c.m, a.m, b.m, __FILE__, __LINE__);
} else {
assert(0);
}
}
static void waitabit()
{
// randomly return instantly.
if (random() & 1)
return;
usleep(0xff & random());
}
void aprocess::runtest()
{
for (int i = 0; i < 10000; i++) {
waitabit();
// printf("%s %d here\n",id.c_str(),i);
lockall(0);
waitabit();
// printf("%s1:a=%d b=%d c=%d\n",id.c_str(),a.m.lockcnt(), b.m.lockcnt(), c.m.lockcnt());
// Add in some random locking behavior.
if (random() & 1) {
m.lock(__FILE__, __LINE__);
waitabit();
m.unlock();
}
// printf("%s2:a=%d b=%d c=%d\n",id.c_str(),a.m.lockcnt(), b.m.lockcnt(), c.m.lockcnt());
waitabit();
// printf("%s %d there\n",id.c_str(),i);
{
ScopedLock lock(m);
lockall(1);
waitabit();
// printf("%s3:a=%d b=%d c=%d\n",id.c_str(),a.m.lockcnt(), b.m.lockcnt(), c.m.lockcnt());
}
// printf("%s4:a=%d b=%d c=%d\n",id.c_str(),a.m.lockcnt(), b.m.lockcnt(), c.m.lockcnt());
}
printf("finished\n");
}
void *aprocess::pstart(void *v)
{
// This is the interface for the Thread.start() method.
aprocess *p = (aprocess *)v;
p->runtest();
return 0;
}
void aprocess::start1() { this->t.start(&this->pstart, this); }
typedef void *(*task_t)(void *);
int main(int argc, char **argv)
{
gConfigObject = new ConfigurationTable();
// Start the three processes running.
a.start1();
b.start1();
c.start1();
// And let the main process fight for the locks as well.
// We also do a coverage check here: When we randomly sample the locks, all of them must have been locked at
// some point.
int fndA = 0, fndB = 0, fndC = 0;
for (int n = 0; n < 1000; n++) {
waitabit();
fndA += a.m.lockcnt();
fndB += b.m.lockcnt();
fndC += c.m.lockcnt();
// printf("loop %d: a=%d b=%d c=%d\n",n, a.m.lockcnt(), b.m.lockcnt(), c.m.lockcnt());
printf("loop %d: a=%s b=%s c=%s\n", n, a.m.mutext().c_str(), b.m.mutext().c_str(),
c.m.mutext().c_str());
a.m.lock(__FILE__, __LINE__);
b.m.lock(__FILE__, __LINE__);
{
ScopedLockMultiple tmp(3, a.m, b.m, c.m);
waitabit();
}
c.m.lock(__FILE__, __LINE__);
waitabit();
a.m.unlock();
a.m.lock(__FILE__, __LINE__);
waitabit();
b.m.unlock();
b.m.lock(__FILE__, __LINE__);
waitabit();
a.m.unlock();
b.m.unlock();
c.m.unlock();
}
// a.t.start(&a.pstart,&a);
// b.t.start((void*)&b);
// c.t.start((void*)&c);
a.t.join(); // Wait for it to finish.
b.t.join(); // Wait for it to finish.
printf("Test Finished. During random sampling, locks held were: A %d, B %d, C %d\n", fndA, fndB, fndC);
delete gConfigObject;
return 0;
}