ovr_sdk

view LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp @ 3:f12a8f74fe1f

added the Xcode project
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 21 Jan 2015 11:37:50 +0200
parents
children
line source
1 /************************************************************************************
3 Filename : OVR_ThreadsPthread.cpp
4 Content :
5 Created :
6 Notes :
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
15 You may obtain a copy of the License at
17 http://www.oculusvr.com/licenses/LICENSE-3.2
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
25 ************************************************************************************/
27 #include "OVR_Threads.h"
28 #include "OVR_Hash.h"
30 #ifdef OVR_ENABLE_THREADS
32 #include "OVR_Timer.h"
33 #include "OVR_Log.h"
35 #include <pthread.h>
36 #include <sched.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include <sys/time.h>
40 #include <errno.h>
42 #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
43 #include <sys/sysctl.h>
44 #include <sys/param.h>
45 #if !defined(OVR_OS_MAC)
46 #include <pthread_np.h>
47 #endif
48 #endif
52 namespace OVR {
54 // ***** Mutex implementation
57 // *** Internal Mutex implementation structure
59 class MutexImpl : public NewOverrideBase
60 {
61 // System mutex or semaphore
62 pthread_mutex_t SMutex;
63 bool Recursive;
64 unsigned LockCount;
65 pthread_t LockedBy;
67 friend class WaitConditionImpl;
69 public:
70 // Constructor/destructor
71 MutexImpl(Mutex* pmutex, bool recursive = 1);
72 ~MutexImpl();
74 // Locking functions
75 void DoLock();
76 bool TryLock();
77 void Unlock(Mutex* pmutex);
78 // Returns 1 if the mutes is currently locked
79 bool IsLockedByAnotherThread(Mutex* pmutex);
80 bool IsSignaled() const;
81 };
83 pthread_mutexattr_t Lock::RecursiveAttr;
84 bool Lock::RecursiveAttrInit = 0;
86 // *** Constructor/destructor
87 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
88 {
89 OVR_UNUSED(pmutex);
90 Recursive = recursive;
91 LockCount = 0;
93 if (Recursive)
94 {
95 if (!Lock::RecursiveAttrInit)
96 {
97 pthread_mutexattr_init(&Lock::RecursiveAttr);
98 pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
99 Lock::RecursiveAttrInit = 1;
100 }
102 pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
103 }
104 else
105 pthread_mutex_init(&SMutex, 0);
106 }
108 MutexImpl::~MutexImpl()
109 {
110 pthread_mutex_destroy(&SMutex);
111 }
114 // Lock and try lock
115 void MutexImpl::DoLock()
116 {
117 while (pthread_mutex_lock(&SMutex))
118 ;
119 LockCount++;
120 LockedBy = pthread_self();
121 }
123 bool MutexImpl::TryLock()
124 {
125 if (!pthread_mutex_trylock(&SMutex))
126 {
127 LockCount++;
128 LockedBy = pthread_self();
129 return 1;
130 }
132 return 0;
133 }
135 void MutexImpl::Unlock(Mutex* pmutex)
136 {
137 OVR_UNUSED(pmutex);
138 OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
140 //unsigned lockCount;
141 LockCount--;
142 //lockCount = LockCount;
144 pthread_mutex_unlock(&SMutex);
145 }
147 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
148 {
149 OVR_UNUSED(pmutex);
150 // There could be multiple interpretations of IsLocked with respect to current thread
151 if (LockCount == 0)
152 return 0;
153 if (pthread_self() != LockedBy)
154 return 1;
155 return 0;
156 }
158 bool MutexImpl::IsSignaled() const
159 {
160 // An mutex is signaled if it is not locked ANYWHERE
161 // Note that this is different from IsLockedByAnotherThread function,
162 // that takes current thread into account
163 return LockCount == 0;
164 }
167 // *** Actual Mutex class implementation
169 Mutex::Mutex(bool recursive)
170 {
171 // NOTE: RefCount mode already thread-safe for all waitables.
172 pImpl = new MutexImpl(this, recursive);
173 }
175 Mutex::~Mutex()
176 {
177 delete pImpl;
178 }
180 // Lock and try lock
181 void Mutex::DoLock()
182 {
183 pImpl->DoLock();
184 }
185 bool Mutex::TryLock()
186 {
187 return pImpl->TryLock();
188 }
189 void Mutex::Unlock()
190 {
191 pImpl->Unlock(this);
192 }
193 bool Mutex::IsLockedByAnotherThread()
194 {
195 return pImpl->IsLockedByAnotherThread(this);
196 }
200 //-----------------------------------------------------------------------------------
201 // ***** Event
203 bool Event::Wait(unsigned delay)
204 {
205 Mutex::Locker lock(&StateMutex);
207 // Do the correct amount of waiting
208 if (delay == OVR_WAIT_INFINITE)
209 {
210 while(!State)
211 StateWaitCondition.Wait(&StateMutex);
212 }
213 else if (delay)
214 {
215 if (!State)
216 StateWaitCondition.Wait(&StateMutex, delay);
217 }
219 bool state = State;
220 // Take care of temporary 'pulsing' of a state
221 if (Temporary)
222 {
223 Temporary = false;
224 State = false;
225 }
226 return state;
227 }
229 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
230 {
231 Mutex::Locker lock(&StateMutex);
232 State = newState;
233 Temporary = newTemp;
234 if (mustNotify)
235 StateWaitCondition.NotifyAll();
236 }
240 // ***** Wait Condition Implementation
242 // Internal implementation class
243 class WaitConditionImpl : public NewOverrideBase
244 {
245 pthread_mutex_t SMutex;
246 pthread_cond_t Condv;
248 public:
250 // Constructor/destructor
251 WaitConditionImpl();
252 ~WaitConditionImpl();
254 // Release mutex and wait for condition. The mutex is re-aqured after the wait.
255 bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
257 // Notify a condition, releasing at one object waiting
258 void Notify();
259 // Notify a condition, releasing all objects waiting
260 void NotifyAll();
261 };
264 WaitConditionImpl::WaitConditionImpl()
265 {
266 pthread_mutex_init(&SMutex, 0);
267 pthread_cond_init(&Condv, 0);
268 }
270 WaitConditionImpl::~WaitConditionImpl()
271 {
272 pthread_mutex_destroy(&SMutex);
273 pthread_cond_destroy(&Condv);
274 }
276 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
277 {
278 bool result = 1;
279 unsigned lockCount = pmutex->pImpl->LockCount;
281 // Mutex must have been locked
282 if (lockCount == 0)
283 return 0;
285 pthread_mutex_lock(&SMutex);
287 // Finally, release a mutex or semaphore
288 if (pmutex->pImpl->Recursive)
289 {
290 // Release the recursive mutex N times
291 pmutex->pImpl->LockCount = 0;
292 for(unsigned i=0; i<lockCount; i++)
293 pthread_mutex_unlock(&pmutex->pImpl->SMutex);
294 }
295 else
296 {
297 pmutex->pImpl->LockCount = 0;
298 pthread_mutex_unlock(&pmutex->pImpl->SMutex);
299 }
301 // Note that there is a gap here between mutex.Unlock() and Wait().
302 // The other mutex protects this gap.
304 if (delay == OVR_WAIT_INFINITE)
305 pthread_cond_wait(&Condv,&SMutex);
306 else
307 {
308 timespec ts;
310 struct timeval tv;
311 gettimeofday(&tv, 0);
313 ts.tv_sec = tv.tv_sec + (delay / 1000);
314 ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
316 if (ts.tv_nsec > 999999999)
317 {
318 ts.tv_sec++;
319 ts.tv_nsec -= 1000000000;
320 }
321 int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
322 OVR_ASSERT(r == 0 || r == ETIMEDOUT);
323 if (r)
324 result = 0;
325 }
327 pthread_mutex_unlock(&SMutex);
329 // Re-aquire the mutex
330 for(unsigned i=0; i<lockCount; i++)
331 pmutex->DoLock();
333 // Return the result
334 return result;
335 }
337 // Notify a condition, releasing the least object in a queue
338 void WaitConditionImpl::Notify()
339 {
340 pthread_mutex_lock(&SMutex);
341 pthread_cond_signal(&Condv);
342 pthread_mutex_unlock(&SMutex);
343 }
345 // Notify a condition, releasing all objects waiting
346 void WaitConditionImpl::NotifyAll()
347 {
348 pthread_mutex_lock(&SMutex);
349 pthread_cond_broadcast(&Condv);
350 pthread_mutex_unlock(&SMutex);
351 }
355 // *** Actual implementation of WaitCondition
357 WaitCondition::WaitCondition()
358 {
359 pImpl = new WaitConditionImpl;
360 }
361 WaitCondition::~WaitCondition()
362 {
363 delete pImpl;
364 }
366 bool WaitCondition::Wait(Mutex *pmutex, unsigned delay)
367 {
368 return pImpl->Wait(pmutex, delay);
369 }
370 // Notification
371 void WaitCondition::Notify()
372 {
373 pImpl->Notify();
374 }
375 void WaitCondition::NotifyAll()
376 {
377 pImpl->NotifyAll();
378 }
381 // ***** Current thread
383 // Per-thread variable
384 /*
385 static __thread Thread* pCurrentThread = 0;
387 // Static function to return a pointer to the current thread
388 void Thread::InitCurrentThread(Thread *pthread)
389 {
390 pCurrentThread = pthread;
391 }
393 // Static function to return a pointer to the current thread
394 Thread* Thread::GetThread()
395 {
396 return pCurrentThread;
397 }
398 */
401 // *** Thread constructors.
403 Thread::Thread(UPInt stackSize, int processor)
404 {
405 // NOTE: RefCount mode already thread-safe for all Waitable objects.
406 CreateParams params;
407 params.stackSize = stackSize;
408 params.processor = processor;
409 Init(params);
410 }
412 Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
413 int processor, Thread::ThreadState initialState)
414 {
415 CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
416 Init(params);
417 }
419 Thread::Thread(const CreateParams& params)
420 {
421 Init(params);
422 }
424 void Thread::Init(const CreateParams& params)
425 {
426 // Clear the variables
427 ThreadFlags = 0;
428 ThreadHandle = 0;
429 ExitCode = 0;
430 SuspendCount = 0;
431 StackSize = params.stackSize;
432 Processor = params.processor;
433 Priority = params.priority;
435 // Clear Function pointers
436 ThreadFunction = params.threadFunction;
437 UserHandle = params.userHandle;
438 if (params.initialState != NotRunning)
439 Start(params.initialState);
440 }
442 Thread::~Thread()
443 {
444 // Thread should not running while object is being destroyed,
445 // this would indicate ref-counting issue.
446 //OVR_ASSERT(IsRunning() == 0);
448 // Clean up thread.
449 ThreadHandle = 0;
450 }
454 // *** Overridable User functions.
456 // Default Run implementation
457 int Thread::Run()
458 {
459 // Call pointer to function, if available.
460 return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
461 }
462 void Thread::OnExit()
463 {
464 }
467 // Finishes the thread and releases internal reference to it.
468 void Thread::FinishAndRelease()
469 {
470 // Note: thread must be US.
471 ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
472 ThreadFlags |= OVR_THREAD_FINISHED;
474 // Release our reference; this is equivalent to 'delete this'
475 // from the point of view of our thread.
476 Release();
477 }
481 // *** ThreadList - used to track all created threads
483 class ThreadList : public NewOverrideBase
484 {
485 //------------------------------------------------------------------------
486 struct ThreadHashOp
487 {
488 size_t operator()(const Thread* ptr)
489 {
490 return (((size_t)ptr) >> 6) ^ (size_t)ptr;
491 }
492 };
494 HashSet<Thread*, ThreadHashOp> ThreadSet;
495 Mutex ThreadMutex;
496 WaitCondition ThreadsEmpty;
497 // Track the root thread that created us.
498 pthread_t RootThreadId;
500 static ThreadList* volatile pRunningThreads;
502 void addThread(Thread *pthread)
503 {
504 Mutex::Locker lock(&ThreadMutex);
505 ThreadSet.Add(pthread);
506 }
508 void removeThread(Thread *pthread)
509 {
510 Mutex::Locker lock(&ThreadMutex);
511 ThreadSet.Remove(pthread);
512 if (ThreadSet.GetSize() == 0)
513 ThreadsEmpty.Notify();
514 }
516 void finishAllThreads()
517 {
518 // Only original root thread can call this.
519 OVR_ASSERT(pthread_self() == RootThreadId);
521 Mutex::Locker lock(&ThreadMutex);
522 while (ThreadSet.GetSize() != 0)
523 ThreadsEmpty.Wait(&ThreadMutex);
524 }
526 public:
528 ThreadList()
529 {
530 RootThreadId = pthread_self();
531 }
532 ~ThreadList() { }
535 static void AddRunningThread(Thread *pthread)
536 {
537 // Non-atomic creation ok since only the root thread
538 if (!pRunningThreads)
539 {
540 pRunningThreads = new ThreadList;
541 OVR_ASSERT(pRunningThreads);
542 }
543 pRunningThreads->addThread(pthread);
544 }
546 // NOTE: 'pthread' might be a dead pointer when this is
547 // called so it should not be accessed; it is only used
548 // for removal.
549 static void RemoveRunningThread(Thread *pthread)
550 {
551 OVR_ASSERT(pRunningThreads);
552 pRunningThreads->removeThread(pthread);
553 }
555 static void FinishAllThreads()
556 {
557 // This is ok because only root thread can wait for other thread finish.
558 if (pRunningThreads)
559 {
560 pRunningThreads->finishAllThreads();
561 delete pRunningThreads;
562 pRunningThreads = 0;
563 }
564 }
565 };
567 // By default, we have no thread list.
568 ThreadList* volatile ThreadList::pRunningThreads = 0;
571 // FinishAllThreads - exposed publicly in Thread.
572 void Thread::FinishAllThreads()
573 {
574 ThreadList::FinishAllThreads();
575 }
577 // *** Run override
579 int Thread::PRun()
580 {
581 // Suspend us on start, if requested
582 if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
583 {
584 Suspend();
585 ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
586 }
588 // Call the virtual run function
589 ExitCode = Run();
590 return ExitCode;
591 }
596 // *** User overridables
598 bool Thread::GetExitFlag() const
599 {
600 return (ThreadFlags & OVR_THREAD_EXIT) != 0;
601 }
603 void Thread::SetExitFlag(bool exitFlag)
604 {
605 // The below is atomic since ThreadFlags is AtomicInt.
606 if (exitFlag)
607 ThreadFlags |= OVR_THREAD_EXIT;
608 else
609 ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
610 }
613 // Determines whether the thread was running and is now finished
614 bool Thread::IsFinished() const
615 {
616 return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
617 }
618 // Determines whether the thread is suspended
619 bool Thread::IsSuspended() const
620 {
621 return SuspendCount > 0;
622 }
623 // Returns current thread state
624 Thread::ThreadState Thread::GetThreadState() const
625 {
626 if (IsSuspended())
627 return Suspended;
628 if (ThreadFlags & OVR_THREAD_STARTED)
629 return Running;
630 return NotRunning;
631 }
633 // Join thread
634 bool Thread::Join(int maxWaitMs) const
635 {
636 // If polling,
637 if (maxWaitMs == 0)
638 {
639 // Just return if finished
640 return IsFinished();
641 }
642 // If waiting forever,
643 else if (maxWaitMs > 0)
644 {
645 UInt32 t0 = Timer::GetTicksMs();
647 while (!IsFinished())
648 {
649 UInt32 t1 = Timer::GetTicksMs();
651 // If the wait has expired,
652 int delta = (int)(t1 - t0);
653 if (delta >= maxWaitMs)
654 {
655 return false;
656 }
658 Thread::MSleep(10);
659 }
661 return true;
662 }
663 else
664 {
665 while (!IsFinished())
666 {
667 pthread_join(ThreadHandle, NULL);
668 }
669 }
671 return true;
672 }
674 /*
675 static const char* mapsched_policy(int policy)
676 {
677 switch(policy)
678 {
679 case SCHED_OTHER:
680 return "SCHED_OTHER";
681 case SCHED_RR:
682 return "SCHED_RR";
683 case SCHED_FIFO:
684 return "SCHED_FIFO";
686 }
687 return "UNKNOWN";
688 }
689 int policy;
690 sched_param sparam;
691 pthread_getschedparam(pthread_self(), &policy, &sparam);
692 int max_prior = sched_get_priority_max(policy);
693 int min_prior = sched_get_priority_min(policy);
694 printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
695 #include <stdio.h>
696 */
697 // ***** Thread management
699 // The actual first function called on thread start
700 void* Thread_PthreadStartFn(void* phandle)
701 {
702 Thread* pthread = (Thread*)phandle;
703 int result = pthread->PRun();
704 // Signal the thread as done and release it atomically.
705 pthread->FinishAndRelease();
706 // At this point Thread object might be dead; however we can still pass
707 // it to RemoveRunningThread since it is only used as a key there.
708 ThreadList::RemoveRunningThread(pthread);
709 return reinterpret_cast<void*>(result);
710 }
712 int Thread::InitAttr = 0;
713 pthread_attr_t Thread::Attr;
715 /* static */
716 int Thread::GetOSPriority(ThreadPriority p)
717 {
718 OVR_UNUSED(p);
719 return -1;
720 }
722 /* static */
723 Thread::ThreadPriority Thread::GetOVRPriority(int osPriority)
724 {
725 #if defined(OVR_OS_LINUX)
726 return (ThreadPriority)(Thread::NormalPriority - osPriority); // This works for both SCHED_OTHER, SCHED_RR, and SCHED_FIFO.
727 #else
728 // Apple priorities are such that the min is a value less than the max.
729 static int minPriority = sched_get_priority_min(SCHED_FIFO); // We don't have a means to pass a policy type to this function.
730 static int maxPriority = sched_get_priority_max(SCHED_FIFO);
732 return (ThreadPriority)(Thread::NormalPriority - (osPriority - ((minPriority + maxPriority) / 2)));
733 #endif
734 }
737 Thread::ThreadPriority Thread::GetPriority()
738 {
739 int policy;
740 sched_param param;
742 int result = pthread_getschedparam(ThreadHandle, &policy, &param);
744 if(result == 0)
745 {
746 #if !defined(OVR_OS_LINUX)
747 if(policy == SCHED_OTHER)
748 {
749 return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
750 }
751 #endif
753 return GetOVRPriority(param.sched_priority);
754 }
756 return Thread::NormalPriority;
757 }
759 /* static */
760 Thread::ThreadPriority Thread::GetCurrentPriority()
761 {
762 int policy;
763 sched_param param;
764 pthread_t currentThreadId = pthread_self();
766 int result = pthread_getschedparam(currentThreadId, &policy, &param);
768 if(result == 0)
769 {
770 #if !defined(OVR_OS_LINUX)
771 if(policy == SCHED_OTHER)
772 {
773 return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
774 }
775 #endif
777 return GetOVRPriority(param.sched_priority);
778 }
780 return Thread::NormalPriority;
781 }
784 bool Thread::SetPriority(ThreadPriority)
785 {
786 // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
787 // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
788 return false;
789 }
791 /* static */
792 bool Thread::SetCurrentPriority(ThreadPriority)
793 {
794 // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
795 // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
796 return false;
797 }
799 bool Thread::Start(ThreadState initialState)
800 {
801 if (initialState == NotRunning)
802 return 0;
803 if (GetThreadState() != NotRunning)
804 {
805 OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
806 return 0;
807 }
809 if (!InitAttr)
810 {
811 pthread_attr_init(&Attr);
812 pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
813 pthread_attr_setstacksize(&Attr, 128 * 1024);
814 sched_param sparam;
815 sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
816 pthread_attr_setschedparam(&Attr, &sparam);
817 InitAttr = 1;
818 }
820 ExitCode = 0;
821 SuspendCount = 0;
822 ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
824 // AddRef to us until the thread is finished
825 AddRef();
826 ThreadList::AddRunningThread(this);
828 int result;
829 if (StackSize != 128 * 1024 || Priority != NormalPriority)
830 {
831 pthread_attr_t attr;
833 pthread_attr_init(&attr);
834 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
835 pthread_attr_setstacksize(&attr, StackSize);
836 sched_param sparam;
837 sparam.sched_priority = Thread::GetOSPriority(Priority);
838 pthread_attr_setschedparam(&attr, &sparam);
839 result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
840 pthread_attr_destroy(&attr);
841 }
842 else
843 result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
845 if (result)
846 {
847 ThreadFlags = 0;
848 Release();
849 ThreadList::RemoveRunningThread(this);
850 return 0;
851 }
852 return 1;
853 }
856 // Suspend the thread until resumed
857 bool Thread::Suspend()
858 {
859 OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
860 return 0;
861 }
863 // Resumes currently suspended thread
864 bool Thread::Resume()
865 {
866 return 0;
867 }
870 // Quits with an exit code
871 void Thread::Exit(int exitCode)
872 {
873 // Can only exist the current thread
874 // if (GetThread() != this)
875 // return;
877 // Call the virtual OnExit function
878 OnExit();
880 // Signal this thread object as done and release it's references.
881 FinishAndRelease();
882 ThreadList::RemoveRunningThread(this);
884 pthread_exit(reinterpret_cast<void*>(exitCode));
885 }
887 ThreadId GetCurrentThreadId()
888 {
889 return (void*)pthread_self();
890 }
892 // *** Sleep functions
894 /* static */
895 bool Thread::Sleep(unsigned secs)
896 {
897 sleep(secs);
898 return 1;
899 }
900 /* static */
901 bool Thread::MSleep(unsigned msecs)
902 {
903 usleep(msecs*1000);
904 return 1;
905 }
907 /* static */
908 int Thread::GetCPUCount()
909 {
910 #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
911 // http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/sysctlbyname.3.html
912 int cpuCount = 0;
913 size_t len = sizeof(cpuCount);
915 if(sysctlbyname("hw.logicalcpu", &cpuCount, &len, NULL, 0) != 0)
916 cpuCount = 1;
918 return cpuCount;
920 #else // Linux, Android
922 // Alternative: read /proc/cpuinfo
923 #ifdef _SC_NPROCESSORS_ONLN
924 return (int)sysconf(_SC_NPROCESSORS_ONLN);
925 #else
926 return 1;
927 #endif
928 #endif
929 }
932 void Thread::SetThreadName( const char* name )
933 {
934 #if defined (OVR_OS_APPLE)
935 if(ThreadHandle == pthread_self())
936 pthread_setname_np(name);
937 // Else there's nothing we can do.
938 #else
939 if(ThreadHandle != 0)
940 pthread_setname_np(ThreadHandle, name);
941 // Else we can possibly save this name and set it later when the thread starts.
942 #endif
943 }
946 void Thread::SetThreadName(const char* name, ThreadId threadId)
947 {
948 #if defined (OVR_OS_APPLE)
949 if(pthread_equal((pthread_t)threadId, pthread_self()))
950 pthread_setname_np(name);
951 // Else there's no way to set the name of another thread.
952 #else
953 pthread_setname_np((pthread_t)threadId, name);
954 #endif
955 }
958 void Thread::SetCurrentThreadName(const char* name)
959 {
960 #if defined (OVR_OS_APPLE)
961 pthread_setname_np(name);
962 #else
963 pthread_setname_np(pthread_self(), name);
964 #endif
965 }
968 void Thread::GetThreadName(char* name, size_t nameCapacity, ThreadId threadId)
969 {
970 name[0] = 0;
971 pthread_getname_np((pthread_t)threadId, name, nameCapacity);
972 }
975 void Thread::GetCurrentThreadName(char* name, size_t nameCapacity)
976 {
977 name[0] = 0;
978 pthread_getname_np(pthread_self(), name, nameCapacity);
979 }
982 } // namespace OVR
984 #endif // OVR_ENABLE_THREADS