OVR_ThreadsPthread.cpp 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. /************************************************************************************
  2. Filename : OVR_ThreadsPthread.cpp
  3. Content :
  4. Created :
  5. Notes :
  6. Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
  7. Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
  8. you may not use the Oculus VR Rift SDK except in compliance with the License,
  9. which is provided at the time of installation or download, or which
  10. otherwise accompanies this software in either electronic or hard copy form.
  11. You may obtain a copy of the License at
  12. http://www.oculusvr.com/licenses/LICENSE-3.2
  13. Unless required by applicable law or agreed to in writing, the Oculus VR SDK
  14. distributed under the License is distributed on an "AS IS" BASIS,
  15. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. See the License for the specific language governing permissions and
  17. limitations under the License.
  18. ************************************************************************************/
  19. #if !defined(_WIN32) // Skip the entire file under Windows
  20. #include "OVR_Threads.h"
  21. #include "OVR_Hash.h"
  22. #ifdef OVR_ENABLE_THREADS
  23. #include "OVR_Timer.h"
  24. #include "OVR_Log.h"
  25. #include <pthread.h>
  26. #include <sched.h>
  27. #include <time.h>
  28. #include <unistd.h>
  29. #include <sys/time.h>
  30. #include <errno.h>
  31. #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
  32. #include <sys/sysctl.h>
  33. #include <sys/param.h>
  34. #if !defined(OVR_OS_MAC)
  35. #include <pthread_np.h>
  36. #endif
  37. #endif
  38. namespace OVR {
  39. // ***** Mutex implementation
  40. // *** Internal Mutex implementation structure
  41. class MutexImpl : public NewOverrideBase
  42. {
  43. // System mutex or semaphore
  44. pthread_mutex_t SMutex;
  45. bool Recursive;
  46. unsigned LockCount;
  47. pthread_t LockedBy;
  48. friend class WaitConditionImpl;
  49. public:
  50. // Constructor/destructor
  51. MutexImpl(Mutex* pmutex, bool recursive = 1);
  52. ~MutexImpl();
  53. // Locking functions
  54. void DoLock();
  55. bool TryLock();
  56. void Unlock(Mutex* pmutex);
  57. // Returns 1 if the mutes is currently locked
  58. bool IsLockedByAnotherThread(Mutex* pmutex);
  59. bool IsSignaled() const;
  60. };
  61. pthread_mutexattr_t Lock::RecursiveAttr;
  62. bool Lock::RecursiveAttrInit = 0;
  63. // *** Constructor/destructor
  64. MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
  65. {
  66. OVR_UNUSED(pmutex);
  67. Recursive = recursive;
  68. LockCount = 0;
  69. if (Recursive)
  70. {
  71. if (!Lock::RecursiveAttrInit)
  72. {
  73. pthread_mutexattr_init(&Lock::RecursiveAttr);
  74. pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
  75. Lock::RecursiveAttrInit = 1;
  76. }
  77. pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
  78. }
  79. else
  80. pthread_mutex_init(&SMutex, 0);
  81. }
  82. MutexImpl::~MutexImpl()
  83. {
  84. pthread_mutex_destroy(&SMutex);
  85. }
  86. // Lock and try lock
  87. void MutexImpl::DoLock()
  88. {
  89. while (pthread_mutex_lock(&SMutex))
  90. ;
  91. LockCount++;
  92. LockedBy = pthread_self();
  93. }
  94. bool MutexImpl::TryLock()
  95. {
  96. if (!pthread_mutex_trylock(&SMutex))
  97. {
  98. LockCount++;
  99. LockedBy = pthread_self();
  100. return 1;
  101. }
  102. return 0;
  103. }
  104. void MutexImpl::Unlock(Mutex* pmutex)
  105. {
  106. OVR_UNUSED(pmutex);
  107. OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
  108. //unsigned lockCount;
  109. LockCount--;
  110. //lockCount = LockCount;
  111. pthread_mutex_unlock(&SMutex);
  112. }
  113. bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
  114. {
  115. OVR_UNUSED(pmutex);
  116. // There could be multiple interpretations of IsLocked with respect to current thread
  117. if (LockCount == 0)
  118. return 0;
  119. if (pthread_self() != LockedBy)
  120. return 1;
  121. return 0;
  122. }
  123. bool MutexImpl::IsSignaled() const
  124. {
  125. // An mutex is signaled if it is not locked ANYWHERE
  126. // Note that this is different from IsLockedByAnotherThread function,
  127. // that takes current thread into account
  128. return LockCount == 0;
  129. }
  130. // *** Actual Mutex class implementation
  131. Mutex::Mutex(bool recursive)
  132. {
  133. // NOTE: RefCount mode already thread-safe for all waitables.
  134. pImpl = new MutexImpl(this, recursive);
  135. }
  136. Mutex::~Mutex()
  137. {
  138. delete pImpl;
  139. }
  140. // Lock and try lock
  141. void Mutex::DoLock()
  142. {
  143. pImpl->DoLock();
  144. }
  145. bool Mutex::TryLock()
  146. {
  147. return pImpl->TryLock();
  148. }
  149. void Mutex::Unlock()
  150. {
  151. pImpl->Unlock(this);
  152. }
  153. bool Mutex::IsLockedByAnotherThread()
  154. {
  155. return pImpl->IsLockedByAnotherThread(this);
  156. }
  157. //-----------------------------------------------------------------------------------
  158. // ***** Event
  159. bool Event::Wait(unsigned delay)
  160. {
  161. Mutex::Locker lock(&StateMutex);
  162. // Do the correct amount of waiting
  163. if (delay == OVR_WAIT_INFINITE)
  164. {
  165. while(!State)
  166. StateWaitCondition.Wait(&StateMutex);
  167. }
  168. else if (delay)
  169. {
  170. if (!State)
  171. StateWaitCondition.Wait(&StateMutex, delay);
  172. }
  173. bool state = State;
  174. // Take care of temporary 'pulsing' of a state
  175. if (Temporary)
  176. {
  177. Temporary = false;
  178. State = false;
  179. }
  180. return state;
  181. }
  182. void Event::updateState(bool newState, bool newTemp, bool mustNotify)
  183. {
  184. Mutex::Locker lock(&StateMutex);
  185. State = newState;
  186. Temporary = newTemp;
  187. if (mustNotify)
  188. StateWaitCondition.NotifyAll();
  189. }
  190. // ***** Wait Condition Implementation
  191. // Internal implementation class
  192. class WaitConditionImpl : public NewOverrideBase
  193. {
  194. pthread_mutex_t SMutex;
  195. pthread_cond_t Condv;
  196. public:
  197. // Constructor/destructor
  198. WaitConditionImpl();
  199. ~WaitConditionImpl();
  200. // Release mutex and wait for condition. The mutex is re-aqured after the wait.
  201. bool Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  202. // Notify a condition, releasing at one object waiting
  203. void Notify();
  204. // Notify a condition, releasing all objects waiting
  205. void NotifyAll();
  206. };
  207. WaitConditionImpl::WaitConditionImpl()
  208. {
  209. pthread_mutex_init(&SMutex, 0);
  210. pthread_cond_init(&Condv, 0);
  211. }
  212. WaitConditionImpl::~WaitConditionImpl()
  213. {
  214. pthread_mutex_destroy(&SMutex);
  215. pthread_cond_destroy(&Condv);
  216. }
  217. bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  218. {
  219. bool result = 1;
  220. unsigned lockCount = pmutex->pImpl->LockCount;
  221. // Mutex must have been locked
  222. if (lockCount == 0)
  223. return 0;
  224. pthread_mutex_lock(&SMutex);
  225. // Finally, release a mutex or semaphore
  226. if (pmutex->pImpl->Recursive)
  227. {
  228. // Release the recursive mutex N times
  229. pmutex->pImpl->LockCount = 0;
  230. for(unsigned i=0; i<lockCount; i++)
  231. pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  232. }
  233. else
  234. {
  235. pmutex->pImpl->LockCount = 0;
  236. pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  237. }
  238. // Note that there is a gap here between mutex.Unlock() and Wait().
  239. // The other mutex protects this gap.
  240. if (delay == OVR_WAIT_INFINITE)
  241. pthread_cond_wait(&Condv,&SMutex);
  242. else
  243. {
  244. timespec ts;
  245. struct timeval tv;
  246. gettimeofday(&tv, 0);
  247. ts.tv_sec = tv.tv_sec + (delay / 1000);
  248. ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
  249. if (ts.tv_nsec > 999999999)
  250. {
  251. ts.tv_sec++;
  252. ts.tv_nsec -= 1000000000;
  253. }
  254. int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
  255. OVR_ASSERT(r == 0 || r == ETIMEDOUT);
  256. if (r)
  257. result = 0;
  258. }
  259. pthread_mutex_unlock(&SMutex);
  260. // Re-aquire the mutex
  261. for(unsigned i=0; i<lockCount; i++)
  262. pmutex->DoLock();
  263. // Return the result
  264. return result;
  265. }
  266. // Notify a condition, releasing the least object in a queue
  267. void WaitConditionImpl::Notify()
  268. {
  269. pthread_mutex_lock(&SMutex);
  270. pthread_cond_signal(&Condv);
  271. pthread_mutex_unlock(&SMutex);
  272. }
  273. // Notify a condition, releasing all objects waiting
  274. void WaitConditionImpl::NotifyAll()
  275. {
  276. pthread_mutex_lock(&SMutex);
  277. pthread_cond_broadcast(&Condv);
  278. pthread_mutex_unlock(&SMutex);
  279. }
  280. // *** Actual implementation of WaitCondition
  281. WaitCondition::WaitCondition()
  282. {
  283. pImpl = new WaitConditionImpl;
  284. }
  285. WaitCondition::~WaitCondition()
  286. {
  287. delete pImpl;
  288. }
  289. bool WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  290. {
  291. return pImpl->Wait(pmutex, delay);
  292. }
  293. // Notification
  294. void WaitCondition::Notify()
  295. {
  296. pImpl->Notify();
  297. }
  298. void WaitCondition::NotifyAll()
  299. {
  300. pImpl->NotifyAll();
  301. }
  302. // ***** Current thread
  303. // Per-thread variable
  304. /*
  305. static __thread Thread* pCurrentThread = 0;
  306. // Static function to return a pointer to the current thread
  307. void Thread::InitCurrentThread(Thread *pthread)
  308. {
  309. pCurrentThread = pthread;
  310. }
  311. // Static function to return a pointer to the current thread
  312. Thread* Thread::GetThread()
  313. {
  314. return pCurrentThread;
  315. }
  316. */
  317. // *** Thread constructors.
  318. Thread::Thread(UPInt stackSize, int processor)
  319. {
  320. // NOTE: RefCount mode already thread-safe for all Waitable objects.
  321. CreateParams params;
  322. params.stackSize = stackSize;
  323. params.processor = processor;
  324. Init(params);
  325. }
  326. Thread::Thread(Thread::ThreadFn threadFunction, void* userHandle, UPInt stackSize,
  327. int processor, Thread::ThreadState initialState)
  328. {
  329. CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  330. Init(params);
  331. }
  332. Thread::Thread(const CreateParams& params)
  333. {
  334. Init(params);
  335. }
  336. void Thread::Init(const CreateParams& params)
  337. {
  338. // Clear the variables
  339. ThreadFlags = 0;
  340. ThreadHandle = 0;
  341. ExitCode = 0;
  342. SuspendCount = 0;
  343. StackSize = params.stackSize;
  344. Processor = params.processor;
  345. Priority = params.priority;
  346. // Clear Function pointers
  347. ThreadFunction = params.threadFunction;
  348. UserHandle = params.userHandle;
  349. if (params.initialState != NotRunning)
  350. Start(params.initialState);
  351. }
  352. Thread::~Thread()
  353. {
  354. // Thread should not running while object is being destroyed,
  355. // this would indicate ref-counting issue.
  356. //OVR_ASSERT(IsRunning() == 0);
  357. // Clean up thread.
  358. ThreadHandle = 0;
  359. }
  360. // *** Overridable User functions.
  361. // Default Run implementation
  362. int Thread::Run()
  363. {
  364. // Call pointer to function, if available.
  365. return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  366. }
  367. void Thread::OnExit()
  368. {
  369. }
  370. // Finishes the thread and releases internal reference to it.
  371. void Thread::FinishAndRelease()
  372. {
  373. // Note: thread must be US.
  374. ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  375. ThreadFlags |= OVR_THREAD_FINISHED;
  376. // Release our reference; this is equivalent to 'delete this'
  377. // from the point of view of our thread.
  378. Release();
  379. }
  380. // *** ThreadList - used to track all created threads
  381. class ThreadList : public NewOverrideBase
  382. {
  383. //------------------------------------------------------------------------
  384. struct ThreadHashOp
  385. {
  386. size_t operator()(const Thread* ptr)
  387. {
  388. return (((size_t)ptr) >> 6) ^ (size_t)ptr;
  389. }
  390. };
  391. HashSet<Thread*, ThreadHashOp> ThreadSet;
  392. Mutex ThreadMutex;
  393. WaitCondition ThreadsEmpty;
  394. // Track the root thread that created us.
  395. pthread_t RootThreadId;
  396. static ThreadList* volatile pRunningThreads;
  397. void addThread(Thread *pthread)
  398. {
  399. Mutex::Locker lock(&ThreadMutex);
  400. ThreadSet.Add(pthread);
  401. }
  402. void removeThread(Thread *pthread)
  403. {
  404. Mutex::Locker lock(&ThreadMutex);
  405. ThreadSet.Remove(pthread);
  406. if (ThreadSet.GetSize() == 0)
  407. ThreadsEmpty.Notify();
  408. }
  409. void finishAllThreads()
  410. {
  411. // Only original root thread can call this.
  412. OVR_ASSERT(pthread_self() == RootThreadId);
  413. Mutex::Locker lock(&ThreadMutex);
  414. while (ThreadSet.GetSize() != 0)
  415. ThreadsEmpty.Wait(&ThreadMutex);
  416. }
  417. public:
  418. ThreadList()
  419. {
  420. RootThreadId = pthread_self();
  421. }
  422. ~ThreadList() { }
  423. static void AddRunningThread(Thread *pthread)
  424. {
  425. // Non-atomic creation ok since only the root thread
  426. if (!pRunningThreads)
  427. {
  428. pRunningThreads = new ThreadList;
  429. OVR_ASSERT(pRunningThreads);
  430. }
  431. pRunningThreads->addThread(pthread);
  432. }
  433. // NOTE: 'pthread' might be a dead pointer when this is
  434. // called so it should not be accessed; it is only used
  435. // for removal.
  436. static void RemoveRunningThread(Thread *pthread)
  437. {
  438. OVR_ASSERT(pRunningThreads);
  439. pRunningThreads->removeThread(pthread);
  440. }
  441. static void FinishAllThreads()
  442. {
  443. // This is ok because only root thread can wait for other thread finish.
  444. if (pRunningThreads)
  445. {
  446. pRunningThreads->finishAllThreads();
  447. delete pRunningThreads;
  448. pRunningThreads = 0;
  449. }
  450. }
  451. };
  452. // By default, we have no thread list.
  453. ThreadList* volatile ThreadList::pRunningThreads = 0;
  454. // FinishAllThreads - exposed publicly in Thread.
  455. void Thread::FinishAllThreads()
  456. {
  457. ThreadList::FinishAllThreads();
  458. }
  459. // *** Run override
  460. int Thread::PRun()
  461. {
  462. // Suspend us on start, if requested
  463. if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  464. {
  465. Suspend();
  466. ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  467. }
  468. // Call the virtual run function
  469. ExitCode = Run();
  470. return ExitCode;
  471. }
  472. // *** User overridables
  473. bool Thread::GetExitFlag() const
  474. {
  475. return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  476. }
  477. void Thread::SetExitFlag(bool exitFlag)
  478. {
  479. // The below is atomic since ThreadFlags is AtomicInt.
  480. if (exitFlag)
  481. ThreadFlags |= OVR_THREAD_EXIT;
  482. else
  483. ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  484. }
  485. // Determines whether the thread was running and is now finished
  486. bool Thread::IsFinished() const
  487. {
  488. return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  489. }
  490. // Determines whether the thread is suspended
  491. bool Thread::IsSuspended() const
  492. {
  493. return SuspendCount > 0;
  494. }
  495. // Returns current thread state
  496. Thread::ThreadState Thread::GetThreadState() const
  497. {
  498. if (IsSuspended())
  499. return Suspended;
  500. if (ThreadFlags & OVR_THREAD_STARTED)
  501. return Running;
  502. return NotRunning;
  503. }
  504. // Join thread
  505. bool Thread::Join(int maxWaitMs) const
  506. {
  507. // If polling,
  508. if (maxWaitMs == 0)
  509. {
  510. // Just return if finished
  511. return IsFinished();
  512. }
  513. // If waiting forever,
  514. else if (maxWaitMs > 0)
  515. {
  516. UInt32 t0 = Timer::GetTicksMs();
  517. while (!IsFinished())
  518. {
  519. UInt32 t1 = Timer::GetTicksMs();
  520. // If the wait has expired,
  521. int delta = (int)(t1 - t0);
  522. if (delta >= maxWaitMs)
  523. {
  524. return false;
  525. }
  526. Thread::MSleep(10);
  527. }
  528. return true;
  529. }
  530. else
  531. {
  532. while (!IsFinished())
  533. {
  534. pthread_join(ThreadHandle, NULL);
  535. }
  536. }
  537. return true;
  538. }
  539. /*
  540. static const char* mapsched_policy(int policy)
  541. {
  542. switch(policy)
  543. {
  544. case SCHED_OTHER:
  545. return "SCHED_OTHER";
  546. case SCHED_RR:
  547. return "SCHED_RR";
  548. case SCHED_FIFO:
  549. return "SCHED_FIFO";
  550. }
  551. return "UNKNOWN";
  552. }
  553. int policy;
  554. sched_param sparam;
  555. pthread_getschedparam(pthread_self(), &policy, &sparam);
  556. int max_prior = sched_get_priority_max(policy);
  557. int min_prior = sched_get_priority_min(policy);
  558. printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
  559. #include <stdio.h>
  560. */
  561. // ***** Thread management
  562. // The actual first function called on thread start
  563. void* Thread_PthreadStartFn(void* phandle)
  564. {
  565. Thread* pthread = (Thread*)phandle;
  566. int result = pthread->PRun();
  567. // Signal the thread as done and release it atomically.
  568. pthread->FinishAndRelease();
  569. // At this point Thread object might be dead; however we can still pass
  570. // it to RemoveRunningThread since it is only used as a key there.
  571. ThreadList::RemoveRunningThread(pthread);
  572. return reinterpret_cast<void*>(result);
  573. }
  574. int Thread::InitAttr = 0;
  575. pthread_attr_t Thread::Attr;
  576. /* static */
  577. int Thread::GetOSPriority(ThreadPriority p)
  578. {
  579. OVR_UNUSED(p);
  580. return -1;
  581. }
  582. /* static */
  583. Thread::ThreadPriority Thread::GetOVRPriority(int osPriority)
  584. {
  585. #if defined(OVR_OS_LINUX)
  586. return (ThreadPriority)(Thread::NormalPriority - osPriority); // This works for both SCHED_OTHER, SCHED_RR, and SCHED_FIFO.
  587. #else
  588. // Apple priorities are such that the min is a value less than the max.
  589. static int minPriority = sched_get_priority_min(SCHED_FIFO); // We don't have a means to pass a policy type to this function.
  590. static int maxPriority = sched_get_priority_max(SCHED_FIFO);
  591. return (ThreadPriority)(Thread::NormalPriority - (osPriority - ((minPriority + maxPriority) / 2)));
  592. #endif
  593. }
  594. Thread::ThreadPriority Thread::GetPriority()
  595. {
  596. int policy;
  597. sched_param param;
  598. int result = pthread_getschedparam(ThreadHandle, &policy, &param);
  599. if(result == 0)
  600. {
  601. #if !defined(OVR_OS_LINUX)
  602. if(policy == SCHED_OTHER)
  603. {
  604. return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
  605. }
  606. #endif
  607. return GetOVRPriority(param.sched_priority);
  608. }
  609. return Thread::NormalPriority;
  610. }
  611. /* static */
  612. Thread::ThreadPriority Thread::GetCurrentPriority()
  613. {
  614. int policy;
  615. sched_param param;
  616. pthread_t currentThreadId = pthread_self();
  617. int result = pthread_getschedparam(currentThreadId, &policy, &param);
  618. if(result == 0)
  619. {
  620. #if !defined(OVR_OS_LINUX)
  621. if(policy == SCHED_OTHER)
  622. {
  623. return Thread::NormalPriority; //SCHED_OTHER allows only normal priority on BSD-style Unix and Mac OS X.
  624. }
  625. #endif
  626. return GetOVRPriority(param.sched_priority);
  627. }
  628. return Thread::NormalPriority;
  629. }
  630. bool Thread::SetPriority(ThreadPriority)
  631. {
  632. // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
  633. // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
  634. return false;
  635. }
  636. /* static */
  637. bool Thread::SetCurrentPriority(ThreadPriority)
  638. {
  639. // We currently fail. To do: add code to support this via pthread_getschedparam/pthread_attr_setschedparam
  640. // This won't work unless using SCHED_FIFO or SCHED_RR anyway, which require root privileges.
  641. return false;
  642. }
  643. bool Thread::Start(ThreadState initialState)
  644. {
  645. if (initialState == NotRunning)
  646. return 0;
  647. if (GetThreadState() != NotRunning)
  648. {
  649. OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  650. return 0;
  651. }
  652. if (!InitAttr)
  653. {
  654. pthread_attr_init(&Attr);
  655. pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
  656. pthread_attr_setstacksize(&Attr, 128 * 1024);
  657. sched_param sparam;
  658. sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
  659. pthread_attr_setschedparam(&Attr, &sparam);
  660. InitAttr = 1;
  661. }
  662. ExitCode = 0;
  663. SuspendCount = 0;
  664. ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  665. // AddRef to us until the thread is finished
  666. AddRef();
  667. ThreadList::AddRunningThread(this);
  668. int result;
  669. if (StackSize != 128 * 1024 || Priority != NormalPriority)
  670. {
  671. pthread_attr_t attr;
  672. pthread_attr_init(&attr);
  673. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  674. pthread_attr_setstacksize(&attr, StackSize);
  675. sched_param sparam;
  676. sparam.sched_priority = Thread::GetOSPriority(Priority);
  677. pthread_attr_setschedparam(&attr, &sparam);
  678. result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
  679. pthread_attr_destroy(&attr);
  680. }
  681. else
  682. result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
  683. if (result)
  684. {
  685. ThreadFlags = 0;
  686. Release();
  687. ThreadList::RemoveRunningThread(this);
  688. return 0;
  689. }
  690. return 1;
  691. }
  692. // Suspend the thread until resumed
  693. bool Thread::Suspend()
  694. {
  695. OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
  696. return 0;
  697. }
  698. // Resumes currently suspended thread
  699. bool Thread::Resume()
  700. {
  701. return 0;
  702. }
  703. // Quits with an exit code
  704. void Thread::Exit(int exitCode)
  705. {
  706. // Can only exist the current thread
  707. // if (GetThread() != this)
  708. // return;
  709. // Call the virtual OnExit function
  710. OnExit();
  711. // Signal this thread object as done and release it's references.
  712. FinishAndRelease();
  713. ThreadList::RemoveRunningThread(this);
  714. pthread_exit(reinterpret_cast<void*>(exitCode));
  715. }
  716. ThreadId GetCurrentThreadId()
  717. {
  718. return (void*)pthread_self();
  719. }
  720. // *** Sleep functions
  721. /* static */
  722. bool Thread::Sleep(unsigned secs)
  723. {
  724. sleep(secs);
  725. return 1;
  726. }
  727. /* static */
  728. bool Thread::MSleep(unsigned msecs)
  729. {
  730. usleep(msecs*1000);
  731. return 1;
  732. }
  733. /* static */
  734. void Thread::YieldCurrentThread()
  735. {
  736. #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
  737. pthread_yield_np();
  738. #elif defined(OVR_OS_ANDROID)
  739. sched_yield();
  740. #else // Linux
  741. pthread_yield();
  742. #endif
  743. }
  744. /* static */
  745. int Thread::GetCPUCount()
  746. {
  747. #if defined(OVR_OS_MAC) || defined(OVR_OS_BSD)
  748. // http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man3/sysctlbyname.3.html
  749. int cpuCount = 0;
  750. size_t len = sizeof(cpuCount);
  751. if(sysctlbyname("hw.logicalcpu", &cpuCount, &len, NULL, 0) != 0)
  752. cpuCount = 1;
  753. return cpuCount;
  754. #else // Linux, Android
  755. // Alternative: read /proc/cpuinfo
  756. #ifdef _SC_NPROCESSORS_ONLN
  757. return (int)sysconf(_SC_NPROCESSORS_ONLN);
  758. #else
  759. return 1;
  760. #endif
  761. #endif
  762. }
  763. void Thread::SetThreadName( const char* name )
  764. {
  765. #if defined (OVR_OS_APPLE)
  766. if(ThreadHandle == pthread_self())
  767. pthread_setname_np(name);
  768. // Else there's nothing we can do.
  769. #else
  770. if(ThreadHandle != 0)
  771. pthread_setname_np(ThreadHandle, name);
  772. // Else we can possibly save this name and set it later when the thread starts.
  773. #endif
  774. }
  775. void Thread::SetThreadName(const char* name, ThreadId threadId)
  776. {
  777. #if defined (OVR_OS_APPLE)
  778. if(pthread_equal((pthread_t)threadId, pthread_self()))
  779. pthread_setname_np(name);
  780. // Else there's no way to set the name of another thread.
  781. #else
  782. pthread_setname_np((pthread_t)threadId, name);
  783. #endif
  784. }
  785. void Thread::SetCurrentThreadName(const char* name)
  786. {
  787. #if defined (OVR_OS_APPLE)
  788. pthread_setname_np(name);
  789. #else
  790. pthread_setname_np(pthread_self(), name);
  791. #endif
  792. }
  793. void Thread::GetThreadName(char* name, size_t nameCapacity, ThreadId threadId)
  794. {
  795. name[0] = 0;
  796. #if !defined (OVR_OS_ANDROID)
  797. // Android does not have pthread_getname_np (or an equivalent)
  798. pthread_getname_np((pthread_t)threadId, name, nameCapacity);
  799. #endif
  800. }
  801. void Thread::GetCurrentThreadName(char* name, size_t nameCapacity)
  802. {
  803. name[0] = 0;
  804. #if !defined (OVR_OS_ANDROID)
  805. // Android does not have pthread_getname_np (or an equivalent)
  806. pthread_getname_np(pthread_self(), name, nameCapacity);
  807. #endif
  808. }
  809. } // namespace OVR
  810. #endif // OVR_ENABLE_THREADS
  811. #endif // _WIN32