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