17 #include "SafeMutex.hpp"
24 return err(ErrState, __LINE__);
25 ret = pthread_mutex_init(&m_mutex, 0);
27 return err(ret, __LINE__);
28 ret = pthread_cond_init(&m_cond, 0);
30 return err(ret, __LINE__);
40 return err(ErrState, __LINE__);
41 ret = pthread_cond_destroy(&m_cond);
43 return err(ret, __LINE__);
44 ret = pthread_mutex_destroy(&m_mutex);
46 return err(ret, __LINE__);
56 ret = pthread_mutex_lock(&m_mutex);
58 return err(ret, __LINE__);
61 ret = pthread_mutex_lock(&m_mutex);
63 return err(ret, __LINE__);
68 SafeMutex::lock_impl()
71 pthread_t
self = pthread_self();
77 }
else if (m_owner !=
self) {
78 ret = pthread_cond_wait(&m_cond, &m_mutex);
80 return err(ret, __LINE__);
83 if (!(m_level < m_limit))
84 return err(ErrLevel, __LINE__);
86 if (m_usage < m_level)
88 ret = pthread_cond_signal(&m_cond);
90 return err(ret, __LINE__);
91 ret = pthread_mutex_unlock(&m_mutex);
93 return err(ret, __LINE__);
104 ret = pthread_mutex_unlock(&m_mutex);
106 return err(ret, __LINE__);
109 ret = pthread_mutex_lock(&m_mutex);
111 return err(ret, __LINE__);
112 return unlock_impl();
116 SafeMutex::unlock_impl()
119 pthread_t
self = pthread_self();
122 return err(ErrOwner, __LINE__);
124 return err(ErrNolock, __LINE__);
128 ret = pthread_cond_signal(&m_cond);
130 return err(ret, __LINE__);
132 ret = pthread_mutex_unlock(&m_mutex);
134 return err(ret, __LINE__);
139 SafeMutex::err(
int errcode,
int errline)
141 assert(errcode != 0);
144 ndbout << *
this << endl;
152 operator<<(NdbOut& out,
const SafeMutex& sm)
154 out << sm.m_name <<
":";
155 out <<
" level=" << sm.m_level;
156 out <<
" usage=" << sm.m_usage;
157 if (sm.m_errcode != 0) {
158 out <<
" errcode=" << sm.m_errcode;
159 out <<
" errline=" << sm.m_errline;
172 sm_thr() : sm_ptr(0),
index(0), loops(0),
limit(0),
id(0) {}
176 extern "C" {
static void* sm_run(
void* arg); }
181 sm_thr&
thr = *(sm_thr*)arg;
182 assert(thr.sm_ptr != 0);
187 for (i = 0; i < thr.loops; i++) {
189 uint sel = uint(random()) % 10;
193 }
else if (level == thr.limit) {
196 }
else if (dir == +1) {
197 op = sel != 0 ? +1 : -1;
198 }
else if (dir == -1) {
199 op = sel != 0 ? -1 : +1;
204 assert(level < thr.limit);
209 }
else if (op == -1) {
211 int ret = sm.unlock();
220 int ret = sm.unlock();
228 main(
int argc,
char** argv)
230 const uint max_thr = 128;
231 struct sm_thr thr[max_thr];
234 uint num_thr = argc > 1 ? atoi(argv[1]) : 4;
235 assert(num_thr != 0 && num_thr <= max_thr);
236 uint loops = argc > 2 ? atoi(argv[2]) : 1000000;
237 uint
limit = argc > 3 ? atoi(argv[3]) : 10;
239 bool debug = argc > 4 ? atoi(argv[4]) : true;
241 ndbout <<
"threads=" << num_thr;
242 ndbout <<
" loops=" << loops;
243 ndbout <<
" max level=" << limit << endl;
245 SafeMutex sm(
"test-mutex", limit, debug);
251 for (i = 0; i < num_thr; i++) {
254 thr[
i].loops = loops;
256 pthread_create(&thr[i].
id, 0, &sm_run, &thr[i]);
257 ndbout <<
"create " << i <<
" id=" << thr[
i].id << endl;
259 for (i = 0; i < num_thr; i++) {
261 pthread_join(thr[i].
id, &value);
262 ndbout <<
"join " << i <<
" id=" << thr[
i].id << endl;