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