oculus1

diff libovr/Src/linux/OVR_ThreadsPthread.cpp @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libovr/Src/linux/OVR_ThreadsPthread.cpp	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,1 @@
     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