00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #include "sync.h"
00037
00038 using namespace zmm;
00039
00040
00041
00042 Mutex::Mutex(bool recursive) : Object()
00043 {
00044 #ifdef TOMBDEBUG
00045 this->recursive = recursive;
00046 lock_level = 0;
00047
00048 int res;
00049 pthread_mutexattr_t mutex_attr;
00050 res = pthread_mutexattr_init(&mutex_attr);
00051 res = pthread_mutexattr_settype(&mutex_attr, (recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_ERRORCHECK));
00052 pthread_mutex_init(&mutex_struct, &mutex_attr);
00053 pthread_mutexattr_destroy(&mutex_attr);
00054 #else
00055 if (recursive)
00056 {
00057 int res;
00058 pthread_mutexattr_t mutex_attr;
00059 res = pthread_mutexattr_init(&mutex_attr);
00060 res = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
00061 pthread_mutex_init(&mutex_struct, &mutex_attr);
00062 pthread_mutexattr_destroy(&mutex_attr);
00063 }
00064 else
00065 pthread_mutex_init(&mutex_struct, NULL);
00066 #endif
00067 }
00068
00069 Mutex::~Mutex()
00070 {
00071 pthread_mutex_destroy(&mutex_struct);
00072 }
00073
00074 #ifdef TOMBDEBUG
00075 void Mutex::lock()
00076 {
00077 pthread_mutex_lock(&mutex_struct);
00078 pthread_t this_thread = pthread_self();
00079 if (lock_level && ! recursive && this_thread == locking_thread)
00080 errorExit(_("same thread tried to lock non-recursive mutex twice"));
00081 doLock(false);
00082 autolock = false;
00083 }
00084
00085 void Mutex::unlock(bool autolock)
00086 {
00087 if (! recursive && autolock != this->autolock)
00088 {
00089 if (autolock)
00090 errorExit(_("unlock() called by autolock, but not locked by getAutolock()?? - seems to be an error in sync.cc..."));
00091 else
00092 errorExit(_("unlock() called, but locked by an getAutolock()!"));
00093 }
00094 pthread_t this_thread = pthread_self();
00095 if (lock_level <= 0)
00096 errorExit(_("tried to unlock not locked mutex"));
00097 if (this_thread != locking_thread)
00098 errorExit(_("a different thread tried to unlock the locked mutex"));
00099 doUnlock(false);
00100 pthread_mutex_unlock(&mutex_struct);
00101 }
00102
00103
00104 void Mutex::errorExit(String error)
00105 {
00106 printf("%s\n", error.c_str());
00107 print_backtrace();
00108 abort();
00109 }
00110
00111 void Mutex::unlockAutolock()
00112 {
00113 unlock(true);
00114 }
00115
00116 void Mutex::doLock(bool cond)
00117 {
00118 lock_level++;
00119 if (! recursive && lock_level > 1)
00120 errorExit(_("managed to lock a non-recursive thread twice? cond: ") + cond);
00121 locking_thread = pthread_self();
00122 }
00123
00124 void Mutex::doUnlock(bool cond)
00125 {
00126 if (cond && recursive && lock_level != 1)
00127 errorExit(_("tried to unlock a recursive mutex via a cond->wait() or cond->timedwait() call, which is locked more than once - is this correct?"));
00128 if (--lock_level < 0)
00129 errorExit(_("unlocked a thread somehow, but it wasn't locked. cond: ") + cond);
00130 }
00131
00132 #endif // TOMBDEBUG
00133
00134
00135
00136 Cond::Cond(Ref<Mutex> mutex) : Object()
00137 {
00138 this->mutex = mutex;
00139 pthread_cond_init(&cond_struct, NULL);
00140 }
00141
00142 Cond::~Cond()
00143 {
00144 pthread_cond_destroy(&cond_struct);
00145 }
00146
00147 #ifdef TOMBDEBUG
00148 void Cond::wait()
00149 {
00150 bool autolock_save = mutex->autolock;
00151 mutex->doUnlock(true);
00152 pthread_cond_wait(&cond_struct, mutex->getMutex());
00153 mutex->doLock(true);
00154 mutex->autolock = autolock_save;
00155 }
00156
00157 int Cond::timedwait(struct timespec *timeout)
00158 {
00159 mutex->doUnlock(true);
00160 int ret = pthread_cond_timedwait(&cond_struct, mutex->getMutex(), timeout);
00161 mutex->doLock(true);
00162 return ret;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 #endif // TOMBDEBUG
00179
00180
00181 MutexAutolock::MutexAutolock(Ref<Mutex> mutex, bool unlocked)
00182 {
00183 this->mutex = mutex;
00184 #ifdef TOMBDEBUG
00185 if (! unlocked)
00186 mutex->lockAutolock();
00187 #else
00188 pmutex = mutex->getMutex();
00189 if (! unlocked)
00190 pthread_mutex_lock(pmutex);
00191 #endif
00192 locked = ! unlocked;
00193 }
00194
00195 #ifdef TOMBDEBUG
00196 MutexAutolock::~MutexAutolock()
00197 {
00198 if (locked)
00199 mutex->unlockAutolock();
00200 }
00201
00202 void MutexAutolock::unlock()
00203 {
00204 if (locked)
00205 mutex->unlockAutolock();
00206 else
00207 mutex->errorExit(_("tried to unlock a not-locked autolock"));
00208 locked = false;
00209 }
00210
00211 void MutexAutolock::relock()
00212 {
00213 if (! locked)
00214 mutex->lockAutolock();
00215 else
00216 mutex->errorExit(_("tried to relock a locked autolock"));
00217 locked = true;
00218 }
00219 #endif