oculus1
diff libovr/Src/linux/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/linux/OVR_ThreadsPthread.cpp Sat Sep 14 17:51:03 2013 +0300 1.2 +++ b/libovr/Src/linux/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