1 /* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007  The Open Thread Group
2  *
3  * This library is open source and may be redistributed and/or modified under
4  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5  * (at your option) any later version.  The full license is in LICENSE file
6  * included with this distribution, and on the openscenegraph.org website.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * OpenSceneGraph Public License for more details.
12 */
13 
14 
15 //
16 // PThread.c++ - C++ Thread class built on top of posix threads.
17 // ~~~~~~~~~~~
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <pthread.h>
24 #if defined(HAVE_PTHREAD_SETAFFINITY_NP) && defined(__FreeBSD__)
25     #include <pthread_np.h>
26 #endif
27 #include <limits.h>
28 
29 #if defined __linux__ || defined __sun || defined __APPLE__ || ANDROID
30 #include <string.h>
31 #include <sys/time.h>
32 #include <sys/resource.h>
33 #if !defined ANDROID
34     #include <sys/unistd.h>
35 #endif
36 #endif
37 #if defined(__hpux)
38 #include <sys/mpctl.h>
39 #endif
40 
41 #if defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
42 #    include <sched.h>
43 #endif
44 #if defined (__FreeBSD__) || defined (__APPLE__) || defined (__MACH__)
45     #include <sys/types.h>
46 #if !defined (__GNU__)
47     #include <sys/sysctl.h>
48 #endif
49 #endif
50 
51 #if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__ANDROID__)
52 #   include <unistd.h>
53 #   include <sys/syscall.h>
54 #endif
55 
56 #if defined(__ANDROID__)
57     #ifndef PAGE_SIZE
58         #define PAGE_SIZE 0x400
59     #endif
60 #endif
61 
62 #include <OpenThreads/Thread>
63 #include "PThreadPrivateData.h"
64 
65 #include <iostream>
66 
67 using namespace OpenThreads;
68 
69 #ifdef DEBUG
70 # define DPRINTF(arg) printf arg
71 #else
72 # define DPRINTF(arg)
73 #endif
74 
75 
76 //-----------------------------------------------------------------------------
77 // Initialize thread master priority level
78 //
79 Thread::ThreadPriority Thread::s_masterThreadPriority =
80                                           Thread::THREAD_PRIORITY_DEFAULT;
81 
82 bool Thread::s_isInitialized = false;
83 pthread_key_t PThreadPrivateData::s_tls_key;
84 
85 struct ThreadCleanupStruct
86 {
87 
88     OpenThreads::Thread *thread;
89     Atomic *runflag;
90 
91 };
92 
93 //-----------------------------------------------------------------------------
94 // This cleanup handler is necessary to ensure that the thread will cleanup
95 // and set its isRunning flag properly.
96 //
thread_cleanup_handler(void * arg)97 void thread_cleanup_handler(void *arg)
98 {
99 
100     ThreadCleanupStruct *tcs = static_cast<ThreadCleanupStruct *>(arg);
101 
102     tcs->thread->cancelCleanup();
103     (*(tcs->runflag)).exchange(0);
104 
105 }
106 
107 //-----------------------------------------------------------------------------
108 // Class to support some static methods necessary for pthread's to work
109 // correctly.
110 //
111 
112 namespace OpenThreads
113 {
114 
115 #if defined(HAVE_PTHREAD_SETAFFINITY_NP) || defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY) || defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
setAffinity(const Affinity & affinity)116 static void setAffinity(const Affinity& affinity)
117 {
118     //std::cout<<"setProcessAffinity : "<< affinity.activeCPUs.size() <<std::endl;
119 #if defined(__FreeBSD__)
120     cpuset_t cpumask;
121 #else
122     cpu_set_t cpumask;
123 #endif
124     CPU_ZERO( &cpumask );
125     unsigned int numprocessors = OpenThreads::GetNumberOfProcessors();
126     if (affinity)
127     {
128         for(Affinity::ActiveCPUs::const_iterator itr = affinity.activeCPUs.begin();
129             itr != affinity.activeCPUs.end();
130             ++itr)
131         {
132             if (*itr<numprocessors)
133             {
134                 //std::cout<<"   setting CPU : "<< *itr<<std::endl;
135                 CPU_SET( *itr, &cpumask );
136             }
137         }
138     }
139     else
140     {
141         // BUG-fix for linux:
142         // Each thread inherits the processor affinity mask from its parent thread.
143         // We need to explicitly set it to all CPUs, if no affinity was specified.
144         for (unsigned int i = 0; i < numprocessors; ++i)
145         {
146             //std::cout<<"   Fallback setting CPU : "<< i<<std::endl;
147 
148             CPU_SET( i, &cpumask );
149         }
150     }
151 
152 #if defined(HAVE_PTHREAD_SETAFFINITY_NP)
153         pthread_setaffinity_np( pthread_self(), sizeof(cpumask), &cpumask);
154 #elif defined(HAVE_THREE_PARAM_SCHED_SETAFFINITY)
155         sched_setaffinity( 0, sizeof(cpumask), &cpumask );
156 #elif defined(HAVE_TWO_PARAM_SCHED_SETAFFINITY)
157         sched_setaffinity( 0, &cpumask );
158 #endif
159 
160 }
161 #else
162 static void setAffinity(const Affinity&)
163 {
164 // No supported.
165 }
166 #endif
167 
168 
169 class ThreadPrivateActions
170 {
171 
172     //-------------------------------------------------------------------------
173     // We're friendly to Thread, so it can issue the methods.
174     //
175     friend class Thread;
176 
177 private:
178 
179     //-------------------------------------------------------------------------
180     // pthreads standard start routine.
181     //
StartThread(void * data)182     static void *StartThread(void *data)
183     {
184 
185         Thread *thread = static_cast<Thread *>(data);
186 
187         PThreadPrivateData *pd = static_cast<PThreadPrivateData *>(thread->_prvData);
188 
189         // set up processor affinity
190         setAffinity( pd->affinity );
191 
192         ThreadCleanupStruct tcs;
193         tcs.thread = thread;
194         tcs.runflag = &pd->_isRunning;
195 
196         // Set local storage so that Thread::CurrentThread() can return the right thing
197         int status = pthread_setspecific(PThreadPrivateData::s_tls_key, thread);
198         if (status)
199         {
200            printf("Error: pthread_setspecific(,) returned error status, status = %d\n",status);
201         }
202 
203         pthread_cleanup_push(thread_cleanup_handler, &tcs);
204 
205 #ifdef ALLOW_PRIORITY_SCHEDULING
206 
207         //---------------------------------------------------------------------
208         // Set the proper scheduling priorities
209         //
210         SetThreadSchedulingParams(thread);
211 
212 #endif // ] ALLOW_PRIORITY_SCHEDULING
213 
214         pd->uniqueId = Thread::CurrentThreadId();
215 
216         pd->setRunning(true);
217 
218         // release the thread that created this thread.
219         pd->threadStartedBlock.release();
220 
221         thread->run();
222 
223         pd->setRunning(false);
224 
225         pthread_cleanup_pop(0);
226 
227         return 0;
228 
229     };
230 
231     //-------------------------------------------------------------------------
232     // Print information related to thread schduling parameters.
233     //
PrintThreadSchedulingInfo(Thread * thread)234     static void PrintThreadSchedulingInfo(Thread *thread) {
235 
236 #ifdef ALLOW_PRIORITY_SCHEDULING // [
237 
238         if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING))
239         {
240 
241             int status, my_policy, min_priority, max_priority;
242             struct sched_param my_param;
243 
244             status = pthread_getschedparam(thread->getProcessId(),
245                            &my_policy,
246                            &my_param);
247 
248             if(status != 0) {
249             printf("THREAD INFO (%d) : Get sched: %s\n",
250                    (int)thread->getProcessId(),
251                    strerror(status));
252             } else {
253             printf(
254                 "THREAD INFO (%d) : Thread running at %s / Priority: %d\n",
255                 (int)thread->getProcessId(),
256                 (my_policy == SCHED_FIFO ? "SCHEDULE_FIFO"
257                  : (my_policy == SCHED_RR ? "SCHEDULE_ROUND_ROBIN"
258                 : (my_policy == SCHED_OTHER ? "SCHEDULE_OTHER"
259                    : "UNKNOWN"))),
260                 my_param.sched_priority);
261 
262             max_priority = sched_get_priority_max(my_policy);
263             min_priority = sched_get_priority_min(my_policy);
264 
265             printf(
266                 "THREAD INFO (%d) : Max priority: %d, Min priority: %d\n",
267                 (int)thread->getProcessId(),
268                 max_priority, min_priority);
269             }
270 
271         }
272         else
273         {
274             printf(
275             "THREAD INFO (%d) POSIX Priority scheduling not available\n",
276             (int)thread->getProcessId());
277         }
278 
279         fflush(stdout);
280 
281 #endif // ] ALLOW_PRIORITY_SCHEDULING
282 
283     }
284 
285     //--------------------------------------------------------------------------
286     // Set thread scheduling parameters.  Unfortunately on Linux, there's no
287     // good way to set this, as pthread_setschedparam is mostly a no-op.
288     //
SetThreadSchedulingParams(Thread * thread)289     static int SetThreadSchedulingParams(Thread *thread)
290     {
291 
292         int status = 0;
293 
294 #ifdef ALLOW_PRIORITY_SCHEDULING // [
295 
296         if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING))
297         {
298 
299             int th_policy;
300             int max_priority, nominal_priority, min_priority;
301             sched_param th_param;
302             pthread_getschedparam(thread->getProcessId(),
303                       &th_policy, &th_param);
304 
305             switch(thread->getSchedulePolicy())
306             {
307 
308                 case Thread::THREAD_SCHEDULE_FIFO:
309                 th_policy = SCHED_FIFO;
310                 break;
311 
312                 case Thread::THREAD_SCHEDULE_ROUND_ROBIN:
313                 th_policy = SCHED_RR;
314                 break;
315 
316                 case Thread::THREAD_SCHEDULE_TIME_SHARE:
317                 th_policy = SCHED_OTHER;
318                 break;
319 
320                 default:
321                 th_policy = SCHED_FIFO;
322                 break;
323             };
324 
325             max_priority = sched_get_priority_max(th_policy);
326             min_priority = sched_get_priority_min(th_policy);
327             nominal_priority = (max_priority + min_priority)/2;
328 
329             switch(thread->getSchedulePriority())
330             {
331 
332                 case Thread::THREAD_PRIORITY_MAX:
333                     th_param.sched_priority = max_priority;
334                     break;
335 
336                 case Thread::THREAD_PRIORITY_HIGH:
337                     th_param.sched_priority = (max_priority + nominal_priority)/2;
338                     break;
339 
340                 case Thread::THREAD_PRIORITY_NOMINAL:
341                     th_param.sched_priority = nominal_priority;
342                     break;
343 
344                 case Thread::THREAD_PRIORITY_LOW:
345                     th_param.sched_priority = (min_priority + nominal_priority)/2;
346                     break;
347 
348                 case Thread::THREAD_PRIORITY_MIN:
349                     th_param.sched_priority = min_priority;
350                     break;
351 
352                 default:
353                     th_param.sched_priority = max_priority;
354                     break;
355 
356             }
357 
358             status = pthread_setschedparam(thread->getProcessId(),
359                            th_policy,
360                            &th_param);
361 
362 
363             if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0)
364             PrintThreadSchedulingInfo(thread);
365 
366         }
367 
368 #endif // ] ALLOW_PRIORITY_SCHEDULING
369 
370     return status;
371     };
372 };
373 
374 }
375 
376 //----------------------------------------------------------------------------
377 //
378 // Description: Set the concurrency level (no-op)
379 //
380 // Use static public
381 //
SetConcurrency(int concurrencyLevel)382 int Thread::SetConcurrency(int concurrencyLevel)
383 {
384 
385 #if defined (HAVE_PTHREAD_SETCONCURRENCY)
386     return pthread_setconcurrency(concurrencyLevel);
387 #else
388     return -1;
389 #endif
390 
391 }
392 
393 //----------------------------------------------------------------------------
394 //
395 // Description: Get the concurrency level
396 //
397 // Use static public
398 //
GetConcurrency()399 int Thread::GetConcurrency()
400 {
401 
402 #if defined (HAVE_PTHREAD_GETCONCURRENCY)
403     return pthread_getconcurrency();
404 #else
405     return -1;
406 #endif
407 
408 }
409 
410 //----------------------------------------------------------------------------
411 //
412 // Description: Constructor
413 //
414 // Use: public.
415 //
Thread()416 Thread::Thread()
417 {
418 
419     if(!s_isInitialized) Init();
420 
421     PThreadPrivateData *pd = new PThreadPrivateData();
422 
423     _prvData = static_cast<void *>(pd);
424 
425 }
426 
427 //----------------------------------------------------------------------------
428 //
429 // Description: Destructor
430 //
431 // Use: public.
432 //
~Thread()433 Thread::~Thread()
434 {
435     PThreadPrivateData *pd = static_cast<PThreadPrivateData *>(_prvData);
436 
437     if(pd->isRunning())
438     {
439         std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl;
440 
441         //---------------------------------------------------------------------
442         // Kill the thread when it is destructed
443         //
444         cancel();
445 
446         // wait till the thread is stopped before finishing.
447         join();
448 
449     }
450 
451     delete pd;
452 
453     _prvData = 0;
454 }
455 
CurrentThread()456 Thread *Thread::CurrentThread()
457 {
458     if(!s_isInitialized) Thread::Init();
459 
460     Thread *thread =
461     static_cast<Thread *>(pthread_getspecific(PThreadPrivateData::s_tls_key));
462 
463     return thread;
464 
465 }
466 
CurrentThreadId()467 size_t Thread::CurrentThreadId()
468 {
469 #if defined(__APPLE__)
470   return (size_t)::syscall(SYS_thread_selfid);
471 #elif defined(__ANDROID__)
472   return (size_t)gettid();
473 #elif defined(__linux__)
474   return (size_t)::syscall(SYS_gettid);
475 #elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) &&	\
476   !defined(__DragonFly__)
477   long  tid;
478   syscall(SYS_thr_self, &tid);
479   return (size_t)tid;
480 #else
481   return (size_t)pthread_self();
482 #endif
483 }
484 
485 
486 
487 //-----------------------------------------------------------------------------
488 //
489 // Description: Initialize Threading
490 //
491 // Use: public.
492 //
Init()493 void Thread::Init()
494 {
495 
496     if(s_isInitialized) return;
497 
498     // Allocate a key to be used to access thread local storage
499     int status = pthread_key_create(&PThreadPrivateData::s_tls_key, NULL);
500     if (status)
501     {
502         printf("Error: pthread_key_create(,) returned error status, status = %d\n",status);
503     }
504 
505 #ifdef ALLOW_PRIORITY_SCHEDULING
506 
507     //--------------------------------------------------------------------------
508     // If we've got priority scheduling, set things to nominal.
509     //
510     if(sysconf(_POSIX_THREAD_PRIORITY_SCHEDULING))
511     {
512 
513         int max_priority, nominal_priority, min_priority;
514 
515         int th_policy;
516         sched_param th_param;
517         pthread_getschedparam(pthread_self(),
518                       &th_policy, &th_param);
519 
520         max_priority = sched_get_priority_max(th_policy);
521         min_priority = sched_get_priority_min(th_policy);
522         nominal_priority = (max_priority + min_priority)/2;
523 
524         th_param.sched_priority = nominal_priority;
525 
526         pthread_setschedparam(pthread_self(),
527                       th_policy,
528                       &th_param);
529 
530         s_masterThreadPriority = Thread::THREAD_PRIORITY_NOMINAL;
531 
532     }
533     else
534     {
535 
536         s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;
537 
538     }
539 
540 #endif // ] ALLOW_PRIORITY_SCHEDULING
541 
542     s_isInitialized = true;
543 
544 }
545 
546 //-----------------------------------------------------------------------------
547 //
548 // Description: Get a unique identifier for this thread.
549 //
550 // Use: public
551 //
getThreadId()552 size_t Thread::getThreadId()
553 {
554 
555     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
556     return pd->uniqueId;
557 }
558 
559 //-----------------------------------------------------------------------------
560 //
561 // Description: Get the thread's process id
562 //
563 // Use: public
564 //
getProcessId()565 size_t Thread::getProcessId()
566 {
567 
568     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
569 
570     if(pd->idSet == false) return (size_t)(pthread_self());
571 
572     return (size_t)(pd->tid);
573 }
574 
SetProcessorAffinityOfCurrentThread(const Affinity & affinity)575 int OpenThreads::SetProcessorAffinityOfCurrentThread(const Affinity& affinity)
576 {
577     Thread::Init();
578 
579     Thread* thread = Thread::CurrentThread();
580     if (thread)
581     {
582         return thread->setProcessorAffinity(affinity);
583     }
584     else
585     {
586         // set up processor affinity
587         setAffinity( affinity );
588     }
589 
590     return -1;
591 }
592 
593 //-----------------------------------------------------------------------------
594 //
595 // Description: Set the thread's processor affinity
596 //
597 // Use: public
598 //
setProcessorAffinity(const Affinity & affinity)599 int Thread::setProcessorAffinity(const Affinity& affinity)
600 {
601     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
602     pd->affinity = affinity;
603 
604     if (pd->isRunning() && Thread::CurrentThread()==this)
605     {
606         setAffinity( affinity );
607     }
608 
609     return -1;
610 
611 }
612 
613 //-----------------------------------------------------------------------------
614 //
615 // Description: Determine if the thread is running
616 //
617 // Use: public
618 //
isRunning()619 bool Thread::isRunning()
620 {
621     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
622     return pd->isRunning();
623 
624 }
625 
626 //-----------------------------------------------------------------------------
627 //
628 // Description: Start the thread.
629 //
630 // Use: public
631 //
start()632 int Thread::start() {
633 
634     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
635     if (pd->isRunning())
636     {
637         return 0;
638     }
639 
640     int status;
641     pthread_attr_t thread_attr;
642 
643     status = pthread_attr_init( &thread_attr );
644     if(status != 0)
645     {
646         return status;
647     }
648 
649     //-------------------------------------------------------------------------
650     // Set the stack size if requested, but not less than a platform reasonable
651     // value.
652     //
653     if(pd->stackSize)
654     {
655 #ifdef PTHREAD_STACK_MIN
656         if(pd->stackSize < PTHREAD_STACK_MIN)
657             pd->stackSize = PTHREAD_STACK_MIN;
658 #endif
659         status = pthread_attr_setstacksize( &thread_attr, pd->stackSize);
660         if(status != 0)
661         {
662             return status;
663         }
664     }
665 
666     //-------------------------------------------------------------------------
667     // Now get what we actually have...
668     //
669     size_t size;
670     status = pthread_attr_getstacksize( &thread_attr, &size);
671     if(status != 0)
672     {
673         return status;
674     }
675     pd->stackSize = size;
676 
677     //-------------------------------------------------------------------------
678     // Prohibit the stack size from being changed.
679     //
680     pd->stackSizeLocked = true;
681 
682 #ifdef ALLOW_PRIORITY_SCHEDULING
683 
684     status = pthread_attr_setinheritsched( &thread_attr,
685                        PTHREAD_EXPLICIT_SCHED );
686 
687     if(status != 0)
688     {
689         return status;
690     }
691 
692     pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM);
693 
694 #endif // ] ALLOW_PRIORITY_SCHEDULING
695 
696 
697     pd->threadStartedBlock.reset();
698 
699     status = pthread_create(&(pd->tid), &thread_attr,
700                            ThreadPrivateActions::StartThread,
701                            static_cast<void *>(this));
702 
703     if(status == 0)
704     {
705         // wait till the thread has actually started.
706         pd->threadStartedBlock.block();
707 
708         pd->idSet = true;
709     }
710 
711     return status;
712 }
713 
714 //-----------------------------------------------------------------------------
715 //
716 // Description: Alternate thread start routine.
717 //
718 // Use: public
719 //
startThread()720 int Thread::startThread()
721 {
722     if (_prvData) return start();
723     else return 0;
724 }
725 
726 //-----------------------------------------------------------------------------
727 //
728 // Description: detach the thread.
729 //
730 // Use: public
731 //
detach()732 int Thread::detach()
733 {
734     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
735     return pthread_detach(pd->tid);
736 }
737 
738 //-----------------------------------------------------------------------------
739 //
740 // Description: Join the thread.
741 //
742 // Use: public
743 //
join()744 int Thread::join()
745 {
746 
747     void *threadResult = 0; // Dummy var.
748     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
749     return pthread_join(pd->tid, &threadResult);
750 
751 }
752 
753 //-----------------------------------------------------------------------------
754 //
755 // Description: test the cancel state of the thread.
756 //
757 // Use: public
758 //
testCancel()759 int Thread::testCancel()
760 {
761 #if defined(HAVE_PTHREAD_TESTCANCEL)
762     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
763 
764     if(pthread_self() != pd->tid)
765     return -1;
766 
767     pthread_testcancel();
768 
769     return 0;
770 #else
771     return 0;
772 #endif
773 }
774 
775 
776 //-----------------------------------------------------------------------------
777 //
778 // Description: Cancel the thread.
779 //
780 // Use: public
781 //
cancel()782 int Thread::cancel()
783 {
784 #if defined(HAVE_PTHREAD_CANCEL)
785     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
786     if (pd->isRunning())
787     {
788         pd->isCanceled = true;
789         int status = pthread_cancel(pd->tid);
790         return status;
791     }
792     return 0;
793 #else
794     return 0;
795 #endif
796 }
797 
798 //-----------------------------------------------------------------------------
799 //
800 // Description: Disable cancelibility
801 //
802 // Use: public
803 //
setCancelModeDisable()804 int Thread::setCancelModeDisable()
805 {
806 #if defined(HAVE_PTHREAD_SETCANCELSTATE)
807     return pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, 0 );
808 #else
809     return 0;
810 #endif
811 }
812 
813 //-----------------------------------------------------------------------------
814 //
815 // Description: set the thread to cancel immediately
816 //
817 // Use: public
818 //
setCancelModeAsynchronous()819 int Thread::setCancelModeAsynchronous() {
820 
821 #if defined(HAVE_PTHREAD_SETCANCELSTATE)
822     int status = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
823     if(status != 0) return status;
824 
825     return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
826 #else
827     return 0;
828 #endif
829 }
830 
831 //-----------------------------------------------------------------------------
832 //
833 // Description: set the thread to cancel at the next convenient point.
834 //
835 // Use: public
836 //
setCancelModeDeferred()837 int Thread::setCancelModeDeferred() {
838 
839 #if defined(HAVE_PTHREAD_SETCANCELSTATE)
840     int status = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
841     if(status != 0) return status;
842 
843     return pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, 0);
844 #else
845     return 0;
846 #endif
847 }
848 
849 //-----------------------------------------------------------------------------
850 //
851 // Description: Set the thread's schedule priority (if able)
852 //
853 // Use: public
854 //
setSchedulePriority(ThreadPriority priority)855 int Thread::setSchedulePriority(ThreadPriority priority) {
856 
857 #ifdef ALLOW_PRIORITY_SCHEDULING
858 
859     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
860 
861     pd->threadPriority = priority;
862 
863     if(pd->isRunning())
864         return ThreadPrivateActions::SetThreadSchedulingParams(this);
865     else
866         return 0;
867 
868 #else
869     return -1;
870 #endif
871 
872 }
873 
874 //-----------------------------------------------------------------------------
875 //
876 // Description: Get the thread's schedule priority (if able)
877 //
878 // Use: public
879 //
getSchedulePriority()880 int Thread::getSchedulePriority() {
881 
882     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
883 
884     return pd->threadPriority;
885 
886 }
887 
888 //-----------------------------------------------------------------------------
889 //
890 // Description: Set the thread's scheduling policy (if able)
891 //
892 // Use: public
893 //
setSchedulePolicy(ThreadPolicy policy)894 int Thread::setSchedulePolicy(ThreadPolicy policy)
895 {
896 
897 #ifdef ALLOW_PRIORITY_SCHEDULING
898 
899     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
900 
901     pd->threadPolicy = policy;
902 
903     if(pd->isRunning())
904     return ThreadPrivateActions::SetThreadSchedulingParams(this);
905     else
906     return 0;
907 #else
908     return -1;
909 #endif
910 
911 }
912 
913 //-----------------------------------------------------------------------------
914 //
915 // Description: Set the thread's scheduling policy (if able)
916 //
917 // Use: public
918 //
getSchedulePolicy()919 int Thread::getSchedulePolicy()
920 {
921 
922     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
923 
924     return pd->threadPolicy;
925 
926 }
927 
928 
929 //-----------------------------------------------------------------------------
930 //
931 // Description: Set the thread's desired stack size
932 //
933 // Use: public
934 //
setStackSize(size_t stackSize)935 int Thread::setStackSize(size_t stackSize) {
936 
937     PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
938 
939     if(pd->stackSizeLocked == true) return 13;  // EACESS
940 
941     pd->stackSize = stackSize;
942 
943     return 0;
944 
945 }
946 
947 //-----------------------------------------------------------------------------
948 //
949 // Description: Get the thread's stack size.
950 //
951 // Use: public
952 //
getStackSize()953 size_t Thread::getStackSize()
954 {
955 
956    PThreadPrivateData *pd = static_cast<PThreadPrivateData *> (_prvData);
957 
958    return pd->stackSize;
959 
960 }
961 
962 //-----------------------------------------------------------------------------
963 //
964 // Description:  Print the thread's scheduling information to stdout.
965 //
966 // Use: public
967 //
printSchedulingInfo()968 void Thread::printSchedulingInfo()
969 {
970 
971     ThreadPrivateActions::PrintThreadSchedulingInfo(this);
972 
973 }
974 
975 //-----------------------------------------------------------------------------
976 //
977 // Description:  Yield the processor
978 //
979 // Use: protected
980 //
YieldCurrentThread()981 int Thread::YieldCurrentThread()
982 {
983 #if defined(HAVE_PTHREAD_YIELD)
984     pthread_yield();
985     return 0;
986 #elif defined(HAVE_SCHED_YIELD)
987     return sched_yield();
988 #else
989     return -1;
990 #endif
991 }
992 
993 // Description:  sleep
994 //
995 // Use: public
996 //
microSleep(unsigned int microsec)997 int Thread::microSleep(unsigned int microsec)
998 {
999 #if !defined(__ANDROID__)
1000     return ::usleep(microsec);
1001 #else
1002     ::usleep(microsec);
1003     return 0;
1004 #endif
1005 }
1006 
1007 
1008 
1009 //-----------------------------------------------------------------------------
1010 //
1011 // Description:  Get the number of processors
1012 //
GetNumberOfProcessors()1013 int OpenThreads::GetNumberOfProcessors()
1014 {
1015 #if defined(__linux__) || defined(__GNU__)
1016    long ret = sysconf(_SC_NPROCESSORS_ONLN);
1017    if (ret == -1)
1018       return 0;
1019    return ret;
1020 #elif defined(__sun__)
1021    long ret = sysconf(_SC_NPROCESSORS_ONLN);
1022    if (ret == -1)
1023       return 0;
1024    return ret;
1025 #elif defined(__hpux)
1026    int ret = mpctl(MPC_GETNUMSPUS, 0, NULL);
1027    if (ret == -1)
1028       return 0;
1029    return ret;
1030 #elif defined(__FreeBSD__) || defined(__APPLE__) || defined(__MACH__)
1031    uint64_t num_cpus = 0;
1032    size_t num_cpus_length = sizeof(num_cpus);
1033 #if defined(__FreeBSD__)
1034    sysctlbyname("hw.ncpu", &num_cpus, &num_cpus_length, NULL, 0);
1035 #else
1036    sysctlbyname("hw.activecpu", &num_cpus, &num_cpus_length, NULL, 0);
1037 #endif
1038    return num_cpus;
1039 #else
1040    return 1;
1041 #endif
1042 }
1043 
1044