Imported Upstream version 3.2.2
[debian/gnuradio] / omnithread / posix.cc
1 //                              Package : omnithread
2 // omnithread/posix.cc          Created : 7/94 tjr
3 //
4 //    Copyright (C) 2006 Free Software Foundation, Inc.
5 //    Copyright (C) 1994-1999 AT&T Laboratories Cambridge
6 //
7 //    This file is part of the omnithread library
8 //
9 //    The omnithread library is free software; you can redistribute it and/or
10 //    modify it under the terms of the GNU Library General Public
11 //    License as published by the Free Software Foundation; either
12 //    version 2 of the License, or (at your option) any later version.
13 //
14 //    This library is distributed in the hope that it will be useful,
15 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //    Library General Public License for more details.
18 //
19 //    You should have received a copy of the GNU Library General Public
20 //    License along with this library; if not, write to the Free
21 //    Software Foundation, Inc., 51 Franklin Street, Boston, MA  
22 //    02110-1301, USA
23 //
24
25 //
26 // Implementation of OMNI thread abstraction for posix threads
27 //
28 // The source below tests for the definition of the macros:
29 //     PthreadDraftVersion
30 //     PthreadSupportThreadPriority
31 //     NoNanoSleep
32 //     NeedPthreadInit
33 //
34 // As different draft versions of the pthread standard P1003.4a/P1003.1c
35 // define slightly different APIs, the macro 'PthreadDraftVersion'
36 // identifies the draft version supported by this particular platform.
37 //
38 // Some unix variants do not support thread priority unless a real-time
39 // kernel option is installed. The macro 'PthreadSupportThreadPriority',
40 // if defined, enables the use of thread priority. If it is not defined,
41 // setting or changing thread priority will be silently ignored.
42 //
43 // nanosleep() is defined in Posix P1003.4 since Draft 9 (?).
44 // Not all platforms support this standard. The macro 'NoNanoSleep'
45 // identifies platform that don't.
46 //
47
48 #include <config.h>
49 #include <stdlib.h>
50 #include <errno.h>
51 #include <time.h>
52 #include <gnuradio/omnithread.h>
53
54 #if (PthreadDraftVersion == 0)
55 #error "PthreadDraftVersion not defined.  If not sure, define it to 10"
56 #endif
57
58 #ifdef HAVE_NANOSLEEP
59 #undef NoNanoSleep
60 #else
61 #define NoNanoSleep
62 #endif
63
64 #ifdef HAVE_SYS_TIME_H
65 // typedef of struct timeval and gettimeofday();
66 #include <sys/time.h>
67 #include <unistd.h>
68 #endif
69
70 #if defined(__linux__) && defined(_MIT_POSIX_THREADS)
71 #include <pthread/mit/sys/timers.h>
72 #endif
73
74 #if defined(__irix__) && defined(PthreadSupportThreadPriority)
75 #if _POSIX_THREAD_PRIORITY_SCHEDULING
76 #include <sched.h>
77 #endif
78 #endif
79
80 #if 1
81 #define DB(x) // x
82 #else
83 #define DB(x) x
84 #include <iostream>
85 using std::cerr;
86 using std::endl;
87 #endif
88
89 #if (PthreadDraftVersion <= 6)
90 #define ERRNO(x) (((x) != 0) ? (errno) : 0)
91 #ifdef __VMS
92 // pthread_setprio returns old priority on success (draft version 4:
93 // OpenVms version < 7)
94 #define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); }
95 #else
96 #define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); }
97 #endif
98 #else
99 #define ERRNO(x) (x)
100 #define THROW_ERRORS(x) { int rc = (x); \
101                           if (rc != 0) throw omni_thread_fatal(rc); }
102 #endif
103
104
105
106 ///////////////////////////////////////////////////////////////////////////
107 //
108 // Mutex
109 //
110 ///////////////////////////////////////////////////////////////////////////
111
112
113 omni_mutex::omni_mutex(void)
114 {
115 #if (PthreadDraftVersion == 4)
116     THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default));
117 #else
118     THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0));
119 #endif
120 }
121
122 omni_mutex::~omni_mutex(void)
123 {
124     THROW_ERRORS(pthread_mutex_destroy(&posix_mutex));
125 }
126
127
128 ///////////////////////////////////////////////////////////////////////////
129 //
130 // Condition variable
131 //
132 ///////////////////////////////////////////////////////////////////////////
133
134
135 omni_condition::omni_condition(omni_mutex* m) : mutex(m)
136 {
137 #if (PthreadDraftVersion == 4)
138     THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default));
139 #else
140     THROW_ERRORS(pthread_cond_init(&posix_cond, 0));
141 #endif
142 }
143
144 omni_condition::~omni_condition(void)
145 {
146     THROW_ERRORS(pthread_cond_destroy(&posix_cond));
147 }
148
149 void
150 omni_condition::wait(void)
151 {
152     THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex));
153 }
154
155 int
156 omni_condition::timedwait(unsigned long secs, unsigned long nanosecs)
157 {
158     timespec rqts = { secs, nanosecs };
159
160 again:
161     int rc = ERRNO(pthread_cond_timedwait(&posix_cond,
162                                           &mutex->posix_mutex, &rqts));
163     if (rc == 0)
164         return 1;
165
166 #if (PthreadDraftVersion <= 6)
167     if (rc == EAGAIN)
168         return 0;
169 #endif
170
171     // Some versions of unix produces this errno when the wait was
172     // interrupted by a unix signal or fork.
173     // Some versions of the glibc 2.0.x produces this errno when the 
174     // program is debugged under gdb. Straightly speaking this is non-posix
175     // compliant. We catch this here to make debugging possible.
176     if (rc == EINTR)
177       goto again;
178
179     if (rc == ETIMEDOUT)
180         return 0;
181
182     throw omni_thread_fatal(rc);
183 #ifdef _MSC_VER
184     return 0;
185 #endif
186 }
187
188 void
189 omni_condition::signal(void)
190 {
191     THROW_ERRORS(pthread_cond_signal(&posix_cond));
192 }
193
194 void
195 omni_condition::broadcast(void)
196 {
197     THROW_ERRORS(pthread_cond_broadcast(&posix_cond));
198 }
199
200
201
202 ///////////////////////////////////////////////////////////////////////////
203 //
204 // Counting (or binary) semaphore
205 //
206 ///////////////////////////////////////////////////////////////////////////
207
208
209 omni_semaphore::omni_semaphore(unsigned int initial, unsigned int _max_count) : c(&m)
210 {
211     value = initial;
212     max_count = _max_count;
213     if (value < 0 || max_count < 1)
214       throw omni_thread_fatal(0);
215 }
216
217 omni_semaphore::~omni_semaphore(void)
218 {
219 }
220
221 void
222 omni_semaphore::wait(void)
223 {
224     omni_mutex_lock l(m);
225
226     while (value == 0)
227         c.wait();
228
229     value--;
230 }
231
232 int
233 omni_semaphore::trywait(void)
234 {
235     omni_mutex_lock l(m);
236
237     if (value == 0)
238         return 0;
239
240     value--;
241     return 1;
242 }
243
244 void
245 omni_semaphore::post(void)
246 {
247     {
248         omni_mutex_lock l(m);
249         if (value < max_count)
250           value++;
251     }
252
253     c.signal();
254 }
255
256
257
258 ///////////////////////////////////////////////////////////////////////////
259 //
260 // Thread
261 //
262 ///////////////////////////////////////////////////////////////////////////
263
264
265 //
266 // static variables
267 //
268
269 omni_mutex* omni_thread::next_id_mutex;
270 int omni_thread::next_id = 0;
271
272 static pthread_key_t self_key;
273
274 #ifdef PthreadSupportThreadPriority
275 static int lowest_priority;
276 static int normal_priority;
277 static int highest_priority;
278 #endif
279
280 #if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
281 // omniORB requires a larger stack size than the default (21120) on OSF/1
282 static size_t stack_size = 32768;
283 #elif defined(__rtems__)
284 static size_t stack_size = ThreadStackSize;
285 #elif defined(__aix__)
286 static size_t stack_size = 262144;
287 #else
288 static size_t stack_size = 0;
289 #endif
290
291 //
292 // Initialisation function (gets called before any user code).
293 //
294
295 static int& count() {
296   static int the_count = 0;
297   return the_count;
298 }
299
300 omni_thread::init_t::init_t(void)
301 {
302     if (count()++ != 0) // only do it once however many objects get created.
303         return;
304
305     DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft "
306        << PthreadDraftVersion << ") implementation initialising\n");
307
308 #ifdef NeedPthreadInit
309
310     pthread_init();
311
312 #endif
313
314 #if (PthreadDraftVersion == 4)
315     THROW_ERRORS(pthread_keycreate(&self_key, NULL));
316 #else
317     THROW_ERRORS(pthread_key_create(&self_key, NULL));
318 #endif
319
320 #ifdef PthreadSupportThreadPriority
321
322 #if defined(__osf1__) && defined(__alpha__) || defined(__VMS)
323
324     lowest_priority = PRI_OTHER_MIN;
325     highest_priority = PRI_OTHER_MAX;
326
327 #elif defined(__hpux__)
328
329     lowest_priority = PRI_OTHER_MIN;
330     highest_priority = PRI_OTHER_MAX;
331
332 #elif defined(__sunos__) && (__OSVERSION__ == 5)
333
334     // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0
335
336     lowest_priority  = 1;
337     highest_priority = 3;
338
339 #else
340
341     lowest_priority = sched_get_priority_min(SCHED_FIFO);
342     highest_priority = sched_get_priority_max(SCHED_FIFO);
343
344 #endif
345
346     switch (highest_priority - lowest_priority) {
347
348     case 0:
349     case 1:
350         normal_priority = lowest_priority;
351         break;
352
353     default:
354         normal_priority = lowest_priority + 1;
355         break;
356     }
357
358 #endif   /* PthreadSupportThreadPriority */
359
360     next_id_mutex = new omni_mutex;
361
362     //
363     // Create object for this (i.e. initial) thread.
364     //
365
366     omni_thread* t = new omni_thread;
367
368     t->_state = STATE_RUNNING;
369
370     t->posix_thread = pthread_self ();
371
372     DB(cerr << "initial thread " << t->id() << endl);
373
374     THROW_ERRORS(pthread_setspecific(self_key, (void*)t));
375
376 #ifdef PthreadSupportThreadPriority
377
378 #if (PthreadDraftVersion == 4)
379
380     THROW_ERRORS(pthread_setprio(t->posix_thread,
381                                  posix_priority(PRIORITY_NORMAL)));
382
383 #elif (PthreadDraftVersion == 6)
384
385     pthread_attr_t attr;
386     pthread_attr_init(&attr);
387
388     THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL)));
389
390     THROW_ERRORS(pthread_setschedattr(t->posix_thread, attr));
391
392 #else
393
394     struct sched_param sparam;
395
396     sparam.sched_priority = posix_priority(PRIORITY_NORMAL);
397
398     THROW_ERRORS(pthread_setschedparam(t->posix_thread, SCHED_OTHER, &sparam));
399
400 #endif   /* PthreadDraftVersion */
401
402 #endif   /* PthreadSupportThreadPriority */
403 }
404
405 omni_thread::init_t::~init_t(void)
406 {
407     if (--count() != 0) return;
408
409     omni_thread* self = omni_thread::self();
410     if (!self) return;
411
412     pthread_setspecific(self_key, 0);
413     delete self;
414
415     delete next_id_mutex;
416 }
417
418 //
419 // Wrapper for thread creation.
420 //
421
422 extern "C" void* 
423 omni_thread_wrapper(void* ptr)
424 {
425     omni_thread* me = (omni_thread*)ptr;
426
427     DB(cerr << "omni_thread_wrapper: thread " << me->id()
428        << " started\n");
429
430     THROW_ERRORS(pthread_setspecific(self_key, me));
431
432     //
433     // Now invoke the thread function with the given argument.
434     //
435
436     if (me->fn_void != NULL) {
437         (*me->fn_void)(me->thread_arg);
438         omni_thread::exit();
439     }
440
441     if (me->fn_ret != NULL) {
442         void* return_value = (*me->fn_ret)(me->thread_arg);
443         omni_thread::exit(return_value);
444     }
445
446     if (me->detached) {
447         me->run(me->thread_arg);
448         omni_thread::exit();
449     } else {
450         void* return_value = me->run_undetached(me->thread_arg);
451         omni_thread::exit(return_value);
452     }
453
454     // should never get here.
455
456     return NULL;
457 }
458
459
460 //
461 // Constructors for omni_thread - set up the thread object but don't
462 // start it running.
463 //
464
465 // construct a detached thread running a given function.
466
467 omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri)
468 {
469     common_constructor(arg, pri, 1);
470     fn_void = fn;
471     fn_ret = NULL;
472 }
473
474 // construct an undetached thread running a given function.
475
476 omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri)
477 {
478     common_constructor(arg, pri, 0);
479     fn_void = NULL;
480     fn_ret = fn;
481 }
482
483 // construct a thread which will run either run() or run_undetached().
484
485 omni_thread::omni_thread(void* arg, priority_t pri)
486 {
487     common_constructor(arg, pri, 1);
488     fn_void = NULL;
489     fn_ret = NULL;
490 }
491
492 // common part of all constructors.
493
494 void
495 omni_thread::common_constructor(void* arg, priority_t pri, int det)
496 {
497     _state = STATE_NEW;
498     _priority = pri;
499
500     next_id_mutex->lock();
501     _id = next_id++;
502     next_id_mutex->unlock();
503
504     thread_arg = arg;
505     detached = det;     // may be altered in start_undetached()
506
507     _dummy       = 0;
508     _values      = 0;
509     _value_alloc = 0;
510     // posix_thread is set up in initialisation routine or start().
511 }
512
513
514 //
515 // Destructor for omni_thread.
516 //
517
518 omni_thread::~omni_thread(void)
519 {
520     DB(cerr << "destructor called for thread " << id() << endl);
521     if (_values) {
522         for (key_t i=0; i < _value_alloc; i++) {
523             if (_values[i]) {
524                 delete _values[i];
525             }
526         }
527         delete [] _values;
528     }
529 }
530
531
532 //
533 // Start the thread
534 //
535
536 void
537 omni_thread::start(void)
538 {
539     omni_mutex_lock l(mutex);
540
541     if (_state != STATE_NEW)
542         throw omni_thread_invalid();
543
544     pthread_attr_t attr;
545
546 #if (PthreadDraftVersion == 4)
547     pthread_attr_create(&attr);
548 #else
549     pthread_attr_init(&attr);
550 #endif
551
552 #if (PthreadDraftVersion == 8)
553     pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED);
554 #endif
555
556 #ifdef PthreadSupportThreadPriority
557
558 #if (PthreadDraftVersion <= 6)
559
560     THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(_priority)));
561
562 #else
563
564     struct sched_param sparam;
565
566     sparam.sched_priority = posix_priority(_priority);
567
568     THROW_ERRORS(pthread_attr_setschedparam(&attr, &sparam));
569
570 #endif  /* PthreadDraftVersion */
571
572 #endif  /* PthreadSupportThreadPriority */
573
574 #if !defined(__linux__)
575     if (stack_size) {
576       THROW_ERRORS(pthread_attr_setstacksize(&attr, stack_size));
577     }
578 #endif
579
580
581 #if (PthreadDraftVersion == 4)
582     THROW_ERRORS(pthread_create(&posix_thread, attr, omni_thread_wrapper,
583                                 (void*)this));
584     pthread_attr_delete(&attr);
585 #else
586     THROW_ERRORS(pthread_create(&posix_thread, &attr, omni_thread_wrapper,
587                                 (void*)this));
588     pthread_attr_destroy(&attr);
589 #endif
590
591     _state = STATE_RUNNING;
592
593     if (detached) {
594
595 #if (PthreadDraftVersion <= 6)
596         THROW_ERRORS(pthread_detach(&posix_thread));
597 #else
598         THROW_ERRORS(pthread_detach(posix_thread));
599 #endif
600     }
601 }
602
603
604 //
605 // Start a thread which will run the member function run_undetached().
606 //
607
608 void
609 omni_thread::start_undetached(void)
610 {
611     if ((fn_void != NULL) || (fn_ret != NULL))
612         throw omni_thread_invalid();
613
614     detached = 0;
615     start();
616 }
617
618
619 //
620 // join - simply check error conditions & call pthread_join.
621 //
622
623 void
624 omni_thread::join(void** status)
625 {
626     mutex.lock();
627
628     if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
629         mutex.unlock();
630         throw omni_thread_invalid();
631     }
632
633     mutex.unlock();
634
635     if (this == self())
636         throw omni_thread_invalid();
637
638     if (detached)
639         throw omni_thread_invalid();
640
641     DB(cerr << "omni_thread::join: doing pthread_join\n");
642
643     THROW_ERRORS(pthread_join(posix_thread, status));
644
645     DB(cerr << "omni_thread::join: pthread_join succeeded\n");
646
647 #if (PthreadDraftVersion == 4)
648     // With draft 4 pthreads implementations (HPUX 10.x and
649     // Digital Unix 3.2), have to detach the thread after 
650     // join. If not, the storage for the thread will not be
651     // be reclaimed.
652     THROW_ERRORS(pthread_detach(&posix_thread));
653 #endif
654
655     delete this;
656 }
657
658
659 //
660 // Change this thread's priority.
661 //
662
663 void
664 omni_thread::set_priority(priority_t pri)
665 {
666     omni_mutex_lock l(mutex);
667
668     if (_state != STATE_RUNNING)
669         throw omni_thread_invalid();
670
671     _priority = pri;
672
673 #ifdef PthreadSupportThreadPriority
674
675 #if (PthreadDraftVersion == 4)
676
677     THROW_ERRORS(pthread_setprio(posix_thread, posix_priority(pri)));
678
679 #elif (PthreadDraftVersion == 6)
680
681     pthread_attr_t attr;
682     pthread_attr_init(&attr);
683
684     THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(pri)));
685
686     THROW_ERRORS(pthread_setschedattr(posix_thread, attr));
687
688 #else
689
690     struct sched_param sparam;
691
692     sparam.sched_priority = posix_priority(pri);
693
694     THROW_ERRORS(pthread_setschedparam(posix_thread, SCHED_OTHER, &sparam));
695
696 #endif   /* PthreadDraftVersion */
697
698 #endif   /* PthreadSupportThreadPriority */
699 }
700
701
702 //
703 // create - construct a new thread object and start it running.  Returns thread
704 // object if successful, null pointer if not.
705 //
706
707 // detached version
708
709 omni_thread*
710 omni_thread::create(void (*fn)(void*), void* arg, priority_t pri)
711 {
712     omni_thread* t = new omni_thread(fn, arg, pri);
713
714     t->start();
715
716     return t;
717 }
718
719 // undetached version
720
721 omni_thread*
722 omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri)
723 {
724     omni_thread* t = new omni_thread(fn, arg, pri);
725
726     t->start();
727
728     return t;
729 }
730
731
732 //
733 // exit() _must_ lock the mutex even in the case of a detached thread.  This is
734 // because a thread may run to completion before the thread that created it has
735 // had a chance to get out of start().  By locking the mutex we ensure that the
736 // creating thread must have reached the end of start() before we delete the
737 // thread object.  Of course, once the call to start() returns, the user can
738 // still incorrectly refer to the thread object, but that's their problem.
739 //
740
741 void
742 omni_thread::exit(void* return_value)
743 {
744     omni_thread* me = self();
745
746     if (me)
747       {
748         me->mutex.lock();
749
750         me->_state = STATE_TERMINATED;
751
752         me->mutex.unlock();
753
754         DB(cerr << "omni_thread::exit: thread " << me->id() << " detached "
755            << me->detached << " return value " << return_value << endl);
756
757         if (me->detached)
758           delete me;
759       }
760     else
761       {
762         DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl);
763       }
764
765     pthread_exit(return_value);
766 }
767
768
769 omni_thread*
770 omni_thread::self(void)
771 {
772     omni_thread* me;
773
774 #if (PthreadDraftVersion <= 6)
775
776     THROW_ERRORS(pthread_getspecific(self_key, (void**)&me));
777
778 #else
779
780     me = (omni_thread *)pthread_getspecific(self_key);
781
782 #endif
783
784     if (!me) {
785       // This thread is not created by omni_thread::start because it
786       // doesn't has a class omni_thread instance attached to its key.
787       DB(cerr << "omni_thread::self: called with a non-omnithread. NULL is returned." << endl);
788     }
789
790     return me;
791 }
792
793
794 void
795 omni_thread::yield(void)
796 {
797 #if (PthreadDraftVersion == 6)
798
799     pthread_yield(NULL);
800
801 #elif (PthreadDraftVersion < 9)
802
803     pthread_yield();
804
805 #else
806
807     THROW_ERRORS(sched_yield());
808
809 #endif
810 }
811
812
813 void
814 omni_thread::sleep(unsigned long secs, unsigned long nanosecs)
815 {
816     timespec rqts = { secs, nanosecs };
817
818 #ifndef NoNanoSleep
819
820     timespec remain;
821     while (nanosleep(&rqts, &remain)) {
822       if (errno == EINTR) {
823         rqts.tv_sec  = remain.tv_sec;
824         rqts.tv_nsec = remain.tv_nsec;
825         continue;
826       }
827       else
828         throw omni_thread_fatal(errno);
829     }
830 #else
831
832 #if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined (__POSIX_NT__)
833
834     if (pthread_delay_np(&rqts) != 0)
835         throw omni_thread_fatal(errno);
836
837 #elif defined(__linux__) || defined(__aix__)
838
839     if (secs > 2000) {
840       while ((secs = ::sleep(secs))) ;
841     } else {
842         usleep(secs * 1000000 + (nanosecs / 1000));
843     }
844
845 #elif defined(__darwin__) || defined(__macos__)
846
847     // Single UNIX Specification says argument of usleep() must be
848     // less than 1,000,000.
849     secs += nanosecs / 1000000000;
850     nanosecs %= 1000000000;
851     while ((secs = ::sleep(secs))) ;
852     usleep(nanosecs / 1000);
853
854 #else
855
856     throw omni_thread_invalid();
857
858 #endif
859 #endif  /* NoNanoSleep */
860 }
861
862
863 void
864 omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec,
865                       unsigned long rel_sec, unsigned long rel_nsec)
866 {
867     timespec abs;
868
869 #if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined(__POSIX_NT__)
870
871     timespec rel;
872     rel.tv_sec = rel_sec;
873     rel.tv_nsec = rel_nsec;
874     THROW_ERRORS(pthread_get_expiration_np(&rel, &abs));
875
876 #else
877
878 #ifdef HAVE_CLOCK_GETTIME       /* __linux__ || __aix__ */
879
880     clock_gettime(CLOCK_REALTIME, &abs);
881
882 #elif defined(HAVE_GETTIMEOFDAY)        /* defined(__linux__) || defined(__aix__) || defined(__SCO_VERSION__) || defined(__darwin__) || defined(__macos__) */
883
884     struct timeval tv;
885     gettimeofday(&tv, NULL); 
886     abs.tv_sec = tv.tv_sec;
887     abs.tv_nsec = tv.tv_usec * 1000;
888
889 #else
890 #error no get time support
891 #endif  /* __linux__ || __aix__ */
892
893     abs.tv_nsec += rel_nsec;
894     abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000;
895     abs.tv_nsec = abs.tv_nsec % 1000000000;
896
897 #endif  /* __osf1__ && __alpha__ */
898
899     *abs_sec = abs.tv_sec;
900     *abs_nsec = abs.tv_nsec;
901 }
902
903
904 int
905 omni_thread::posix_priority(priority_t pri)
906 {
907 #ifdef PthreadSupportThreadPriority
908     switch (pri) {
909
910     case PRIORITY_LOW:
911         return lowest_priority;
912
913     case PRIORITY_NORMAL:
914         return normal_priority;
915
916     case PRIORITY_HIGH:
917         return highest_priority;
918
919     }
920 #endif
921
922     throw omni_thread_invalid();
923 #ifdef _MSC_VER
924     return 0;
925 #endif
926 }
927
928 void
929 omni_thread::stacksize(unsigned long sz)
930 {
931   stack_size = sz;
932 }
933
934 unsigned long
935 omni_thread::stacksize()
936 {
937   return stack_size;
938 }
939
940 //
941 // Dummy thread
942 //
943
944 class omni_thread_dummy : public omni_thread {
945 public:
946   inline omni_thread_dummy() : omni_thread()
947   {
948     _dummy = 1;
949     _state = STATE_RUNNING;
950     posix_thread = pthread_self();
951     THROW_ERRORS(pthread_setspecific(self_key, (void*)this));
952   }
953   inline ~omni_thread_dummy()
954   {
955     THROW_ERRORS(pthread_setspecific(self_key, 0));
956   }
957 };
958
959 omni_thread*
960 omni_thread::create_dummy()
961 {
962   if (omni_thread::self())
963     throw omni_thread_invalid();
964
965   return new omni_thread_dummy;
966 }
967
968 void
969 omni_thread::release_dummy()
970 {
971   omni_thread* self = omni_thread::self();
972   if (!self || !self->_dummy)
973     throw omni_thread_invalid();
974
975   omni_thread_dummy* dummy = (omni_thread_dummy*)self;
976   delete dummy;
977 }
978
979
980 #define INSIDE_THREAD_IMPL_CC
981 #include "threaddata.cc"
982 #undef INSIDE_THREAD_IMPL_CC