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;