oculus1

diff libovr/Src/osx/OVR_ThreadsPthread.cpp @ 3:b069a5c27388

added a couple more stuff, fixed all the LibOVR line endings
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Sep 2013 04:10:05 +0300
parents e2f9e4603129
children
line diff
     1.1 --- a/libovr/Src/osx/OVR_ThreadsPthread.cpp	Sat Sep 14 17:51:03 2013 +0300
     1.2 +++ b/libovr/Src/osx/OVR_ThreadsPthread.cpp	Sun Sep 15 04:10:05 2013 +0300
     1.3 @@ -1,1 +1,795 @@
     1.4 -
     1.5 #include "OVR_Threads.h"
     1.6 #include "OVR_Hash.h"
     1.7 
     1.8 #ifdef OVR_ENABLE_THREADS
     1.9 
    1.10 #include "OVR_Timer.h"
    1.11 #include "OVR_Log.h"
    1.12 
    1.13 #include <pthread.h>
    1.14 #include <time.h>
    1.15 
    1.16 #ifdef OVR_OS_PS3
    1.17 #include <sys/sys_time.h>
    1.18 #include <sys/timer.h>
    1.19 #include <sys/synchronization.h>
    1.20 #define sleep(x) sys_timer_sleep(x)
    1.21 #define usleep(x) sys_timer_usleep(x)
    1.22 using std::timespec;
    1.23 #else
    1.24 #include <unistd.h>
    1.25 #include <sys/time.h>
    1.26 #include <errno.h>
    1.27 #endif
    1.28 
    1.29 namespace OVR {
    1.30 
    1.31 // ***** Mutex implementation
    1.32 
    1.33 
    1.34 // *** Internal Mutex implementation structure
    1.35 
    1.36 class MutexImpl : public NewOverrideBase
    1.37 {
    1.38     // System mutex or semaphore
    1.39     pthread_mutex_t   SMutex;
    1.40     bool          Recursive;
    1.41     unsigned      LockCount;
    1.42     pthread_t     LockedBy;
    1.43 
    1.44     friend class WaitConditionImpl;
    1.45 
    1.46 public:
    1.47     // Constructor/destructor
    1.48     MutexImpl(Mutex* pmutex, bool recursive = 1);
    1.49     ~MutexImpl();
    1.50 
    1.51     // Locking functions
    1.52     void                DoLock();
    1.53     bool                TryLock();
    1.54     void                Unlock(Mutex* pmutex);
    1.55     // Returns 1 if the mutes is currently locked
    1.56     bool                IsLockedByAnotherThread(Mutex* pmutex);        
    1.57     bool                IsSignaled() const;
    1.58 };
    1.59 
    1.60 pthread_mutexattr_t Lock::RecursiveAttr;
    1.61 bool Lock::RecursiveAttrInit = 0;
    1.62 
    1.63 // *** Constructor/destructor
    1.64 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
    1.65 {   
    1.66     Recursive           = recursive;
    1.67     LockCount           = 0;
    1.68 
    1.69     if (Recursive)
    1.70     {
    1.71         if (!Lock::RecursiveAttrInit)
    1.72         {
    1.73             pthread_mutexattr_init(&Lock::RecursiveAttr);
    1.74             pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
    1.75             Lock::RecursiveAttrInit = 1;
    1.76         }
    1.77 
    1.78         pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
    1.79     }
    1.80     else
    1.81         pthread_mutex_init(&SMutex, 0);
    1.82 }
    1.83 
    1.84 MutexImpl::~MutexImpl()
    1.85 {
    1.86     pthread_mutex_destroy(&SMutex);
    1.87 }
    1.88 
    1.89 
    1.90 // Lock and try lock
    1.91 void MutexImpl::DoLock()
    1.92 {
    1.93     while (pthread_mutex_lock(&SMutex));
    1.94     LockCount++;
    1.95     LockedBy = pthread_self();
    1.96 }
    1.97 
    1.98 bool MutexImpl::TryLock()
    1.99 {
   1.100     if (!pthread_mutex_trylock(&SMutex))
   1.101     {
   1.102         LockCount++;
   1.103         LockedBy = pthread_self();
   1.104         return 1;
   1.105     }
   1.106     
   1.107     return 0;
   1.108 }
   1.109 
   1.110 void MutexImpl::Unlock(Mutex* pmutex)
   1.111 {
   1.112     OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
   1.113 
   1.114     unsigned lockCount;
   1.115     LockCount--;
   1.116     lockCount = LockCount;
   1.117 
   1.118     pthread_mutex_unlock(&SMutex);
   1.119 }
   1.120 
   1.121 bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
   1.122 {
   1.123     // There could be multiple interpretations of IsLocked with respect to current thread
   1.124     if (LockCount == 0)
   1.125         return 0;
   1.126     if (pthread_self() != LockedBy)
   1.127         return 1;
   1.128     return 0;
   1.129 }
   1.130 
   1.131 bool    MutexImpl::IsSignaled() const
   1.132 {
   1.133     // An mutex is signaled if it is not locked ANYWHERE
   1.134     // Note that this is different from IsLockedByAnotherThread function,
   1.135     // that takes current thread into account
   1.136     return LockCount == 0;
   1.137 }
   1.138 
   1.139 
   1.140 // *** Actual Mutex class implementation
   1.141 
   1.142 Mutex::Mutex(bool recursive)
   1.143 {
   1.144     // NOTE: RefCount mode already thread-safe for all waitables.
   1.145     pImpl = new MutexImpl(this, recursive);
   1.146 }
   1.147 
   1.148 Mutex::~Mutex()
   1.149 {
   1.150     delete pImpl;
   1.151 }
   1.152 
   1.153 // Lock and try lock
   1.154 void Mutex::DoLock()
   1.155 {
   1.156     pImpl->DoLock();
   1.157 }
   1.158 bool Mutex::TryLock()
   1.159 {
   1.160     return pImpl->TryLock();
   1.161 }
   1.162 void Mutex::Unlock()
   1.163 {
   1.164     pImpl->Unlock(this);
   1.165 }
   1.166 bool    Mutex::IsLockedByAnotherThread()
   1.167 {
   1.168     return pImpl->IsLockedByAnotherThread(this);
   1.169 }
   1.170 
   1.171 
   1.172 
   1.173 //-----------------------------------------------------------------------------------
   1.174 // ***** Event
   1.175 
   1.176 bool Event::Wait(unsigned delay)
   1.177 {
   1.178     Mutex::Locker lock(&StateMutex);
   1.179 
   1.180     // Do the correct amount of waiting
   1.181     if (delay == OVR_WAIT_INFINITE)
   1.182     {
   1.183         while(!State)
   1.184             StateWaitCondition.Wait(&StateMutex);
   1.185     }
   1.186     else if (delay)
   1.187     {
   1.188         if (!State)
   1.189             StateWaitCondition.Wait(&StateMutex, delay);
   1.190     }
   1.191 
   1.192     bool state = State;
   1.193     // Take care of temporary 'pulsing' of a state
   1.194     if (Temporary)
   1.195     {
   1.196         Temporary   = false;
   1.197         State       = false;
   1.198     }
   1.199     return state;
   1.200 }
   1.201 
   1.202 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
   1.203 {
   1.204     Mutex::Locker lock(&StateMutex);
   1.205     State       = newState;
   1.206     Temporary   = newTemp;
   1.207     if (mustNotify)
   1.208         StateWaitCondition.NotifyAll();    
   1.209 }
   1.210 
   1.211 
   1.212 
   1.213 // ***** Wait Condition Implementation
   1.214 
   1.215 // Internal implementation class
   1.216 class WaitConditionImpl : public NewOverrideBase
   1.217 {
   1.218     pthread_mutex_t     SMutex;
   1.219     pthread_cond_t      Condv;
   1.220 
   1.221 public:
   1.222 
   1.223     // Constructor/destructor
   1.224     WaitConditionImpl();
   1.225     ~WaitConditionImpl();
   1.226 
   1.227     // Release mutex and wait for condition. The mutex is re-aqured after the wait.
   1.228     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
   1.229 
   1.230     // Notify a condition, releasing at one object waiting
   1.231     void    Notify();
   1.232     // Notify a condition, releasing all objects waiting
   1.233     void    NotifyAll();
   1.234 };
   1.235 
   1.236 
   1.237 WaitConditionImpl::WaitConditionImpl()
   1.238 {
   1.239     pthread_mutex_init(&SMutex, 0);
   1.240     pthread_cond_init(&Condv, 0);
   1.241 }
   1.242 
   1.243 WaitConditionImpl::~WaitConditionImpl()
   1.244 {
   1.245     pthread_mutex_destroy(&SMutex);
   1.246     pthread_cond_destroy(&Condv);
   1.247 }    
   1.248 
   1.249 bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
   1.250 {
   1.251     bool            result = 1;
   1.252     unsigned            lockCount = pmutex->pImpl->LockCount;
   1.253 
   1.254     // Mutex must have been locked
   1.255     if (lockCount == 0)
   1.256         return 0;
   1.257 
   1.258     pthread_mutex_lock(&SMutex);
   1.259 
   1.260     // Finally, release a mutex or semaphore
   1.261     if (pmutex->pImpl->Recursive)
   1.262     {
   1.263         // Release the recursive mutex N times
   1.264         pmutex->pImpl->LockCount = 0;
   1.265         for(unsigned i=0; i<lockCount; i++)
   1.266             pthread_mutex_unlock(&pmutex->pImpl->SMutex);
   1.267     }
   1.268     else
   1.269     {
   1.270         pmutex->pImpl->LockCount = 0;
   1.271         pthread_mutex_unlock(&pmutex->pImpl->SMutex);
   1.272     }
   1.273 
   1.274     // Note that there is a gap here between mutex.Unlock() and Wait().
   1.275     // The other mutex protects this gap.
   1.276 
   1.277     if (delay == OVR_WAIT_INFINITE)
   1.278         pthread_cond_wait(&Condv,&SMutex);
   1.279     else
   1.280     {
   1.281         timespec ts;
   1.282 #ifdef OVR_OS_PS3
   1.283         sys_time_sec_t s;
   1.284         sys_time_nsec_t ns;
   1.285         sys_time_get_current_time(&s, &ns);
   1.286 
   1.287         ts.tv_sec = s + (delay / 1000);
   1.288         ts.tv_nsec = ns + (delay % 1000) * 1000000;
   1.289 
   1.290 #else
   1.291         struct timeval tv;
   1.292         gettimeofday(&tv, 0);
   1.293 
   1.294         ts.tv_sec = tv.tv_sec + (delay / 1000);
   1.295         ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
   1.296 #endif
   1.297         if (ts.tv_nsec > 999999999)
   1.298         {
   1.299             ts.tv_sec++;
   1.300             ts.tv_nsec -= 1000000000;
   1.301         }
   1.302         int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
   1.303         OVR_ASSERT(r == 0 || r == ETIMEDOUT);
   1.304         if (r)
   1.305             result = 0;
   1.306     }
   1.307 
   1.308     pthread_mutex_unlock(&SMutex);
   1.309 
   1.310     // Re-aquire the mutex
   1.311     for(unsigned i=0; i<lockCount; i++)
   1.312         pmutex->DoLock(); 
   1.313 
   1.314     // Return the result
   1.315     return result;
   1.316 }
   1.317 
   1.318 // Notify a condition, releasing the least object in a queue
   1.319 void    WaitConditionImpl::Notify()
   1.320 {
   1.321     pthread_mutex_lock(&SMutex);
   1.322     pthread_cond_signal(&Condv);
   1.323     pthread_mutex_unlock(&SMutex);
   1.324 }
   1.325 
   1.326 // Notify a condition, releasing all objects waiting
   1.327 void    WaitConditionImpl::NotifyAll()
   1.328 {
   1.329     pthread_mutex_lock(&SMutex);
   1.330     pthread_cond_broadcast(&Condv);
   1.331     pthread_mutex_unlock(&SMutex);
   1.332 }
   1.333 
   1.334 
   1.335 
   1.336 // *** Actual implementation of WaitCondition
   1.337 
   1.338 WaitCondition::WaitCondition()
   1.339 {
   1.340     pImpl = new WaitConditionImpl;
   1.341 }
   1.342 WaitCondition::~WaitCondition()
   1.343 {
   1.344     delete pImpl;
   1.345 }
   1.346     
   1.347 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
   1.348 {
   1.349     return pImpl->Wait(pmutex, delay);
   1.350 }
   1.351 // Notification
   1.352 void    WaitCondition::Notify()
   1.353 {
   1.354     pImpl->Notify();
   1.355 }
   1.356 void    WaitCondition::NotifyAll()
   1.357 {
   1.358     pImpl->NotifyAll();
   1.359 }
   1.360 
   1.361 
   1.362 // ***** Current thread
   1.363 
   1.364 // Per-thread variable
   1.365 /*
   1.366 static __thread Thread* pCurrentThread = 0;
   1.367 
   1.368 // Static function to return a pointer to the current thread
   1.369 void    Thread::InitCurrentThread(Thread *pthread)
   1.370 {
   1.371     pCurrentThread = pthread;
   1.372 }
   1.373 
   1.374 // Static function to return a pointer to the current thread
   1.375 Thread*    Thread::GetThread()
   1.376 {
   1.377     return pCurrentThread;
   1.378 }
   1.379 */
   1.380 
   1.381 
   1.382 // *** Thread constructors.
   1.383 
   1.384 Thread::Thread(UPInt stackSize, int processor)
   1.385 {
   1.386     // NOTE: RefCount mode already thread-safe for all Waitable objects.
   1.387     CreateParams params;
   1.388     params.stackSize = stackSize;
   1.389     params.processor = processor;
   1.390     Init(params);
   1.391 }
   1.392 
   1.393 Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
   1.394                  int processor, Thread::ThreadState initialState)
   1.395 {
   1.396     CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
   1.397     Init(params);
   1.398 }
   1.399 
   1.400 Thread::Thread(const CreateParams& params)
   1.401 {
   1.402     Init(params);
   1.403 }
   1.404 
   1.405 void Thread::Init(const CreateParams& params)
   1.406 {
   1.407     // Clear the variables    
   1.408     ThreadFlags     = 0;
   1.409     ThreadHandle    = 0;
   1.410     ExitCode        = 0;
   1.411     SuspendCount    = 0;
   1.412     StackSize       = params.stackSize;
   1.413     Processor       = params.processor;
   1.414     Priority        = params.priority;
   1.415 
   1.416     // Clear Function pointers
   1.417     ThreadFunction  = params.threadFunction;
   1.418     UserHandle      = params.userHandle;
   1.419     if (params.initialState != NotRunning)
   1.420         Start(params.initialState);
   1.421 }
   1.422 
   1.423 Thread::~Thread()
   1.424 {
   1.425     // Thread should not running while object is being destroyed,
   1.426     // this would indicate ref-counting issue.
   1.427     //OVR_ASSERT(IsRunning() == 0);
   1.428 
   1.429     // Clean up thread.    
   1.430     ThreadHandle = 0;
   1.431 }
   1.432 
   1.433 
   1.434 
   1.435 // *** Overridable User functions.
   1.436 
   1.437 // Default Run implementation
   1.438 int    Thread::Run()
   1.439 {
   1.440     // Call pointer to function, if available.    
   1.441     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
   1.442 }
   1.443 void    Thread::OnExit()
   1.444 {   
   1.445 }
   1.446 
   1.447 
   1.448 // Finishes the thread and releases internal reference to it.
   1.449 void    Thread::FinishAndRelease()
   1.450 {
   1.451     // Note: thread must be US.
   1.452     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
   1.453     ThreadFlags |= OVR_THREAD_FINISHED;
   1.454 
   1.455     // Release our reference; this is equivalent to 'delete this'
   1.456     // from the point of view of our thread.
   1.457     Release();
   1.458 }
   1.459 
   1.460 
   1.461 
   1.462 // *** ThreadList - used to track all created threads
   1.463 
   1.464 class ThreadList : public NewOverrideBase
   1.465 {
   1.466     //------------------------------------------------------------------------
   1.467     struct ThreadHashOp
   1.468     {
   1.469         size_t operator()(const Thread* ptr)
   1.470         {
   1.471             return (((size_t)ptr) >> 6) ^ (size_t)ptr;
   1.472         }
   1.473     };
   1.474 
   1.475     HashSet<Thread*, ThreadHashOp>        ThreadSet;
   1.476     Mutex                                 ThreadMutex;
   1.477     WaitCondition                         ThreadsEmpty;
   1.478     // Track the root thread that created us.
   1.479     pthread_t                             RootThreadId;
   1.480 
   1.481     static ThreadList* volatile pRunningThreads;
   1.482 
   1.483     void addThread(Thread *pthread)
   1.484     {
   1.485         Mutex::Locker lock(&ThreadMutex);
   1.486         ThreadSet.Add(pthread);
   1.487     }
   1.488 
   1.489     void removeThread(Thread *pthread)
   1.490     {
   1.491         Mutex::Locker lock(&ThreadMutex);
   1.492         ThreadSet.Remove(pthread);
   1.493         if (ThreadSet.GetSize() == 0)
   1.494             ThreadsEmpty.Notify();
   1.495     }
   1.496 
   1.497     void finishAllThreads()
   1.498     {
   1.499         // Only original root thread can call this.
   1.500         OVR_ASSERT(pthread_self() == RootThreadId);
   1.501 
   1.502         Mutex::Locker lock(&ThreadMutex);
   1.503         while (ThreadSet.GetSize() != 0)
   1.504             ThreadsEmpty.Wait(&ThreadMutex);
   1.505     }
   1.506 
   1.507 public:
   1.508 
   1.509     ThreadList()
   1.510     {
   1.511         RootThreadId = pthread_self();
   1.512     }
   1.513     ~ThreadList() { }
   1.514 
   1.515 
   1.516     static void AddRunningThread(Thread *pthread)
   1.517     {
   1.518         // Non-atomic creation ok since only the root thread
   1.519         if (!pRunningThreads)
   1.520         {
   1.521             pRunningThreads = new ThreadList;
   1.522             OVR_ASSERT(pRunningThreads);
   1.523         }
   1.524         pRunningThreads->addThread(pthread);
   1.525     }
   1.526 
   1.527     // NOTE: 'pthread' might be a dead pointer when this is
   1.528     // called so it should not be accessed; it is only used
   1.529     // for removal.
   1.530     static void RemoveRunningThread(Thread *pthread)
   1.531     {
   1.532         OVR_ASSERT(pRunningThreads);        
   1.533         pRunningThreads->removeThread(pthread);
   1.534     }
   1.535 
   1.536     static void FinishAllThreads()
   1.537     {
   1.538         // This is ok because only root thread can wait for other thread finish.
   1.539         if (pRunningThreads)
   1.540         {           
   1.541             pRunningThreads->finishAllThreads();
   1.542             delete pRunningThreads;
   1.543             pRunningThreads = 0;
   1.544         }        
   1.545     }
   1.546 };
   1.547 
   1.548 // By default, we have no thread list.
   1.549 ThreadList* volatile ThreadList::pRunningThreads = 0;
   1.550 
   1.551 
   1.552 // FinishAllThreads - exposed publicly in Thread.
   1.553 void Thread::FinishAllThreads()
   1.554 {
   1.555     ThreadList::FinishAllThreads();
   1.556 }
   1.557 
   1.558 // *** Run override
   1.559 
   1.560 int    Thread::PRun()
   1.561 {
   1.562     // Suspend us on start, if requested
   1.563     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
   1.564     {
   1.565         Suspend();
   1.566         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
   1.567     }
   1.568 
   1.569     // Call the virtual run function
   1.570     ExitCode = Run();    
   1.571     return ExitCode;
   1.572 }
   1.573 
   1.574 
   1.575 
   1.576 
   1.577 // *** User overridables
   1.578 
   1.579 bool    Thread::GetExitFlag() const
   1.580 {
   1.581     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
   1.582 }       
   1.583 
   1.584 void    Thread::SetExitFlag(bool exitFlag)
   1.585 {
   1.586     // The below is atomic since ThreadFlags is AtomicInt.
   1.587     if (exitFlag)
   1.588         ThreadFlags |= OVR_THREAD_EXIT;
   1.589     else
   1.590         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
   1.591 }
   1.592 
   1.593 
   1.594 // Determines whether the thread was running and is now finished
   1.595 bool    Thread::IsFinished() const
   1.596 {
   1.597     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
   1.598 }
   1.599 // Determines whether the thread is suspended
   1.600 bool    Thread::IsSuspended() const
   1.601 {   
   1.602     return SuspendCount > 0;
   1.603 }
   1.604 // Returns current thread state
   1.605 Thread::ThreadState Thread::GetThreadState() const
   1.606 {
   1.607     if (IsSuspended())
   1.608         return Suspended;    
   1.609     if (ThreadFlags & OVR_THREAD_STARTED)
   1.610         return Running;    
   1.611     return NotRunning;
   1.612 }
   1.613 /*
   1.614 static const char* mapsched_policy(int policy)
   1.615 {
   1.616     switch(policy)
   1.617     {
   1.618     case SCHED_OTHER:
   1.619         return "SCHED_OTHER";
   1.620     case SCHED_RR:
   1.621         return "SCHED_RR";
   1.622     case SCHED_FIFO:
   1.623         return "SCHED_FIFO";
   1.624 
   1.625     }
   1.626     return "UNKNOWN";
   1.627 }
   1.628     int policy;
   1.629     sched_param sparam;
   1.630     pthread_getschedparam(pthread_self(), &policy, &sparam);
   1.631     int max_prior = sched_get_priority_max(policy);
   1.632     int min_prior = sched_get_priority_min(policy);
   1.633     printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
   1.634 #include <stdio.h>
   1.635 */
   1.636 // ***** Thread management
   1.637 
   1.638 // The actual first function called on thread start
   1.639 void* Thread_PthreadStartFn(void* phandle)
   1.640 {
   1.641     Thread* pthread = (Thread*)phandle;
   1.642     int     result = pthread->PRun();
   1.643     // Signal the thread as done and release it atomically.
   1.644     pthread->FinishAndRelease();
   1.645     // At this point Thread object might be dead; however we can still pass
   1.646     // it to RemoveRunningThread since it is only used as a key there.   
   1.647     ThreadList::RemoveRunningThread(pthread);
   1.648     return (void*) result;
   1.649 }
   1.650 
   1.651 int Thread::InitAttr = 0;
   1.652 pthread_attr_t Thread::Attr; 
   1.653 
   1.654 /* static */
   1.655 int Thread::GetOSPriority(ThreadPriority p)
   1.656 //static inline int MapToSystemPrority(Thread::ThreadPriority p)
   1.657 {
   1.658 #ifdef OVR_OS_PS3 
   1.659     switch(p)
   1.660     {
   1.661     case Thread::CriticalPriority:     return 0;
   1.662     case Thread::HighestPriority:      return 300;
   1.663     case Thread::AboveNormalPriority:  return 600;
   1.664     case Thread::NormalPriority:       return 1000;
   1.665     case Thread::BelowNormalPriority:  return 1500;
   1.666     case Thread::LowestPriority:       return 2500;
   1.667     case Thread::IdlePriority:         return 3071;
   1.668     }                                  return 1000;
   1.669 #else
   1.670     OVR_UNUSED(p);
   1.671     return -1;
   1.672 #endif
   1.673 }
   1.674 
   1.675 bool    Thread::Start(ThreadState initialState)
   1.676 {
   1.677     if (initialState == NotRunning)
   1.678         return 0;
   1.679     if (GetThreadState() != NotRunning)
   1.680     {
   1.681         OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
   1.682         return 0;
   1.683     }
   1.684 
   1.685     if (!InitAttr)
   1.686     {
   1.687         pthread_attr_init(&Attr);
   1.688         pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
   1.689         pthread_attr_setstacksize(&Attr, 128 * 1024);
   1.690         sched_param sparam;
   1.691         sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
   1.692         pthread_attr_setschedparam(&Attr, &sparam);
   1.693         InitAttr = 1;
   1.694     }
   1.695 
   1.696     ExitCode        = 0;
   1.697     SuspendCount    = 0;
   1.698     ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
   1.699 
   1.700     // AddRef to us until the thread is finished
   1.701     AddRef();
   1.702     ThreadList::AddRunningThread(this);
   1.703 
   1.704     int result;
   1.705     if (StackSize != 128 * 1024 || Priority != NormalPriority)
   1.706     {
   1.707         pthread_attr_t attr;
   1.708 
   1.709         pthread_attr_init(&attr);
   1.710         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   1.711         pthread_attr_setstacksize(&attr, StackSize);
   1.712         sched_param sparam;
   1.713         sparam.sched_priority = Thread::GetOSPriority(Priority);
   1.714         pthread_attr_setschedparam(&attr, &sparam);
   1.715         result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
   1.716         pthread_attr_destroy(&attr);
   1.717     }
   1.718     else
   1.719         result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
   1.720 
   1.721     if (result)
   1.722     {
   1.723         ThreadFlags = 0;
   1.724         Release();
   1.725         ThreadList::RemoveRunningThread(this);
   1.726         return 0;
   1.727     }
   1.728     return 1;
   1.729 }
   1.730 
   1.731 
   1.732 // Suspend the thread until resumed
   1.733 bool    Thread::Suspend()
   1.734 {
   1.735     OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
   1.736     return 0;
   1.737 }
   1.738 
   1.739 // Resumes currently suspended thread
   1.740 bool    Thread::Resume()
   1.741 {
   1.742     return 0;
   1.743 }
   1.744 
   1.745 
   1.746 // Quits with an exit code  
   1.747 void    Thread::Exit(int exitCode)
   1.748 {
   1.749     // Can only exist the current thread
   1.750    // if (GetThread() != this)
   1.751    //     return;
   1.752 
   1.753     // Call the virtual OnExit function
   1.754     OnExit();   
   1.755 
   1.756     // Signal this thread object as done and release it's references.
   1.757     FinishAndRelease();
   1.758     ThreadList::RemoveRunningThread(this);
   1.759 
   1.760     pthread_exit((void *) exitCode);
   1.761 }
   1.762 
   1.763 ThreadId GetCurrentThreadId()
   1.764 {
   1.765     return (void*)pthread_self();
   1.766 }
   1.767 
   1.768 // *** Sleep functions
   1.769 
   1.770 /* static */
   1.771 bool    Thread::Sleep(unsigned secs)
   1.772 {
   1.773     sleep(secs);
   1.774     return 1;
   1.775 }
   1.776 /* static */
   1.777 bool    Thread::MSleep(unsigned msecs)
   1.778 {
   1.779     usleep(msecs*1000);
   1.780     return 1;
   1.781 }
   1.782 
   1.783 /* static */
   1.784 int     Thread::GetCPUCount()
   1.785 {
   1.786     return 1;
   1.787 }
   1.788 
   1.789 
   1.790 #ifdef OVR_OS_PS3
   1.791 
   1.792 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
   1.793 
   1.794 #endif
   1.795 
   1.796 }
   1.797 
   1.798 #endif  // OVR_ENABLE_THREADS
   1.799 \ No newline at end of file
   1.800 +
   1.801 +#include "OVR_Threads.h"
   1.802 +#include "OVR_Hash.h"
   1.803 +
   1.804 +#ifdef OVR_ENABLE_THREADS
   1.805 +
   1.806 +#include "OVR_Timer.h"
   1.807 +#include "OVR_Log.h"
   1.808 +
   1.809 +#include <pthread.h>
   1.810 +#include <time.h>
   1.811 +
   1.812 +#ifdef OVR_OS_PS3
   1.813 +#include <sys/sys_time.h>
   1.814 +#include <sys/timer.h>
   1.815 +#include <sys/synchronization.h>
   1.816 +#define sleep(x) sys_timer_sleep(x)
   1.817 +#define usleep(x) sys_timer_usleep(x)
   1.818 +using std::timespec;
   1.819 +#else
   1.820 +#include <unistd.h>
   1.821 +#include <sys/time.h>
   1.822 +#include <errno.h>
   1.823 +#endif
   1.824 +
   1.825 +namespace OVR {
   1.826 +
   1.827 +// ***** Mutex implementation
   1.828 +
   1.829 +
   1.830 +// *** Internal Mutex implementation structure
   1.831 +
   1.832 +class MutexImpl : public NewOverrideBase
   1.833 +{
   1.834 +    // System mutex or semaphore
   1.835 +    pthread_mutex_t   SMutex;
   1.836 +    bool          Recursive;
   1.837 +    unsigned      LockCount;
   1.838 +    pthread_t     LockedBy;
   1.839 +
   1.840 +    friend class WaitConditionImpl;
   1.841 +
   1.842 +public:
   1.843 +    // Constructor/destructor
   1.844 +    MutexImpl(Mutex* pmutex, bool recursive = 1);
   1.845 +    ~MutexImpl();
   1.846 +
   1.847 +    // Locking functions
   1.848 +    void                DoLock();
   1.849 +    bool                TryLock();
   1.850 +    void                Unlock(Mutex* pmutex);
   1.851 +    // Returns 1 if the mutes is currently locked
   1.852 +    bool                IsLockedByAnotherThread(Mutex* pmutex);        
   1.853 +    bool                IsSignaled() const;
   1.854 +};
   1.855 +
   1.856 +pthread_mutexattr_t Lock::RecursiveAttr;
   1.857 +bool Lock::RecursiveAttrInit = 0;
   1.858 +
   1.859 +// *** Constructor/destructor
   1.860 +MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
   1.861 +{   
   1.862 +    Recursive           = recursive;
   1.863 +    LockCount           = 0;
   1.864 +
   1.865 +    if (Recursive)
   1.866 +    {
   1.867 +        if (!Lock::RecursiveAttrInit)
   1.868 +        {
   1.869 +            pthread_mutexattr_init(&Lock::RecursiveAttr);
   1.870 +            pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
   1.871 +            Lock::RecursiveAttrInit = 1;
   1.872 +        }
   1.873 +
   1.874 +        pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
   1.875 +    }
   1.876 +    else
   1.877 +        pthread_mutex_init(&SMutex, 0);
   1.878 +}
   1.879 +
   1.880 +MutexImpl::~MutexImpl()
   1.881 +{
   1.882 +    pthread_mutex_destroy(&SMutex);
   1.883 +}
   1.884 +
   1.885 +
   1.886 +// Lock and try lock
   1.887 +void MutexImpl::DoLock()
   1.888 +{
   1.889 +    while (pthread_mutex_lock(&SMutex));
   1.890 +    LockCount++;
   1.891 +    LockedBy = pthread_self();
   1.892 +}
   1.893 +
   1.894 +bool MutexImpl::TryLock()
   1.895 +{
   1.896 +    if (!pthread_mutex_trylock(&SMutex))
   1.897 +    {
   1.898 +        LockCount++;
   1.899 +        LockedBy = pthread_self();
   1.900 +        return 1;
   1.901 +    }
   1.902 +    
   1.903 +    return 0;
   1.904 +}
   1.905 +
   1.906 +void MutexImpl::Unlock(Mutex* pmutex)
   1.907 +{
   1.908 +    OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
   1.909 +
   1.910 +    unsigned lockCount;
   1.911 +    LockCount--;
   1.912 +    lockCount = LockCount;
   1.913 +
   1.914 +    pthread_mutex_unlock(&SMutex);
   1.915 +}
   1.916 +
   1.917 +bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
   1.918 +{
   1.919 +    // There could be multiple interpretations of IsLocked with respect to current thread
   1.920 +    if (LockCount == 0)
   1.921 +        return 0;
   1.922 +    if (pthread_self() != LockedBy)
   1.923 +        return 1;
   1.924 +    return 0;
   1.925 +}
   1.926 +
   1.927 +bool    MutexImpl::IsSignaled() const
   1.928 +{
   1.929 +    // An mutex is signaled if it is not locked ANYWHERE
   1.930 +    // Note that this is different from IsLockedByAnotherThread function,
   1.931 +    // that takes current thread into account
   1.932 +    return LockCount == 0;
   1.933 +}
   1.934 +
   1.935 +
   1.936 +// *** Actual Mutex class implementation
   1.937 +
   1.938 +Mutex::Mutex(bool recursive)
   1.939 +{
   1.940 +    // NOTE: RefCount mode already thread-safe for all waitables.
   1.941 +    pImpl = new MutexImpl(this, recursive);
   1.942 +}
   1.943 +
   1.944 +Mutex::~Mutex()
   1.945 +{
   1.946 +    delete pImpl;
   1.947 +}
   1.948 +
   1.949 +// Lock and try lock
   1.950 +void Mutex::DoLock()
   1.951 +{
   1.952 +    pImpl->DoLock();
   1.953 +}
   1.954 +bool Mutex::TryLock()
   1.955 +{
   1.956 +    return pImpl->TryLock();
   1.957 +}
   1.958 +void Mutex::Unlock()
   1.959 +{
   1.960 +    pImpl->Unlock(this);
   1.961 +}
   1.962 +bool    Mutex::IsLockedByAnotherThread()
   1.963 +{
   1.964 +    return pImpl->IsLockedByAnotherThread(this);
   1.965 +}
   1.966 +
   1.967 +
   1.968 +
   1.969 +//-----------------------------------------------------------------------------------
   1.970 +// ***** Event
   1.971 +
   1.972 +bool Event::Wait(unsigned delay)
   1.973 +{
   1.974 +    Mutex::Locker lock(&StateMutex);
   1.975 +
   1.976 +    // Do the correct amount of waiting
   1.977 +    if (delay == OVR_WAIT_INFINITE)
   1.978 +    {
   1.979 +        while(!State)
   1.980 +            StateWaitCondition.Wait(&StateMutex);
   1.981 +    }
   1.982 +    else if (delay)
   1.983 +    {
   1.984 +        if (!State)
   1.985 +            StateWaitCondition.Wait(&StateMutex, delay);
   1.986 +    }
   1.987 +
   1.988 +    bool state = State;
   1.989 +    // Take care of temporary 'pulsing' of a state
   1.990 +    if (Temporary)
   1.991 +    {
   1.992 +        Temporary   = false;
   1.993 +        State       = false;
   1.994 +    }
   1.995 +    return state;
   1.996 +}
   1.997 +
   1.998 +void Event::updateState(bool newState, bool newTemp, bool mustNotify)
   1.999 +{
  1.1000 +    Mutex::Locker lock(&StateMutex);
  1.1001 +    State       = newState;
  1.1002 +    Temporary   = newTemp;
  1.1003 +    if (mustNotify)
  1.1004 +        StateWaitCondition.NotifyAll();    
  1.1005 +}
  1.1006 +
  1.1007 +
  1.1008 +
  1.1009 +// ***** Wait Condition Implementation
  1.1010 +
  1.1011 +// Internal implementation class
  1.1012 +class WaitConditionImpl : public NewOverrideBase
  1.1013 +{
  1.1014 +    pthread_mutex_t     SMutex;
  1.1015 +    pthread_cond_t      Condv;
  1.1016 +
  1.1017 +public:
  1.1018 +
  1.1019 +    // Constructor/destructor
  1.1020 +    WaitConditionImpl();
  1.1021 +    ~WaitConditionImpl();
  1.1022 +
  1.1023 +    // Release mutex and wait for condition. The mutex is re-aqured after the wait.
  1.1024 +    bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  1.1025 +
  1.1026 +    // Notify a condition, releasing at one object waiting
  1.1027 +    void    Notify();
  1.1028 +    // Notify a condition, releasing all objects waiting
  1.1029 +    void    NotifyAll();
  1.1030 +};
  1.1031 +
  1.1032 +
  1.1033 +WaitConditionImpl::WaitConditionImpl()
  1.1034 +{
  1.1035 +    pthread_mutex_init(&SMutex, 0);
  1.1036 +    pthread_cond_init(&Condv, 0);
  1.1037 +}
  1.1038 +
  1.1039 +WaitConditionImpl::~WaitConditionImpl()
  1.1040 +{
  1.1041 +    pthread_mutex_destroy(&SMutex);
  1.1042 +    pthread_cond_destroy(&Condv);
  1.1043 +}    
  1.1044 +
  1.1045 +bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  1.1046 +{
  1.1047 +    bool            result = 1;
  1.1048 +    unsigned            lockCount = pmutex->pImpl->LockCount;
  1.1049 +
  1.1050 +    // Mutex must have been locked
  1.1051 +    if (lockCount == 0)
  1.1052 +        return 0;
  1.1053 +
  1.1054 +    pthread_mutex_lock(&SMutex);
  1.1055 +
  1.1056 +    // Finally, release a mutex or semaphore
  1.1057 +    if (pmutex->pImpl->Recursive)
  1.1058 +    {
  1.1059 +        // Release the recursive mutex N times
  1.1060 +        pmutex->pImpl->LockCount = 0;
  1.1061 +        for(unsigned i=0; i<lockCount; i++)
  1.1062 +            pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  1.1063 +    }
  1.1064 +    else
  1.1065 +    {
  1.1066 +        pmutex->pImpl->LockCount = 0;
  1.1067 +        pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  1.1068 +    }
  1.1069 +
  1.1070 +    // Note that there is a gap here between mutex.Unlock() and Wait().
  1.1071 +    // The other mutex protects this gap.
  1.1072 +
  1.1073 +    if (delay == OVR_WAIT_INFINITE)
  1.1074 +        pthread_cond_wait(&Condv,&SMutex);
  1.1075 +    else
  1.1076 +    {
  1.1077 +        timespec ts;
  1.1078 +#ifdef OVR_OS_PS3
  1.1079 +        sys_time_sec_t s;
  1.1080 +        sys_time_nsec_t ns;
  1.1081 +        sys_time_get_current_time(&s, &ns);
  1.1082 +
  1.1083 +        ts.tv_sec = s + (delay / 1000);
  1.1084 +        ts.tv_nsec = ns + (delay % 1000) * 1000000;
  1.1085 +
  1.1086 +#else
  1.1087 +        struct timeval tv;
  1.1088 +        gettimeofday(&tv, 0);
  1.1089 +
  1.1090 +        ts.tv_sec = tv.tv_sec + (delay / 1000);
  1.1091 +        ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
  1.1092 +#endif
  1.1093 +        if (ts.tv_nsec > 999999999)
  1.1094 +        {
  1.1095 +            ts.tv_sec++;
  1.1096 +            ts.tv_nsec -= 1000000000;
  1.1097 +        }
  1.1098 +        int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
  1.1099 +        OVR_ASSERT(r == 0 || r == ETIMEDOUT);
  1.1100 +        if (r)
  1.1101 +            result = 0;
  1.1102 +    }
  1.1103 +
  1.1104 +    pthread_mutex_unlock(&SMutex);
  1.1105 +
  1.1106 +    // Re-aquire the mutex
  1.1107 +    for(unsigned i=0; i<lockCount; i++)
  1.1108 +        pmutex->DoLock(); 
  1.1109 +
  1.1110 +    // Return the result
  1.1111 +    return result;
  1.1112 +}
  1.1113 +
  1.1114 +// Notify a condition, releasing the least object in a queue
  1.1115 +void    WaitConditionImpl::Notify()
  1.1116 +{
  1.1117 +    pthread_mutex_lock(&SMutex);
  1.1118 +    pthread_cond_signal(&Condv);
  1.1119 +    pthread_mutex_unlock(&SMutex);
  1.1120 +}
  1.1121 +
  1.1122 +// Notify a condition, releasing all objects waiting
  1.1123 +void    WaitConditionImpl::NotifyAll()
  1.1124 +{
  1.1125 +    pthread_mutex_lock(&SMutex);
  1.1126 +    pthread_cond_broadcast(&Condv);
  1.1127 +    pthread_mutex_unlock(&SMutex);
  1.1128 +}
  1.1129 +
  1.1130 +
  1.1131 +
  1.1132 +// *** Actual implementation of WaitCondition
  1.1133 +
  1.1134 +WaitCondition::WaitCondition()
  1.1135 +{
  1.1136 +    pImpl = new WaitConditionImpl;
  1.1137 +}
  1.1138 +WaitCondition::~WaitCondition()
  1.1139 +{
  1.1140 +    delete pImpl;
  1.1141 +}
  1.1142 +    
  1.1143 +bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  1.1144 +{
  1.1145 +    return pImpl->Wait(pmutex, delay);
  1.1146 +}
  1.1147 +// Notification
  1.1148 +void    WaitCondition::Notify()
  1.1149 +{
  1.1150 +    pImpl->Notify();
  1.1151 +}
  1.1152 +void    WaitCondition::NotifyAll()
  1.1153 +{
  1.1154 +    pImpl->NotifyAll();
  1.1155 +}
  1.1156 +
  1.1157 +
  1.1158 +// ***** Current thread
  1.1159 +
  1.1160 +// Per-thread variable
  1.1161 +/*
  1.1162 +static __thread Thread* pCurrentThread = 0;
  1.1163 +
  1.1164 +// Static function to return a pointer to the current thread
  1.1165 +void    Thread::InitCurrentThread(Thread *pthread)
  1.1166 +{
  1.1167 +    pCurrentThread = pthread;
  1.1168 +}
  1.1169 +
  1.1170 +// Static function to return a pointer to the current thread
  1.1171 +Thread*    Thread::GetThread()
  1.1172 +{
  1.1173 +    return pCurrentThread;
  1.1174 +}
  1.1175 +*/
  1.1176 +
  1.1177 +
  1.1178 +// *** Thread constructors.
  1.1179 +
  1.1180 +Thread::Thread(UPInt stackSize, int processor)
  1.1181 +{
  1.1182 +    // NOTE: RefCount mode already thread-safe for all Waitable objects.
  1.1183 +    CreateParams params;
  1.1184 +    params.stackSize = stackSize;
  1.1185 +    params.processor = processor;
  1.1186 +    Init(params);
  1.1187 +}
  1.1188 +
  1.1189 +Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
  1.1190 +                 int processor, Thread::ThreadState initialState)
  1.1191 +{
  1.1192 +    CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  1.1193 +    Init(params);
  1.1194 +}
  1.1195 +
  1.1196 +Thread::Thread(const CreateParams& params)
  1.1197 +{
  1.1198 +    Init(params);
  1.1199 +}
  1.1200 +
  1.1201 +void Thread::Init(const CreateParams& params)
  1.1202 +{
  1.1203 +    // Clear the variables    
  1.1204 +    ThreadFlags     = 0;
  1.1205 +    ThreadHandle    = 0;
  1.1206 +    ExitCode        = 0;
  1.1207 +    SuspendCount    = 0;
  1.1208 +    StackSize       = params.stackSize;
  1.1209 +    Processor       = params.processor;
  1.1210 +    Priority        = params.priority;
  1.1211 +
  1.1212 +    // Clear Function pointers
  1.1213 +    ThreadFunction  = params.threadFunction;
  1.1214 +    UserHandle      = params.userHandle;
  1.1215 +    if (params.initialState != NotRunning)
  1.1216 +        Start(params.initialState);
  1.1217 +}
  1.1218 +
  1.1219 +Thread::~Thread()
  1.1220 +{
  1.1221 +    // Thread should not running while object is being destroyed,
  1.1222 +    // this would indicate ref-counting issue.
  1.1223 +    //OVR_ASSERT(IsRunning() == 0);
  1.1224 +
  1.1225 +    // Clean up thread.    
  1.1226 +    ThreadHandle = 0;
  1.1227 +}
  1.1228 +
  1.1229 +
  1.1230 +
  1.1231 +// *** Overridable User functions.
  1.1232 +
  1.1233 +// Default Run implementation
  1.1234 +int    Thread::Run()
  1.1235 +{
  1.1236 +    // Call pointer to function, if available.    
  1.1237 +    return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  1.1238 +}
  1.1239 +void    Thread::OnExit()
  1.1240 +{   
  1.1241 +}
  1.1242 +
  1.1243 +
  1.1244 +// Finishes the thread and releases internal reference to it.
  1.1245 +void    Thread::FinishAndRelease()
  1.1246 +{
  1.1247 +    // Note: thread must be US.
  1.1248 +    ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  1.1249 +    ThreadFlags |= OVR_THREAD_FINISHED;
  1.1250 +
  1.1251 +    // Release our reference; this is equivalent to 'delete this'
  1.1252 +    // from the point of view of our thread.
  1.1253 +    Release();
  1.1254 +}
  1.1255 +
  1.1256 +
  1.1257 +
  1.1258 +// *** ThreadList - used to track all created threads
  1.1259 +
  1.1260 +class ThreadList : public NewOverrideBase
  1.1261 +{
  1.1262 +    //------------------------------------------------------------------------
  1.1263 +    struct ThreadHashOp
  1.1264 +    {
  1.1265 +        size_t operator()(const Thread* ptr)
  1.1266 +        {
  1.1267 +            return (((size_t)ptr) >> 6) ^ (size_t)ptr;
  1.1268 +        }
  1.1269 +    };
  1.1270 +
  1.1271 +    HashSet<Thread*, ThreadHashOp>        ThreadSet;
  1.1272 +    Mutex                                 ThreadMutex;
  1.1273 +    WaitCondition                         ThreadsEmpty;
  1.1274 +    // Track the root thread that created us.
  1.1275 +    pthread_t                             RootThreadId;
  1.1276 +
  1.1277 +    static ThreadList* volatile pRunningThreads;
  1.1278 +
  1.1279 +    void addThread(Thread *pthread)
  1.1280 +    {
  1.1281 +        Mutex::Locker lock(&ThreadMutex);
  1.1282 +        ThreadSet.Add(pthread);
  1.1283 +    }
  1.1284 +
  1.1285 +    void removeThread(Thread *pthread)
  1.1286 +    {
  1.1287 +        Mutex::Locker lock(&ThreadMutex);
  1.1288 +        ThreadSet.Remove(pthread);
  1.1289 +        if (ThreadSet.GetSize() == 0)
  1.1290 +            ThreadsEmpty.Notify();
  1.1291 +    }
  1.1292 +
  1.1293 +    void finishAllThreads()
  1.1294 +    {
  1.1295 +        // Only original root thread can call this.
  1.1296 +        OVR_ASSERT(pthread_self() == RootThreadId);
  1.1297 +
  1.1298 +        Mutex::Locker lock(&ThreadMutex);
  1.1299 +        while (ThreadSet.GetSize() != 0)
  1.1300 +            ThreadsEmpty.Wait(&ThreadMutex);
  1.1301 +    }
  1.1302 +
  1.1303 +public:
  1.1304 +
  1.1305 +    ThreadList()
  1.1306 +    {
  1.1307 +        RootThreadId = pthread_self();
  1.1308 +    }
  1.1309 +    ~ThreadList() { }
  1.1310 +
  1.1311 +
  1.1312 +    static void AddRunningThread(Thread *pthread)
  1.1313 +    {
  1.1314 +        // Non-atomic creation ok since only the root thread
  1.1315 +        if (!pRunningThreads)
  1.1316 +        {
  1.1317 +            pRunningThreads = new ThreadList;
  1.1318 +            OVR_ASSERT(pRunningThreads);
  1.1319 +        }
  1.1320 +        pRunningThreads->addThread(pthread);
  1.1321 +    }
  1.1322 +
  1.1323 +    // NOTE: 'pthread' might be a dead pointer when this is
  1.1324 +    // called so it should not be accessed; it is only used
  1.1325 +    // for removal.
  1.1326 +    static void RemoveRunningThread(Thread *pthread)
  1.1327 +    {
  1.1328 +        OVR_ASSERT(pRunningThreads);        
  1.1329 +        pRunningThreads->removeThread(pthread);
  1.1330 +    }
  1.1331 +
  1.1332 +    static void FinishAllThreads()
  1.1333 +    {
  1.1334 +        // This is ok because only root thread can wait for other thread finish.
  1.1335 +        if (pRunningThreads)
  1.1336 +        {           
  1.1337 +            pRunningThreads->finishAllThreads();
  1.1338 +            delete pRunningThreads;
  1.1339 +            pRunningThreads = 0;
  1.1340 +        }        
  1.1341 +    }
  1.1342 +};
  1.1343 +
  1.1344 +// By default, we have no thread list.
  1.1345 +ThreadList* volatile ThreadList::pRunningThreads = 0;
  1.1346 +
  1.1347 +
  1.1348 +// FinishAllThreads - exposed publicly in Thread.
  1.1349 +void Thread::FinishAllThreads()
  1.1350 +{
  1.1351 +    ThreadList::FinishAllThreads();
  1.1352 +}
  1.1353 +
  1.1354 +// *** Run override
  1.1355 +
  1.1356 +int    Thread::PRun()
  1.1357 +{
  1.1358 +    // Suspend us on start, if requested
  1.1359 +    if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  1.1360 +    {
  1.1361 +        Suspend();
  1.1362 +        ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  1.1363 +    }
  1.1364 +
  1.1365 +    // Call the virtual run function
  1.1366 +    ExitCode = Run();    
  1.1367 +    return ExitCode;
  1.1368 +}
  1.1369 +
  1.1370 +
  1.1371 +
  1.1372 +
  1.1373 +// *** User overridables
  1.1374 +
  1.1375 +bool    Thread::GetExitFlag() const
  1.1376 +{
  1.1377 +    return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  1.1378 +}       
  1.1379 +
  1.1380 +void    Thread::SetExitFlag(bool exitFlag)
  1.1381 +{
  1.1382 +    // The below is atomic since ThreadFlags is AtomicInt.
  1.1383 +    if (exitFlag)
  1.1384 +        ThreadFlags |= OVR_THREAD_EXIT;
  1.1385 +    else
  1.1386 +        ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  1.1387 +}
  1.1388 +
  1.1389 +
  1.1390 +// Determines whether the thread was running and is now finished
  1.1391 +bool    Thread::IsFinished() const
  1.1392 +{
  1.1393 +    return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  1.1394 +}
  1.1395 +// Determines whether the thread is suspended
  1.1396 +bool    Thread::IsSuspended() const
  1.1397 +{   
  1.1398 +    return SuspendCount > 0;
  1.1399 +}
  1.1400 +// Returns current thread state
  1.1401 +Thread::ThreadState Thread::GetThreadState() const
  1.1402 +{
  1.1403 +    if (IsSuspended())
  1.1404 +        return Suspended;    
  1.1405 +    if (ThreadFlags & OVR_THREAD_STARTED)
  1.1406 +        return Running;    
  1.1407 +    return NotRunning;
  1.1408 +}
  1.1409 +/*
  1.1410 +static const char* mapsched_policy(int policy)
  1.1411 +{
  1.1412 +    switch(policy)
  1.1413 +    {
  1.1414 +    case SCHED_OTHER:
  1.1415 +        return "SCHED_OTHER";
  1.1416 +    case SCHED_RR:
  1.1417 +        return "SCHED_RR";
  1.1418 +    case SCHED_FIFO:
  1.1419 +        return "SCHED_FIFO";
  1.1420 +
  1.1421 +    }
  1.1422 +    return "UNKNOWN";
  1.1423 +}
  1.1424 +    int policy;
  1.1425 +    sched_param sparam;
  1.1426 +    pthread_getschedparam(pthread_self(), &policy, &sparam);
  1.1427 +    int max_prior = sched_get_priority_max(policy);
  1.1428 +    int min_prior = sched_get_priority_min(policy);
  1.1429 +    printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
  1.1430 +#include <stdio.h>
  1.1431 +*/
  1.1432 +// ***** Thread management
  1.1433 +
  1.1434 +// The actual first function called on thread start
  1.1435 +void* Thread_PthreadStartFn(void* phandle)
  1.1436 +{
  1.1437 +    Thread* pthread = (Thread*)phandle;
  1.1438 +    int     result = pthread->PRun();
  1.1439 +    // Signal the thread as done and release it atomically.
  1.1440 +    pthread->FinishAndRelease();
  1.1441 +    // At this point Thread object might be dead; however we can still pass
  1.1442 +    // it to RemoveRunningThread since it is only used as a key there.   
  1.1443 +    ThreadList::RemoveRunningThread(pthread);
  1.1444 +    return (void*) result;
  1.1445 +}
  1.1446 +
  1.1447 +int Thread::InitAttr = 0;
  1.1448 +pthread_attr_t Thread::Attr; 
  1.1449 +
  1.1450 +/* static */
  1.1451 +int Thread::GetOSPriority(ThreadPriority p)
  1.1452 +//static inline int MapToSystemPrority(Thread::ThreadPriority p)
  1.1453 +{
  1.1454 +#ifdef OVR_OS_PS3 
  1.1455 +    switch(p)
  1.1456 +    {
  1.1457 +    case Thread::CriticalPriority:     return 0;
  1.1458 +    case Thread::HighestPriority:      return 300;
  1.1459 +    case Thread::AboveNormalPriority:  return 600;
  1.1460 +    case Thread::NormalPriority:       return 1000;
  1.1461 +    case Thread::BelowNormalPriority:  return 1500;
  1.1462 +    case Thread::LowestPriority:       return 2500;
  1.1463 +    case Thread::IdlePriority:         return 3071;
  1.1464 +    }                                  return 1000;
  1.1465 +#else
  1.1466 +    OVR_UNUSED(p);
  1.1467 +    return -1;
  1.1468 +#endif
  1.1469 +}
  1.1470 +
  1.1471 +bool    Thread::Start(ThreadState initialState)
  1.1472 +{
  1.1473 +    if (initialState == NotRunning)
  1.1474 +        return 0;
  1.1475 +    if (GetThreadState() != NotRunning)
  1.1476 +    {
  1.1477 +        OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  1.1478 +        return 0;
  1.1479 +    }
  1.1480 +
  1.1481 +    if (!InitAttr)
  1.1482 +    {
  1.1483 +        pthread_attr_init(&Attr);
  1.1484 +        pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
  1.1485 +        pthread_attr_setstacksize(&Attr, 128 * 1024);
  1.1486 +        sched_param sparam;
  1.1487 +        sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
  1.1488 +        pthread_attr_setschedparam(&Attr, &sparam);
  1.1489 +        InitAttr = 1;
  1.1490 +    }
  1.1491 +
  1.1492 +    ExitCode        = 0;
  1.1493 +    SuspendCount    = 0;
  1.1494 +    ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  1.1495 +
  1.1496 +    // AddRef to us until the thread is finished
  1.1497 +    AddRef();
  1.1498 +    ThreadList::AddRunningThread(this);
  1.1499 +
  1.1500 +    int result;
  1.1501 +    if (StackSize != 128 * 1024 || Priority != NormalPriority)
  1.1502 +    {
  1.1503 +        pthread_attr_t attr;
  1.1504 +
  1.1505 +        pthread_attr_init(&attr);
  1.1506 +        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  1.1507 +        pthread_attr_setstacksize(&attr, StackSize);
  1.1508 +        sched_param sparam;
  1.1509 +        sparam.sched_priority = Thread::GetOSPriority(Priority);
  1.1510 +        pthread_attr_setschedparam(&attr, &sparam);
  1.1511 +        result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
  1.1512 +        pthread_attr_destroy(&attr);
  1.1513 +    }
  1.1514 +    else
  1.1515 +        result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
  1.1516 +
  1.1517 +    if (result)
  1.1518 +    {
  1.1519 +        ThreadFlags = 0;
  1.1520 +        Release();
  1.1521 +        ThreadList::RemoveRunningThread(this);
  1.1522 +        return 0;
  1.1523 +    }
  1.1524 +    return 1;
  1.1525 +}
  1.1526 +
  1.1527 +
  1.1528 +// Suspend the thread until resumed
  1.1529 +bool    Thread::Suspend()
  1.1530 +{
  1.1531 +    OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
  1.1532 +    return 0;
  1.1533 +}
  1.1534 +
  1.1535 +// Resumes currently suspended thread
  1.1536 +bool    Thread::Resume()
  1.1537 +{
  1.1538 +    return 0;
  1.1539 +}
  1.1540 +
  1.1541 +
  1.1542 +// Quits with an exit code  
  1.1543 +void    Thread::Exit(int exitCode)
  1.1544 +{
  1.1545 +    // Can only exist the current thread
  1.1546 +   // if (GetThread() != this)
  1.1547 +   //     return;
  1.1548 +
  1.1549 +    // Call the virtual OnExit function
  1.1550 +    OnExit();   
  1.1551 +
  1.1552 +    // Signal this thread object as done and release it's references.
  1.1553 +    FinishAndRelease();
  1.1554 +    ThreadList::RemoveRunningThread(this);
  1.1555 +
  1.1556 +    pthread_exit((void *) exitCode);
  1.1557 +}
  1.1558 +
  1.1559 +ThreadId GetCurrentThreadId()
  1.1560 +{
  1.1561 +    return (void*)pthread_self();
  1.1562 +}
  1.1563 +
  1.1564 +// *** Sleep functions
  1.1565 +
  1.1566 +/* static */
  1.1567 +bool    Thread::Sleep(unsigned secs)
  1.1568 +{
  1.1569 +    sleep(secs);
  1.1570 +    return 1;
  1.1571 +}
  1.1572 +/* static */
  1.1573 +bool    Thread::MSleep(unsigned msecs)
  1.1574 +{
  1.1575 +    usleep(msecs*1000);
  1.1576 +    return 1;
  1.1577 +}
  1.1578 +
  1.1579 +/* static */
  1.1580 +int     Thread::GetCPUCount()
  1.1581 +{
  1.1582 +    return 1;
  1.1583 +}
  1.1584 +
  1.1585 +
  1.1586 +#ifdef OVR_OS_PS3
  1.1587 +
  1.1588 +sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
  1.1589 +
  1.1590 +#endif
  1.1591 +
  1.1592 +}
  1.1593 +
  1.1594 +#endif  // OVR_ENABLE_THREADS