00001 #ifndef PLATFORM_APERIOS
00002 #include "Thread.h"
00003 #include "Shared/ReferenceCounter.h"
00004 #include "ProcessID.h"
00005
00006 #include <pthread.h>
00007 #include <string.h>
00008 #include <iostream>
00009 #include <signal.h>
00010 #include <unistd.h>
00011 #include <cassert>
00012 #include <errno.h>
00013 #ifdef __APPLE__
00014 # include <AvailabilityMacros.h>
00015 #endif
00016
00017 using namespace std;
00018
00019 #define THREADCANCEL_SANITY_CHECKS
00020
00021
00022
00023 struct Threadstorage_t {
00024
00025 Threadstorage_t() : threadInfo() {}
00026
00027
00028 pthread_t threadInfo;
00029
00030
00031 static pthread_key_t selfKey;
00032 private:
00033 Threadstorage_t(const Threadstorage_t& r);
00034 Threadstorage_t& operator=(const Threadstorage_t& r);
00035 };
00036 pthread_key_t Threadstorage_t::selfKey=0;
00037
00038
00039 Thread::Thread()
00040 : pt(new Threadstorage_t), started(false), running(false), returnValue(NULL),
00041 noCancelDepth(0), cancelOrig(PTHREAD_CANCEL_ENABLE), group(NULL)
00042 {
00043 Thread* cur=getCurrent();
00044 if(cur!=NULL)
00045 group=cur->getGroup();
00046 }
00047
00048 Thread::~Thread() {
00049
00050 if(started) {
00051 stop();
00052 join();
00053 }
00054
00055
00056
00057
00058 assert(pt!=NULL);
00059 delete pt;
00060 pt=NULL;
00061 }
00062
00063 void Thread::start() {
00064 if(started) {
00065 std::cerr << "Thread::start() -- thread is already started!" << std::endl;
00066 std::cerr << " make another instance if you want to run another copy of this thread" << std::endl;
00067 return;
00068 }
00069 started=true;
00070 if(int err=pthread_create(&pt->threadInfo, NULL, launch, this))
00071 cerr << "Thread start(), pthread_create: " << strerror(err) << endl;
00072 }
00073
00074 void * Thread::run() {
00075 for(;;) {
00076 unsigned int sleeptime=runloop();
00077 if(sleeptime==-1U)
00078 return returnValue;
00079 if(sleeptime>0)
00080 usleep(sleeptime);
00081 testCancel();
00082 }
00083
00084 return returnValue;
00085 }
00086
00087 void Thread::interrupt() {
00088 if(!isRunning())
00089 return;
00090 if(signal(SIGALRM,handleInterrupt)==SIG_ERR)
00091 perror("PollThread::run(): initial signal()");
00092 sendSignal(SIGALRM);
00093 }
00094
00095 void Thread::stop() {
00096 if(!started && !running) {
00097 std::cerr << "Thread::stop() -- thread has not been started!" << std::endl;
00098 return;
00099 }
00100 if(started && !running)
00101 usleep(50000);
00102 if(started && !running)
00103 std::cerr << "Thread::stop(): Waiting for thread launch to complete (stillborn thread?)" << std::endl;
00104 while(started && !running)
00105 usleep(100000);
00106 if(!running)
00107 return;
00108 if(int err=pthread_cancel(pt->threadInfo))
00109 cerr << "Thread cancel(), pthread_cancel("<<pt->threadInfo<<"): " << strerror(err) << endl;
00110 #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
00111
00112
00113
00114
00115
00116
00117
00118 interrupt();
00119 #endif
00120 }
00121
00122 void Thread::kill() {
00123 sendSignal(SIGUSR1);
00124 }
00125
00126 void Thread::murder() {
00127 if(int err=pthread_detach(pt->threadInfo))
00128 cerr << "Thread kill(), thread_detach: " << strerror(err) << endl;
00129 sendSignal(SIGSTOP);
00130 started=running=false;
00131 }
00132
00133 void Thread::sendSignal(int sig) {
00134 if(started && !running)
00135 usleep(50000);
00136 if(started && !running)
00137 std::cerr << "Thread::stop(): Waiting for thread launch to complete (stillborn thread?)" << std::endl;
00138 while(started && !running)
00139 usleep(100000);
00140 if(!isRunning())
00141 return;
00142 if(int err=pthread_kill(pt->threadInfo,sig))
00143 cerr << "Thread sendSignal(), pthread_kill("<<sig<<"): " << strerror(err) << endl;
00144 }
00145
00146 void * Thread::join() {
00147 void * ans=NULL;
00148 if(int err=pthread_join(pt->threadInfo, &ans))
00149 cerr << "Thread join(), pthread_join: " << strerror(err) << endl;
00150 return ans;
00151 }
00152
00153 Thread* Thread::getCurrent() {
00154 if(Threadstorage_t::selfKey==0) {
00155 static bool gaveError=false;
00156 if(!gaveError) {
00157 cerr << "ERROR: In Thread::getCurrent(), selfKey uninitialized; Thread::initMainThread was not called." << endl;
00158 cerr << " (This error will only be displayed once)" << endl;
00159 gaveError=true;
00160 }
00161 return NULL;
00162 }
00163 return static_cast< Thread* >(pthread_getspecific(Threadstorage_t::selfKey));
00164 }
00165
00166 void Thread::initMainThread() {
00167 if(int err=pthread_key_create(&Threadstorage_t::selfKey,warnSelfUndestructed))
00168 cerr << "WARNING: In Thread::initMainThread(), pthread_key_create(selfKey) returned " << strerror(err) << endl;
00169 if(int err=pthread_setspecific(Threadstorage_t::selfKey,NULL))
00170 cerr << "WARNING: In Thread::initMainThread(), pthread_setspecific(selfKey) returned " << strerror(err) << endl;
00171 }
00172
00173 void Thread::releaseMainThread() {
00174
00175 if(int err=pthread_key_delete(Threadstorage_t::selfKey))
00176 cerr << "WARNING: In Thread::releaseMainThread, pthread_key_delete(selfKey) returned " << strerror(err) << endl;
00177 }
00178
00179 void Thread::testCancel() {
00180 #ifdef DEBUG
00181 if(noCancelDepth!=0) {
00182 cerr << "WARNING: Thread::testCancel called with noCancelDepth=="<<noCancelDepth<<" (process="<<ProcessID::getID()<<", thread="<<pthread_self()<<")"<<endl;
00183 }
00184 #endif
00185 pthread_testcancel();
00186 }
00187
00188 void * Thread::launch(void * msg) {
00189
00190 Thread* cur=static_cast<Thread*>(msg);
00191 if(cur==NULL) {
00192 cerr << "ERROR: Thread::launch with NULL msg" << endl;
00193 return NULL;
00194 }
00195
00196 if(int err=pthread_setspecific(Threadstorage_t::selfKey,msg))
00197 cerr << "WARNING: In ThreadNS::launch(), pthread_setspecific(selfKey) returned " << strerror(err) << endl;
00198
00199
00200 if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL))
00201 cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00202 ++(cur->noCancelDepth);
00203 if(signal(SIGUSR1,Thread::handle_launch_signal)==SIG_ERR)
00204 perror("Thread launch(), signal(SIGUSR1,handle_launch_signal)");
00205 cur->running=true;
00206 if(!cur->launched()) {
00207
00208 --(cur->noCancelDepth);
00209 handle_exit(NULL);
00210 return cur->returnValue;
00211 }
00212 --(cur->noCancelDepth);
00213
00214
00215
00216 pthread_cleanup_push(Thread::handle_exit,msg); {
00217
00218 if(signal(SIGUSR1,Thread::handle_signal)==SIG_ERR)
00219 perror("Thread launch(), signal(SIGUSR1,handle_signal)");
00220
00221 if(cur->noCancelDepth==0) {
00222
00223 if(int err=pthread_setcancelstate(cur->cancelOrig,NULL))
00224 cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00225 if(int err=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL))
00226 cerr << "Thread launch(), pthread_setcanceltype: " << strerror(err) << endl;
00227 }
00228 cur->returnValue=cur->run();
00229
00230 } pthread_cleanup_pop(true);
00231 return cur->returnValue;
00232 }
00233
00234 void Thread::handle_launch_signal(int ) {
00235 handle_exit(NULL);
00236 pthread_exit(NULL);
00237 }
00238
00239 void Thread::handle_signal(int ) {
00240 pthread_exit(NULL);
00241 }
00242
00243 void Thread::handle_exit(void * th) {
00244
00245 Thread* cur=getCurrent();
00246 if(cur==NULL) {
00247 cerr << "ERROR: handle_exit called for a NULL thread" << endl;
00248 if(th!=NULL) {
00249 static_cast<Thread*>(th)->cancelled();
00250 static_cast<Thread*>(th)->started=static_cast<Thread*>(th)->running=false;
00251 }
00252 return;
00253 }
00254
00255 if(th!=NULL && th!=cur)
00256 cerr << "WARNING: handle_exit argument does not match selfKey" << endl;
00257 if(cur->noCancelDepth!=0) {
00258 cerr << "WARNING: thread " << pthread_self() << " of ProcessID_t " << ProcessID::getID() << " exited while noCancelDepth>0 (was " << cur->noCancelDepth << ")" << endl;
00259 cerr << " This may indicate a mutex was left locked." << endl;
00260 }
00261 if(int err=pthread_setspecific(Threadstorage_t::selfKey,NULL))
00262 cerr << "WARNING: In Thread::handle_exit(), pthread_setspecific(selfKey) returned " << err << endl;
00263 cur->cancelled();
00264 cur->started=cur->running=false;
00265 }
00266
00267 void Thread::pushNoCancel() {
00268 Thread * cur=getCurrent();
00269 if(cur==NULL) {
00270
00271
00272 if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL))
00273 cerr << "ERROR: Thread pushNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00274 } else {
00275 ++(cur->noCancelDepth);
00276 int previous=-1;
00277 if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&previous))
00278 cerr << "ERROR: Thread pushNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00279 #ifdef THREADCANCEL_SANITY_CHECKS
00280 if(cur->noCancelDepth==1 && previous!=cur->cancelOrig)
00281 cerr << "WARNING: In Thread::pushNoCancel, cancel state was wrong (was " << previous << ", expected " << cur->cancelOrig << ")" << endl;
00282 else if(cur->noCancelDepth!=1 && previous!=PTHREAD_CANCEL_DISABLE)
00283 cerr << "WARNING: In Thread::pushNoCancel, cancel state was somehow re-enabled" << endl;
00284 #endif
00285 }
00286 }
00287 void Thread::popNoCancel() {
00288 Thread * cur=getCurrent();
00289 if(cur==NULL) {
00290
00291
00292 return;
00293 } else if(cur->noCancelDepth==0) {
00294 cerr << "ERROR: Thread::popNoCancel underflow" << endl;
00295 } else
00296 --(cur->noCancelDepth);
00297 int previous=-1;
00298 if(cur->noCancelDepth==0) {
00299 if(int err=pthread_setcancelstate(cur->cancelOrig,&previous))
00300 cerr << "ERROR: Thread popNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00301 }
00302 #ifdef THREADCANCEL_SANITY_CHECKS
00303 else {
00304 if(int err=pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,&previous))
00305 cerr << "ERROR: Thread popNoCancel(), pthread_setcanceltype: " << strerror(err) << endl;
00306 }
00307 if(previous!=PTHREAD_CANCEL_DISABLE)
00308 cerr << "WARNING: In Thread::popNoCancel, cancel state was somehow re-enabled" << endl;
00309 #endif
00310 }
00311
00312 void Thread::handleInterrupt(int ) {
00313
00314
00315 Thread * cur=Thread::getCurrent();
00316 if(cur==NULL) {
00317 std::cerr << "Thread::handleInterrupt called from non-Thread" << endl;
00318 return;
00319 }
00320 if(cur->noCancelDepth==0)
00321 cur->testCancel();
00322 cur->interrupted();
00323 }
00324
00325 void Thread::warnSelfUndestructed(void* msg) {
00326 cerr << "ERROR: Thread local data (selfKey) not deleted by Thread::handle_exit" << endl;
00327 Thread* cur = getCurrent();
00328 if(cur!=NULL)
00329 cerr << " Weird, key wasn't cleared... (" << cur << ") " << cur->noCancelDepth << " locks on stack? " << endl;;
00330 if(msg==NULL) {
00331 cerr << " Message is null, warnCancelDepthUndestructed shouldn't have been called." << endl;
00332 } else {
00333 if(cur!=NULL && cur!=msg)
00334 cerr << " and current thread does not match msg (" << cur << " vs " << msg << ")" << endl;
00335 cur = static_cast<Thread*>(msg);
00336 }
00337 if(cur!=NULL) {
00338
00339 if(cur->noCancelDepth==0) {
00340 cerr << " But at least the depth is 0" << endl;
00341 } else {
00342 cerr << " The depth indicates there may be " << cur->noCancelDepth << " locks left in place" << endl;
00343 }
00344 cur->cancelled();
00345 cur->started=cur->running=false;
00346 pthread_setspecific(Threadstorage_t::selfKey,NULL);
00347 }
00348 }
00349
00350
00351 namespace ThreadNS {
00352
00353
00354
00355 class Lock::LockStorage : public ReferenceCounter {
00356 friend class Condition;
00357 public:
00358
00359 LockStorage() : ReferenceCounter(), locklevel(0), mutex(), attr(), threadkey() {
00360 AddReference();
00361 pthread_mutexattr_init(&attr);
00362 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
00363 pthread_mutex_init(&mutex,&attr);
00364 }
00365
00366 ~LockStorage() {
00367 pthread_mutexattr_destroy(&attr);
00368 pthread_mutex_destroy(&mutex);
00369 if(locklevel>1)
00370 cerr << "WARNING: lockstorage destructed with " << locklevel << " locks still in effect" << endl;
00371 while(locklevel>0) {
00372 locklevel--;
00373 Thread::popNoCancel();
00374 }
00375 }
00376
00377 LockStorage(const LockStorage& ls) : ReferenceCounter(ls), locklevel(ls.locklevel), mutex(ls.mutex), attr(ls.attr), threadkey(ls.threadkey) {}
00378
00379 LockStorage& operator=(const LockStorage& ls) { ReferenceCounter::operator=(ls); locklevel=ls.locklevel; mutex=ls.mutex; attr=ls.attr; threadkey=ls.threadkey; return *this; }
00380
00381
00382 void lock() {
00383 Thread::pushNoCancel();
00384 if(int err=pthread_mutex_lock(&mutex)) {
00385 cerr << "ERROR: ThreadNS::Lock::lock() failed: " << strerror(err) << endl;
00386 Thread::popNoCancel();
00387 } else
00388 locklevel++;
00389 }
00390
00391 bool trylock() {
00392 Thread::pushNoCancel();
00393 if(!pthread_mutex_trylock(&mutex)) {
00394 locklevel++;
00395 return true;
00396 } else {
00397 Thread::popNoCancel();
00398 return false;
00399 }
00400 }
00401
00402 void unlock() {
00403 if(locklevel==0)
00404 cerr << "ERROR: ThreadNS::Lock::unlock() underflow" << endl;
00405 locklevel--;
00406 if(int err=pthread_mutex_unlock(&mutex))
00407 cerr << "ERROR: ThreadNS::Lock::unlock() failed: " << strerror(err) << endl;
00408 Thread::popNoCancel();
00409 }
00410
00411 unsigned int getLockLevel() { return locklevel; }
00412
00413 protected:
00414 unsigned int locklevel;
00415 pthread_mutex_t mutex;
00416 pthread_mutexattr_t attr;
00417 pthread_key_t threadkey;
00418 };
00419
00420 Lock::LockStorage* Lock::glock=NULL;
00421
00422
00423 Lock::Lock() : mylock(new LockStorage), locklevel(0) {
00424 if(glock==NULL)
00425 setup();
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 Lock::~Lock() {
00458 glock->lock();
00459 if(locklevel>1)
00460 cerr << "WARNING: ThreadNS::Lock destructed with "<<locklevel<<" locks still in effect" << endl;
00461 if(!mylock->RemoveReference())
00462 while(locklevel>0)
00463 unlock();
00464 glock->unlock();
00465 }
00466
00467 void Lock::lock() {
00468 mylock->lock();
00469 locklevel++;
00470 }
00471 bool Lock::trylock() {
00472 if(mylock->trylock()) {
00473 locklevel++;
00474 return true;
00475 } else {
00476 return false;
00477 }
00478 }
00479 void Lock::unlock() {
00480 locklevel--;
00481 mylock->unlock();
00482 }
00483 unsigned int Lock::getLockLevel() const {
00484 return mylock->getLockLevel();
00485 }
00486 void Lock::setup() {
00487 if(glock==NULL)
00488 glock=new LockStorage;
00489 }
00490
00491
00492
00493
00494 class Condition::ConditionStorage {
00495 public:
00496
00497 ConditionStorage() : cond() {
00498 if(int err=pthread_cond_init(&cond,NULL)) {
00499 cerr << "ERROR: ThreadNS::Condition::ConditionStorage() failed: " << strerror(err) << endl;
00500 }
00501 }
00502
00503 ~ConditionStorage() {
00504 if(int err=pthread_cond_destroy(&cond)) {
00505 cerr << "ERROR: ThreadNS::Condition::~ConditionStorage() failed: " << strerror(err) << endl;
00506 }
00507 }
00508
00509 pthread_cond_t cond;
00510 };
00511
00512
00513 Condition::Condition() : mycond(new ConditionStorage) {}
00514 Condition::~Condition() { delete mycond; mycond=NULL; }
00515
00516 void Condition::broadcast() const {
00517 if(int err=pthread_cond_broadcast(&mycond->cond)) {
00518 cerr << "ERROR: ThreadNS::Condition::broadcast() failed: " << strerror(err) << endl;
00519 }
00520 }
00521 void Condition::signal() const {
00522 if(int err=pthread_cond_signal(&mycond->cond)) {
00523 cerr << "ERROR: ThreadNS::Condition::signal() failed: " << strerror(err) << endl;
00524 }
00525 }
00526 bool Condition::timedwait(Lock& l, const timespec* abstime) const {
00527 if(int err=pthread_cond_timedwait(&mycond->cond,&l.mylock->mutex,abstime)) {
00528 if(err!=ETIMEDOUT)
00529 cerr << "ERROR: ThreadNS::Condition::timedwait() failed: " << strerror(err) << endl;
00530 return false;
00531 }
00532 return true;
00533 }
00534 void Condition::wait(Lock& l) const {
00535 if(int err=pthread_cond_wait(&mycond->cond,&l.mylock->mutex)) {
00536 cerr << "ERROR: ThreadNS::Condition::wait() failed: " << strerror(err) << endl;
00537 }
00538 }
00539
00540 }
00541
00542 #endif // PLATFORM check
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553