00001
00002 #include "OVR_Threads.h"
00003 #include "OVR_Hash.h"
00004
00005 #ifdef OVR_ENABLE_THREADS
00006
00007 #include "OVR_Timer.h"
00008 #include "OVR_Log.h"
00009
00010 #include <pthread.h>
00011 #include <time.h>
00012
00013 #ifdef OVR_OS_PS3
00014 #include <sys/sys_time.h>
00015 #include <sys/timer.h>
00016 #include <sys/synchronization.h>
00017 #define sleep(x) sys_timer_sleep(x)
00018 #define usleep(x) sys_timer_usleep(x)
00019 using std::timespec;
00020 #else
00021 #include <unistd.h>
00022 #include <sys/time.h>
00023 #include <errno.h>
00024 #endif
00025
00026 namespace OVR {
00027
00028
00029
00030
00031
00032
00033 class MutexImpl : public NewOverrideBase
00034 {
00035
00036 pthread_mutex_t SMutex;
00037 bool Recursive;
00038 unsigned LockCount;
00039 pthread_t LockedBy;
00040
00041 friend class WaitConditionImpl;
00042
00043 public:
00044
00045 MutexImpl(Mutex* pmutex, bool recursive = 1);
00046 ~MutexImpl();
00047
00048
00049 void DoLock();
00050 bool TryLock();
00051 void Unlock(Mutex* pmutex);
00052
00053 bool IsLockedByAnotherThread(Mutex* pmutex);
00054 bool IsSignaled() const;
00055 };
00056
00057 pthread_mutexattr_t Lock::RecursiveAttr;
00058 bool Lock::RecursiveAttrInit = 0;
00059
00060
00061 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
00062 {
00063 Recursive = recursive;
00064 LockCount = 0;
00065
00066 if (Recursive)
00067 {
00068 if (!Lock::RecursiveAttrInit)
00069 {
00070 pthread_mutexattr_init(&Lock::RecursiveAttr);
00071 pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
00072 Lock::RecursiveAttrInit = 1;
00073 }
00074
00075 pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
00076 }
00077 else
00078 pthread_mutex_init(&SMutex, 0);
00079 }
00080
00081 MutexImpl::~MutexImpl()
00082 {
00083 pthread_mutex_destroy(&SMutex);
00084 }
00085
00086
00087
00088 void MutexImpl::DoLock()
00089 {
00090 while (pthread_mutex_lock(&SMutex));
00091 LockCount++;
00092 LockedBy = pthread_self();
00093 }
00094
00095 bool MutexImpl::TryLock()
00096 {
00097 if (!pthread_mutex_trylock(&SMutex))
00098 {
00099 LockCount++;
00100 LockedBy = pthread_self();
00101 return 1;
00102 }
00103
00104 return 0;
00105 }
00106
00107 void MutexImpl::Unlock(Mutex* pmutex)
00108 {
00109 OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
00110
00111 unsigned lockCount;
00112 LockCount--;
00113 lockCount = LockCount;
00114
00115 pthread_mutex_unlock(&SMutex);
00116 }
00117
00118 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
00119 {
00120
00121 if (LockCount == 0)
00122 return 0;
00123 if (pthread_self() != LockedBy)
00124 return 1;
00125 return 0;
00126 }
00127
00128 bool MutexImpl::IsSignaled() const
00129 {
00130
00131
00132
00133 return LockCount == 0;
00134 }
00135
00136
00137
00138
00139 Mutex::Mutex(bool recursive)
00140 {
00141
00142 pImpl = new MutexImpl(this, recursive);
00143 }
00144
00145 Mutex::~Mutex()
00146 {
00147 delete pImpl;
00148 }
00149
00150
00151 void Mutex::DoLock()
00152 {
00153 pImpl->DoLock();
00154 }
00155 bool Mutex::TryLock()
00156 {
00157 return pImpl->TryLock();
00158 }
00159 void Mutex::Unlock()
00160 {
00161 pImpl->Unlock(this);
00162 }
00163 bool Mutex::IsLockedByAnotherThread()
00164 {
00165 return pImpl->IsLockedByAnotherThread(this);
00166 }
00167
00168
00169
00170
00171
00172
00173 bool Event::Wait(unsigned delay)
00174 {
00175 Mutex::Locker lock(&StateMutex);
00176
00177
00178 if (delay == OVR_WAIT_INFINITE)
00179 {
00180 while(!State)
00181 StateWaitCondition.Wait(&StateMutex);
00182 }
00183 else if (delay)
00184 {
00185 if (!State)
00186 StateWaitCondition.Wait(&StateMutex, delay);
00187 }
00188
00189 bool state = State;
00190
00191 if (Temporary)
00192 {
00193 Temporary = false;
00194 State = false;
00195 }
00196 return state;
00197 }
00198
00199 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
00200 {
00201 Mutex::Locker lock(&StateMutex);
00202 State = newState;
00203 Temporary = newTemp;
00204 if (mustNotify)
00205 StateWaitCondition.NotifyAll();
00206 }
00207
00208
00209
00210
00211
00212
00213 class WaitConditionImpl : public NewOverrideBase
00214 {
00215 pthread_mutex_t SMutex;
00216 pthread_cond_t Condv;
00217
00218 public:
00219
00220
00221 WaitConditionImpl();
00222 ~WaitConditionImpl();
00223
00224
00225 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
00226
00227
00228 void Notify();
00229
00230 void NotifyAll();
00231 };
00232
00233
00234 WaitConditionImpl::WaitConditionImpl()
00235 {
00236 pthread_mutex_init(&SMutex, 0);
00237 pthread_cond_init(&Condv, 0);
00238 }
00239
00240 WaitConditionImpl::~WaitConditionImpl()
00241 {
00242 pthread_mutex_destroy(&SMutex);
00243 pthread_cond_destroy(&Condv);
00244 }
00245
00246 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
00247 {
00248 bool result = 1;
00249 unsigned lockCount = pmutex->pImpl->LockCount;
00250
00251
00252 if (lockCount == 0)
00253 return 0;
00254
00255 pthread_mutex_lock(&SMutex);
00256
00257
00258 if (pmutex->pImpl->Recursive)
00259 {
00260
00261 pmutex->pImpl->LockCount = 0;
00262 for(unsigned i=0; i<lockCount; i++)
00263 pthread_mutex_unlock(&pmutex->pImpl->SMutex);
00264 }
00265 else
00266 {
00267 pmutex->pImpl->LockCount = 0;
00268 pthread_mutex_unlock(&pmutex->pImpl->SMutex);
00269 }
00270
00271
00272
00273
00274 if (delay == OVR_WAIT_INFINITE)
00275 pthread_cond_wait(&Condv,&SMutex);
00276 else
00277 {
00278 timespec ts;
00279 #ifdef OVR_OS_PS3
00280 sys_time_sec_t s;
00281 sys_time_nsec_t ns;
00282 sys_time_get_current_time(&s, &ns);
00283
00284 ts.tv_sec = s + (delay / 1000);
00285 ts.tv_nsec = ns + (delay % 1000) * 1000000;
00286
00287 #else
00288 struct timeval tv;
00289 gettimeofday(&tv, 0);
00290
00291 ts.tv_sec = tv.tv_sec + (delay / 1000);
00292 ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
00293 #endif
00294 if (ts.tv_nsec > 999999999)
00295 {
00296 ts.tv_sec++;
00297 ts.tv_nsec -= 1000000000;
00298 }
00299 int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
00300 OVR_ASSERT(r == 0 || r == ETIMEDOUT);
00301 if (r)
00302 result = 0;
00303 }
00304
00305 pthread_mutex_unlock(&SMutex);
00306
00307
00308 for(unsigned i=0; i<lockCount; i++)
00309 pmutex->DoLock();
00310
00311
00312 return result;
00313 }
00314
00315
00316 void WaitConditionImpl::Notify()
00317 {
00318 pthread_mutex_lock(&SMutex);
00319 pthread_cond_signal(&Condv);
00320 pthread_mutex_unlock(&SMutex);
00321 }
00322
00323
00324 void WaitConditionImpl::NotifyAll()
00325 {
00326 pthread_mutex_lock(&SMutex);
00327 pthread_cond_broadcast(&Condv);
00328 pthread_mutex_unlock(&SMutex);
00329 }
00330
00331
00332
00333
00334
00335 WaitCondition::WaitCondition()
00336 {
00337 pImpl = new WaitConditionImpl;
00338 }
00339 WaitCondition::~WaitCondition()
00340 {
00341 delete pImpl;
00342 }
00343
00344 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay)
00345 {
00346 return pImpl->Wait(pmutex, delay);
00347 }
00348
00349 void WaitCondition::Notify()
00350 {
00351 pImpl->Notify();
00352 }
00353 void WaitCondition::NotifyAll()
00354 {
00355 pImpl->NotifyAll();
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 Thread::Thread(UPInt stackSize, int processor)
00382 {
00383
00384 CreateParams params;
00385 params.stackSize = stackSize;
00386 params.processor = processor;
00387 Init(params);
00388 }
00389
00390 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
00391 int processor, Thread::ThreadState initialState)
00392 {
00393 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
00394 Init(params);
00395 }
00396
00397 Thread::Thread(const CreateParams& params)
00398 {
00399 Init(params);
00400 }
00401
00402 void Thread::Init(const CreateParams& params)
00403 {
00404
00405 ThreadFlags = 0;
00406 ThreadHandle = 0;
00407 ExitCode = 0;
00408 SuspendCount = 0;
00409 StackSize = params.stackSize;
00410 Processor = params.processor;
00411 Priority = params.priority;
00412
00413
00414 ThreadFunction = params.threadFunction;
00415 UserHandle = params.userHandle;
00416 if (params.initialState != NotRunning)
00417 Start(params.initialState);
00418 }
00419
00420 Thread::~Thread()
00421 {
00422
00423
00424
00425
00426
00427 ThreadHandle = 0;
00428 }
00429
00430
00431
00432
00433
00434
00435 int Thread::Run()
00436 {
00437
00438 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
00439 }
00440 void Thread::OnExit()
00441 {
00442 }
00443
00444
00445
00446 void Thread::FinishAndRelease()
00447 {
00448
00449 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
00450 ThreadFlags |= OVR_THREAD_FINISHED;
00451
00452
00453
00454 Release();
00455 }
00456
00457
00458
00459
00460
00461 class ThreadList : public NewOverrideBase
00462 {
00463
00464 struct ThreadHashOp
00465 {
00466 size_t operator()(const Thread* ptr)
00467 {
00468 return (((size_t)ptr) >> 6) ^ (size_t)ptr;
00469 }
00470 };
00471
00472 HashSet<Thread*, ThreadHashOp> ThreadSet;
00473 Mutex ThreadMutex;
00474 WaitCondition ThreadsEmpty;
00475
00476 pthread_t RootThreadId;
00477
00478 static ThreadList* volatile pRunningThreads;
00479
00480 void addThread(Thread *pthread)
00481 {
00482 Mutex::Locker lock(&ThreadMutex);
00483 ThreadSet.Add(pthread);
00484 }
00485
00486 void removeThread(Thread *pthread)
00487 {
00488 Mutex::Locker lock(&ThreadMutex);
00489 ThreadSet.Remove(pthread);
00490 if (ThreadSet.GetSize() == 0)
00491 ThreadsEmpty.Notify();
00492 }
00493
00494 void finishAllThreads()
00495 {
00496
00497 OVR_ASSERT(pthread_self() == RootThreadId);
00498
00499 Mutex::Locker lock(&ThreadMutex);
00500 while (ThreadSet.GetSize() != 0)
00501 ThreadsEmpty.Wait(&ThreadMutex);
00502 }
00503
00504 public:
00505
00506 ThreadList()
00507 {
00508 RootThreadId = pthread_self();
00509 }
00510 ~ThreadList() { }
00511
00512
00513 static void AddRunningThread(Thread *pthread)
00514 {
00515
00516 if (!pRunningThreads)
00517 {
00518 pRunningThreads = new ThreadList;
00519 OVR_ASSERT(pRunningThreads);
00520 }
00521 pRunningThreads->addThread(pthread);
00522 }
00523
00524
00525
00526
00527 static void RemoveRunningThread(Thread *pthread)
00528 {
00529 OVR_ASSERT(pRunningThreads);
00530 pRunningThreads->removeThread(pthread);
00531 }
00532
00533 static void FinishAllThreads()
00534 {
00535
00536 if (pRunningThreads)
00537 {
00538 pRunningThreads->finishAllThreads();
00539 delete pRunningThreads;
00540 pRunningThreads = 0;
00541 }
00542 }
00543 };
00544
00545
00546 ThreadList* volatile ThreadList::pRunningThreads = 0;
00547
00548
00549
00550 void Thread::FinishAllThreads()
00551 {
00552 ThreadList::FinishAllThreads();
00553 }
00554
00555
00556
00557 int Thread::PRun()
00558 {
00559
00560 if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
00561 {
00562 Suspend();
00563 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
00564 }
00565
00566
00567 ExitCode = Run();
00568 return ExitCode;
00569 }
00570
00571
00572
00573
00574
00575
00576 bool Thread::GetExitFlag() const
00577 {
00578 return (ThreadFlags & OVR_THREAD_EXIT) != 0;
00579 }
00580
00581 void Thread::SetExitFlag(bool exitFlag)
00582 {
00583
00584 if (exitFlag)
00585 ThreadFlags |= OVR_THREAD_EXIT;
00586 else
00587 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
00588 }
00589
00590
00591
00592 bool Thread::IsFinished() const
00593 {
00594 return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
00595 }
00596
00597 bool Thread::IsSuspended() const
00598 {
00599 return SuspendCount > 0;
00600 }
00601
00602 Thread::ThreadState Thread::GetThreadState() const
00603 {
00604 if (IsSuspended())
00605 return Suspended;
00606 if (ThreadFlags & OVR_THREAD_STARTED)
00607 return Running;
00608 return NotRunning;
00609 }
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 void* Thread_PthreadStartFn(void* phandle)
00637 {
00638 Thread* pthread = (Thread*)phandle;
00639 int result = pthread->PRun();
00640
00641 pthread->FinishAndRelease();
00642
00643
00644 ThreadList::RemoveRunningThread(pthread);
00645 return (void*) result;
00646 }
00647
00648 int Thread::InitAttr = 0;
00649 pthread_attr_t Thread::Attr;
00650
00651
00652 int Thread::GetOSPriority(ThreadPriority p)
00653
00654 {
00655 #ifdef OVR_OS_PS3
00656 switch(p)
00657 {
00658 case Thread::CriticalPriority: return 0;
00659 case Thread::HighestPriority: return 300;
00660 case Thread::AboveNormalPriority: return 600;
00661 case Thread::NormalPriority: return 1000;
00662 case Thread::BelowNormalPriority: return 1500;
00663 case Thread::LowestPriority: return 2500;
00664 case Thread::IdlePriority: return 3071;
00665 } return 1000;
00666 #else
00667 OVR_UNUSED(p);
00668 return -1;
00669 #endif
00670 }
00671
00672 bool Thread::Start(ThreadState initialState)
00673 {
00674 if (initialState == NotRunning)
00675 return 0;
00676 if (GetThreadState() != NotRunning)
00677 {
00678 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
00679 return 0;
00680 }
00681
00682 if (!InitAttr)
00683 {
00684 pthread_attr_init(&Attr);
00685 pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
00686 pthread_attr_setstacksize(&Attr, 128 * 1024);
00687 sched_param sparam;
00688 sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
00689 pthread_attr_setschedparam(&Attr, &sparam);
00690 InitAttr = 1;
00691 }
00692
00693 ExitCode = 0;
00694 SuspendCount = 0;
00695 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
00696
00697
00698 AddRef();
00699 ThreadList::AddRunningThread(this);
00700
00701 int result;
00702 if (StackSize != 128 * 1024 || Priority != NormalPriority)
00703 {
00704 pthread_attr_t attr;
00705
00706 pthread_attr_init(&attr);
00707 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00708 pthread_attr_setstacksize(&attr, StackSize);
00709 sched_param sparam;
00710 sparam.sched_priority = Thread::GetOSPriority(Priority);
00711 pthread_attr_setschedparam(&attr, &sparam);
00712 result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
00713 pthread_attr_destroy(&attr);
00714 }
00715 else
00716 result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
00717
00718 if (result)
00719 {
00720 ThreadFlags = 0;
00721 Release();
00722 ThreadList::RemoveRunningThread(this);
00723 return 0;
00724 }
00725 return 1;
00726 }
00727
00728
00729
00730 bool Thread::Suspend()
00731 {
00732 OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
00733 return 0;
00734 }
00735
00736
00737 bool Thread::Resume()
00738 {
00739 return 0;
00740 }
00741
00742
00743
00744 void Thread::Exit(int exitCode)
00745 {
00746
00747
00748
00749
00750
00751 OnExit();
00752
00753
00754 FinishAndRelease();
00755 ThreadList::RemoveRunningThread(this);
00756
00757 pthread_exit((void *) exitCode);
00758 }
00759
00760 ThreadId GetCurrentThreadId()
00761 {
00762 return (void*)pthread_self();
00763 }
00764
00765
00766
00767
00768 bool Thread::Sleep(unsigned secs)
00769 {
00770 sleep(secs);
00771 return 1;
00772 }
00773
00774 bool Thread::MSleep(unsigned msecs)
00775 {
00776 usleep(msecs*1000);
00777 return 1;
00778 }
00779
00780
00781 int Thread::GetCPUCount()
00782 {
00783 return 1;
00784 }
00785
00786
00787 #ifdef OVR_OS_PS3
00788
00789 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
00790
00791 #endif
00792
00793 }
00794
00795 #endif // OVR_ENABLE_THREADS