0ad3ec0a0cbeab50089ba92eaabd77fba80fd52d
[cacao.git] / src / threads / native / threads.c
1 /* src/threads/native/threads.c - native threads support
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: threads.c 8402 2007-08-22 19:32:27Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 /* XXX cleanup these includes */
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #include <signal.h>
40 #include <sys/time.h>
41 #include <time.h>
42 #include <errno.h>
43
44 #include <pthread.h>
45
46 #include "vm/types.h"
47
48 #include "arch.h"
49
50 #if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
51 # include "machine-instr.h"
52 #else
53 # include "threads/native/generic-primitives.h"
54 #endif
55
56 #include "mm/gc-common.h"
57 #include "mm/memory.h"
58
59 #include "native/jni.h"
60 #include "native/llni.h"
61 #include "native/native.h"
62 #include "native/include/java_lang_Object.h"
63 #include "native/include/java_lang_String.h"
64 #include "native/include/java_lang_Throwable.h"
65 #include "native/include/java_lang_Thread.h"
66
67 #if defined(ENABLE_JAVASE)
68 # include "native/include/java_lang_ThreadGroup.h"
69 #endif
70
71 #if defined(WITH_CLASSPATH_GNU)
72 # include "native/include/java_lang_VMThread.h"
73 #endif
74
75 #include "threads/lock-common.h"
76 #include "threads/threads-common.h"
77
78 #include "threads/native/threads.h"
79
80 #include "toolbox/logging.h"
81
82 #include "vm/builtin.h"
83 #include "vm/exceptions.h"
84 #include "vm/global.h"
85 #include "vm/stringlocal.h"
86 #include "vm/vm.h"
87
88 #include "vm/jit/asmpart.h"
89
90 #include "vmcore/options.h"
91
92 #if defined(ENABLE_STATISTICS)
93 # include "vmcore/statistics.h"
94 #endif
95
96 #if !defined(__DARWIN__)
97 # if defined(__LINUX__)
98 #  define GC_LINUX_THREADS
99 # elif defined(__MIPS__)
100 #  define GC_IRIX_THREADS
101 # endif
102 # include <semaphore.h>
103 # if defined(ENABLE_GC_BOEHM)
104 #  include "mm/boehm-gc/include/gc.h"
105 # endif
106 #endif
107
108 #if defined(ENABLE_JVMTI)
109 #include "native/jvmti/cacaodbg.h"
110 #endif
111
112 #if defined(__DARWIN__)
113 /* Darwin has no working semaphore implementation.  This one is taken
114    from Boehm-GC. */
115
116 /*
117    This is a very simple semaphore implementation for darwin. It
118    is implemented in terms of pthreads calls so it isn't async signal
119    safe. This isn't a problem because signals aren't used to
120    suspend threads on darwin.
121 */
122    
123 static int sem_init(sem_t *sem, int pshared, int value)
124 {
125         if (pshared)
126                 assert(0);
127
128         sem->value = value;
129     
130         if (pthread_mutex_init(&sem->mutex, NULL) < 0)
131                 return -1;
132
133         if (pthread_cond_init(&sem->cond, NULL) < 0)
134                 return -1;
135
136         return 0;
137 }
138
139 static int sem_post(sem_t *sem)
140 {
141         if (pthread_mutex_lock(&sem->mutex) < 0)
142                 return -1;
143
144         sem->value++;
145
146         if (pthread_cond_signal(&sem->cond) < 0) {
147                 pthread_mutex_unlock(&sem->mutex);
148                 return -1;
149         }
150
151         if (pthread_mutex_unlock(&sem->mutex) < 0)
152                 return -1;
153
154         return 0;
155 }
156
157 static int sem_wait(sem_t *sem)
158 {
159         if (pthread_mutex_lock(&sem->mutex) < 0)
160                 return -1;
161
162         while (sem->value == 0) {
163                 pthread_cond_wait(&sem->cond, &sem->mutex);
164         }
165
166         sem->value--;
167
168         if (pthread_mutex_unlock(&sem->mutex) < 0)
169                 return -1;    
170
171         return 0;
172 }
173
174 static int sem_destroy(sem_t *sem)
175 {
176         if (pthread_cond_destroy(&sem->cond) < 0)
177                 return -1;
178
179         if (pthread_mutex_destroy(&sem->mutex) < 0)
180                 return -1;
181
182         return 0;
183 }
184 #endif /* defined(__DARWIN__) */
185
186
187 /* internally used constants **************************************************/
188
189 /* CAUTION: Do not change these values. Boehm GC code depends on them.        */
190 #define STOPWORLD_FROM_GC               1
191 #define STOPWORLD_FROM_CLASS_NUMBERING  2
192
193
194 /* startupinfo *****************************************************************
195
196    Struct used to pass info from threads_start_thread to 
197    threads_startup_thread.
198
199 ******************************************************************************/
200
201 typedef struct {
202         threadobject *thread;      /* threadobject for this thread             */
203         functionptr   function;    /* function to run in the new thread        */
204         sem_t        *psem;        /* signals when thread has been entered     */
205                                    /* in the thread list                       */
206         sem_t        *psem_first;  /* signals when pthread_create has returned */
207 } startupinfo;
208
209
210 /* prototypes *****************************************************************/
211
212 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
213
214
215 /******************************************************************************/
216 /* GLOBAL VARIABLES                                                           */
217 /******************************************************************************/
218
219 static methodinfo *method_thread_init;
220
221 /* the thread object of the current thread                                    */
222 /* This is either a thread-local variable defined with __thread, or           */
223 /* a thread-specific value stored with key threads_current_threadobject_key.  */
224 #if defined(HAVE___THREAD)
225 __thread threadobject *threads_current_threadobject;
226 #else
227 pthread_key_t threads_current_threadobject_key;
228 #endif
229
230 /* global mutex for the threads table */
231 static pthread_mutex_t mutex_threads_list;
232
233 /* global mutex for stop-the-world                                            */
234 static pthread_mutex_t stopworldlock;
235
236 /* global mutex and condition for joining threads on exit */
237 static pthread_mutex_t mutex_join;
238 static pthread_cond_t  cond_join;
239
240 /* XXX We disable that whole bunch of code until we have the exact-GC
241    running. */
242
243 #if 0
244
245 /* this is one of the STOPWORLD_FROM_ constants, telling why the world is     */
246 /* being stopped                                                              */
247 static volatile int stopworldwhere;
248
249 /* semaphore used for acknowleding thread suspension                          */
250 static sem_t suspend_ack;
251 #if defined(__MIPS__)
252 static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
253 static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
254 #endif
255
256 #endif /* 0 */
257
258 /* mutexes used by the fake atomic instructions                               */
259 #if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
260 pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
261 pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
262 pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
263 #endif
264
265
266 /* threads_sem_init ************************************************************
267  
268    Initialize a semaphore. Checks against errors and interruptions.
269
270    IN:
271        sem..............the semaphore to initialize
272            shared...........true if this semaphore will be shared between processes
273            value............the initial value for the semaphore
274    
275 *******************************************************************************/
276
277 void threads_sem_init(sem_t *sem, bool shared, int value)
278 {
279         int r;
280
281         assert(sem);
282
283         do {
284                 r = sem_init(sem, shared, value);
285                 if (r == 0)
286                         return;
287         } while (errno == EINTR);
288
289         vm_abort("sem_init failed: %s", strerror(errno));
290 }
291
292
293 /* threads_sem_wait ************************************************************
294  
295    Wait for a semaphore, non-interruptible.
296
297    IMPORTANT: Always use this function instead of `sem_wait` directly, as
298               `sem_wait` may be interrupted by signals!
299   
300    IN:
301        sem..............the semaphore to wait on
302    
303 *******************************************************************************/
304
305 void threads_sem_wait(sem_t *sem)
306 {
307         int r;
308
309         assert(sem);
310
311         do {
312                 r = sem_wait(sem);
313                 if (r == 0)
314                         return;
315         } while (errno == EINTR);
316
317         vm_abort("sem_wait failed: %s", strerror(errno));
318 }
319
320
321 /* threads_sem_post ************************************************************
322  
323    Increase the count of a semaphore. Checks for errors.
324
325    IN:
326        sem..............the semaphore to increase the count of
327    
328 *******************************************************************************/
329
330 void threads_sem_post(sem_t *sem)
331 {
332         int r;
333
334         assert(sem);
335
336         /* unlike sem_wait, sem_post is not interruptible */
337
338         r = sem_post(sem);
339         if (r == 0)
340                 return;
341
342         vm_abort("sem_post failed: %s", strerror(errno));
343 }
344
345
346 /* lock_stopworld **************************************************************
347
348    Enter the stopworld lock, specifying why the world shall be stopped.
349
350    IN:
351       where........ STOPWORLD_FROM_GC              (1) from within GC
352                     STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
353
354 ******************************************************************************/
355
356 void lock_stopworld(int where)
357 {
358         pthread_mutex_lock(&stopworldlock);
359 /*      stopworldwhere = where; */
360 }
361
362
363 /* unlock_stopworld ************************************************************
364
365    Release the stopworld lock.
366
367 ******************************************************************************/
368
369 void unlock_stopworld(void)
370 {
371 /*      stopworldwhere = 0; */
372         pthread_mutex_unlock(&stopworldlock);
373 }
374
375 /* XXX We disable that whole bunch of code until we have the exact-GC
376    running. */
377
378 #if 0
379
380 #if !defined(__DARWIN__)
381 /* Caller must hold threadlistlock */
382 static s4 threads_cast_sendsignals(s4 sig)
383 {
384         threadobject *t;
385         threadobject *self;
386         s4            count;
387
388         self = THREADOBJECT;
389
390         /* iterate over all started threads */
391
392         count = 0;
393
394         for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
395                 /* don't send the signal to ourself */
396
397                 if (t == self)
398                         continue;
399
400                 /* don't send the signal to NEW threads (because they are not
401                    completely initialized) */
402
403                 if (t->state == THREAD_STATE_NEW)
404                         continue;
405
406                 /* send the signal */
407
408                 pthread_kill(t->tid, sig);
409
410                 /* increase threads count */
411
412                 count++;
413         }
414
415         return count;
416 }
417
418 #else
419
420 static void threads_cast_darwinstop(void)
421 {
422         threadobject *tobj = mainthreadobj;
423         threadobject *self = THREADOBJECT;
424
425         do {
426                 if (tobj != self)
427                 {
428                         thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
429                         mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
430 #if defined(__I386__)
431                         i386_thread_state_t thread_state;
432 #else
433                         ppc_thread_state_t thread_state;
434 #endif
435                         mach_port_t thread = tobj->mach_thread;
436                         kern_return_t r;
437
438                         r = thread_suspend(thread);
439
440                         if (r != KERN_SUCCESS)
441                                 vm_abort("thread_suspend failed");
442
443                         r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
444                                                                  &thread_state_count);
445
446                         if (r != KERN_SUCCESS)
447                                 vm_abort("thread_get_state failed");
448
449                         md_critical_section_restart((ucontext_t *) &thread_state);
450
451                         r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
452                                                                  thread_state_count);
453
454                         if (r != KERN_SUCCESS)
455                                 vm_abort("thread_set_state failed");
456                 }
457
458                 tobj = tobj->next;
459         } while (tobj != mainthreadobj);
460 }
461
462 static void threads_cast_darwinresume(void)
463 {
464         threadobject *tobj = mainthreadobj;
465         threadobject *self = THREADOBJECT;
466
467         do {
468                 if (tobj != self)
469                 {
470                         mach_port_t thread = tobj->mach_thread;
471                         kern_return_t r;
472
473                         r = thread_resume(thread);
474
475                         if (r != KERN_SUCCESS)
476                                 vm_abort("thread_resume failed");
477                 }
478
479                 tobj = tobj->next;
480         } while (tobj != mainthreadobj);
481 }
482
483 #endif
484
485 #if defined(__MIPS__)
486 static void threads_cast_irixresume(void)
487 {
488         pthread_mutex_lock(&suspend_ack_lock);
489         pthread_cond_broadcast(&suspend_cond);
490         pthread_mutex_unlock(&suspend_ack_lock);
491 }
492 #endif
493
494 #if !defined(DISABLE_GC)
495
496 void threads_cast_stopworld(void)
497 {
498 #if !defined(__DARWIN__) && !defined(__CYGWIN__)
499         s4 count, i;
500 #endif
501
502         lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
503
504         /* lock the threads lists */
505
506         threads_list_lock();
507
508 #if defined(__DARWIN__)
509         threads_cast_darwinstop();
510 #elif defined(__CYGWIN__)
511         /* TODO */
512         assert(0);
513 #else
514         /* send all threads the suspend signal */
515
516         count = threads_cast_sendsignals(GC_signum1());
517
518         /* wait for all threads signaled to suspend */
519
520         for (i = 0; i < count; i++)
521                 threads_sem_wait(&suspend_ack);
522 #endif
523
524         /* ATTENTION: Don't unlock the threads-lists here so that
525            non-signaled NEW threads can't change their state and execute
526            code. */
527 }
528
529
530 void threads_cast_startworld(void)
531 {
532 #if defined(__DARWIN__)
533         threads_cast_darwinresume();
534 #elif defined(__MIPS__)
535         threads_cast_irixresume();
536 #elif defined(__CYGWIN__)
537         /* TODO */
538         assert(0);
539 #else
540         (void) threads_cast_sendsignals(GC_signum2());
541 #endif
542
543         /* unlock the threads lists */
544
545         threads_list_unlock();
546
547         unlock_stopworld();
548 }
549
550
551 #if !defined(__DARWIN__)
552 static void threads_sigsuspend_handler(ucontext_t *_uc)
553 {
554         int sig;
555         sigset_t sigs;
556
557         /* XXX TWISTI: this is just a quick hack */
558 #if defined(ENABLE_JIT)
559         md_critical_section_restart(_uc);
560 #endif
561
562         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
563            (not POSIX async-safe). */
564 #if defined(__IRIX__)
565         pthread_mutex_lock(&suspend_ack_lock);
566         threads_sem_post(&suspend_ack);
567         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
568         pthread_mutex_unlock(&suspend_ack_lock);
569 #elif defined(__CYGWIN__)
570         /* TODO */
571         assert(0);
572 #else
573         threads_sem_post(&suspend_ack);
574
575         sig = GC_signum2();
576         sigfillset(&sigs);
577         sigdelset(&sigs, sig);
578         sigsuspend(&sigs);
579 #endif
580 }
581
582 #endif
583
584
585 /* This function is called from Boehm GC code. */
586
587 int cacao_suspendhandler(ucontext_t *_uc)
588 {
589         if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
590                 return 0;
591
592         threads_sigsuspend_handler(_uc);
593         return 1;
594 }
595
596 #endif /* DISABLE_GC */
597
598 #endif /* 0 */
599
600
601 /* threads_set_current_threadobject ********************************************
602
603    Set the current thread object.
604    
605    IN:
606       thread.......the thread object to set
607
608 *******************************************************************************/
609
610 void threads_set_current_threadobject(threadobject *thread)
611 {
612 #if !defined(HAVE___THREAD)
613         if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
614                 vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
615 #else
616         threads_current_threadobject = thread;
617 #endif
618 }
619
620
621 /* threads_impl_thread_new *****************************************************
622
623    Initialize implementation fields of a threadobject.
624
625    IN:
626       t....the threadobject
627
628 *******************************************************************************/
629
630 void threads_impl_thread_new(threadobject *t)
631 {
632         /* get the pthread id */
633
634         t->tid = pthread_self();
635
636         /* initialize the mutex and the condition */
637
638         pthread_mutex_init(&(t->waitmutex), NULL);
639         pthread_cond_init(&(t->waitcond), NULL);
640
641 #if defined(ENABLE_DEBUG_FILTER)
642         /* Initialize filter counters */
643         t->filterverbosecallctr[0] = 0;
644         t->filterverbosecallctr[1] = 0;
645 #endif
646
647 #if !defined(NDEBUG)
648         t->tracejavacallindent = 0;
649         t->tracejavacallcount = 0;
650 #endif
651 }
652
653
654 /* threads_impl_thread_free ****************************************************
655
656    Cleanup thread stuff.
657
658    IN:
659       t....the threadobject
660
661 *******************************************************************************/
662
663 void threads_impl_thread_free(threadobject *t)
664 {
665         /* destroy the mutex and the condition */
666
667         if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
668                 vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
669                                  strerror(errno));
670
671         if (pthread_cond_destroy(&(t->waitcond)) != 0)
672                 vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
673                                  strerror(errno));
674 }
675
676
677 /* threads_get_current_threadobject ********************************************
678
679    Return the threadobject of the current thread.
680    
681    RETURN VALUE:
682        the current threadobject * (an instance of java.lang.Thread)
683
684 *******************************************************************************/
685
686 threadobject *threads_get_current_threadobject(void)
687 {
688         return THREADOBJECT;
689 }
690
691
692 /* threads_impl_preinit ********************************************************
693
694    Do some early initialization of stuff required.
695
696    ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
697    is called AFTER this function!
698
699 *******************************************************************************/
700
701 void threads_impl_preinit(void)
702 {
703         pthread_mutex_init(&stopworldlock, NULL);
704
705         /* initialize exit mutex and condition (on exit we join all
706            threads) */
707
708         pthread_mutex_init(&mutex_join, NULL);
709         pthread_cond_init(&cond_join, NULL);
710
711         /* initialize the threads-list mutex */
712
713         pthread_mutex_init(&mutex_threads_list, NULL);
714
715 #if !defined(HAVE___THREAD)
716         pthread_key_create(&threads_current_threadobject_key, NULL);
717 #endif
718
719 /*      threads_sem_init(&suspend_ack, 0, 0); */
720 }
721
722
723 /* threads_list_lock ***********************************************************
724
725    Enter the threads table mutex.
726
727    NOTE: We need this function as we can't use an internal lock for
728          the threads lists because the thread's lock is initialized in
729          threads_table_add (when we have the thread index), but we
730          already need the lock at the entry of the function.
731
732 *******************************************************************************/
733
734 void threads_list_lock(void)
735 {
736         if (pthread_mutex_lock(&mutex_threads_list) != 0)
737                 vm_abort("threads_list_lock: pthread_mutex_lock failed: %s",
738                                  strerror(errno));
739 }
740
741
742 /* threads_list_unlock *********************************************************
743
744    Leave the threads list mutex.
745
746 *******************************************************************************/
747
748 void threads_list_unlock(void)
749 {
750         if (pthread_mutex_unlock(&mutex_threads_list) != 0)
751                 vm_abort("threads_list_unlock: pthread_mutex_unlock failed: %s",
752                                  strerror(errno));
753 }
754
755
756 /* threads_mutex_join_lock *****************************************************
757
758    Enter the join mutex.
759
760 *******************************************************************************/
761
762 void threads_mutex_join_lock(void)
763 {
764         if (pthread_mutex_lock(&mutex_join) != 0)
765                 vm_abort("threads_mutex_join_lock: pthread_mutex_lock failed: %s",
766                                  strerror(errno));
767 }
768
769
770 /* threads_mutex_join_unlock ***************************************************
771
772    Leave the join mutex.
773
774 *******************************************************************************/
775
776 void threads_mutex_join_unlock(void)
777 {
778         if (pthread_mutex_unlock(&mutex_join) != 0)
779                 vm_abort("threads_mutex_join_unlock: pthread_mutex_unlock failed: %s",
780                                  strerror(errno));
781 }
782
783
784 /* threads_init ****************************************************************
785
786    Initializes the threads required by the JVM: main, finalizer.
787
788 *******************************************************************************/
789
790 bool threads_init(void)
791 {
792         threadobject     *mainthread;
793         java_handle_t    *threadname;
794         java_lang_Thread *t;
795         java_handle_t    *o;
796
797 #if defined(ENABLE_JAVASE)
798         java_lang_ThreadGroup *threadgroup;
799         methodinfo            *m;
800 #endif
801
802 #if defined(WITH_CLASSPATH_GNU)
803         java_lang_VMThread    *vmt;
804 #endif
805
806         pthread_attr_t attr;
807
808         /* get methods we need in this file */
809
810 #if defined(WITH_CLASSPATH_GNU)
811         method_thread_init =
812                 class_resolveclassmethod(class_java_lang_Thread,
813                                                                  utf_init,
814                                                                  utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
815                                                                  class_java_lang_Thread,
816                                                                  true);
817 #elif defined(WITH_CLASSPATH_SUN)
818         method_thread_init =
819                 class_resolveclassmethod(class_java_lang_Thread,
820                                                                  utf_init,
821                                                                  utf_new_char("(Ljava/lang/String;)V"),
822                                                                  class_java_lang_Thread,
823                                                                  true);
824 #elif defined(WITH_CLASSPATH_CLDC1_1)
825         method_thread_init =
826                 class_resolveclassmethod(class_java_lang_Thread,
827                                                                  utf_init,
828                                                                  utf_new_char("(Ljava/lang/String;)V"),
829                                                                  class_java_lang_Thread,
830                                                                  true);
831 #else
832 # error unknown classpath configuration
833 #endif
834
835         if (method_thread_init == NULL)
836                 return false;
837
838         /* Get the main-thread (NOTE: The main threads is always the first
839            thread in the list). */
840
841         mainthread = threads_list_first();
842
843         /* create a java.lang.Thread for the main thread */
844
845         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
846
847         if (t == NULL)
848                 return false;
849
850         /* set the object in the internal data structure */
851
852         mainthread->object = t;
853
854 #if defined(ENABLE_INTRP)
855         /* create interpreter stack */
856
857         if (opt_intrp) {
858                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
859                 mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
860         }
861 #endif
862
863         threadname = javastring_new(utf_new_char("main"));
864
865 #if defined(ENABLE_JAVASE)
866         /* allocate and init ThreadGroup */
867
868         threadgroup = (java_lang_ThreadGroup *)
869                 native_new_and_init(class_java_lang_ThreadGroup);
870
871         if (threadgroup == NULL)
872                 return false;
873 #endif
874
875 #if defined(WITH_CLASSPATH_GNU)
876         /* create a java.lang.VMThread for the main thread */
877
878         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
879
880         if (vmt == NULL)
881                 return false;
882
883         /* set the thread */
884
885         LLNI_field_set_ref(vmt, thread, t);
886         LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) mainthread);
887
888         /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
889         o = (java_handle_t *) t;
890
891         (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
892                                                   false);
893
894 #elif defined(WITH_CLASSPATH_SUN)
895
896         /* We trick java.lang.Thread.<init>, which sets the priority of
897            the current thread to the parent's one. */
898
899         t->priority = NORM_PRIORITY;
900
901         /* Call java.lang.Thread.<init>(Ljava/lang/String;)V */
902
903         o = (java_object_t *) t;
904
905         (void) vm_call_method(method_thread_init, o, threadname);
906
907 #elif defined(WITH_CLASSPATH_CLDC1_1)
908
909         /* set the thread */
910
911         t->vm_thread = (java_lang_Object *) mainthread;
912
913         /* call public Thread(String name) */
914
915         o = (java_handle_t *) t;
916
917         (void) vm_call_method(method_thread_init, o, threadname);
918 #else
919 # error unknown classpath configuration
920 #endif
921
922         if (exceptions_get_exception())
923                 return false;
924
925 #if defined(ENABLE_JAVASE)
926         LLNI_field_set_ref(t, group, threadgroup);
927
928 # if defined(WITH_CLASSPATH_GNU)
929         /* add main thread to java.lang.ThreadGroup */
930
931         m = class_resolveclassmethod(class_java_lang_ThreadGroup,
932                                                                  utf_addThread,
933                                                                  utf_java_lang_Thread__V,
934                                                                  class_java_lang_ThreadGroup,
935                                                                  true);
936
937         o = (java_handle_t *) threadgroup;
938
939         (void) vm_call_method(m, o, t);
940
941         if (exceptions_get_exception())
942                 return false;
943 # else
944 #  warning Do not know what to do here
945 # endif
946 #endif
947
948         threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
949
950         /* initialize the thread attribute object */
951
952         if (pthread_attr_init(&attr) != 0)
953                 vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
954
955         if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
956                 vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
957                                  strerror(errno));
958
959 #if !defined(NDEBUG)
960         if (opt_verbosethreads) {
961                 printf("[Starting thread ");
962                 threads_thread_print_info(mainthread);
963                 printf("]\n");
964         }
965 #endif
966
967         /* everything's ok */
968
969         return true;
970 }
971
972
973 /* threads_startup_thread ******************************************************
974
975    Thread startup function called by pthread_create.
976
977    Thread which have a startup.function != NULL are marked as internal
978    threads. All other threads are threated as normal Java threads.
979
980    NOTE: This function is not called directly by pthread_create. The Boehm GC
981          inserts its own GC_start_routine in between, which then calls
982                  threads_startup.
983
984    IN:
985       arg..........the argument passed to pthread_create, ie. a pointer to
986                        a startupinfo struct. CAUTION: When the `psem` semaphore
987                                    is posted, the startupinfo struct becomes invalid! (It
988                                    is allocated on the stack of threads_start_thread.)
989
990 ******************************************************************************/
991
992 static void *threads_startup_thread(void *arg)
993 {
994         startupinfo        *startup;
995         threadobject       *thread;
996 #if defined(WITH_CLASSPATH_GNU)
997         java_lang_VMThread *vmt;
998 #endif
999         sem_t              *psem;
1000         classinfo          *c;
1001         methodinfo         *m;
1002         java_handle_t      *o;
1003         functionptr         function;
1004
1005 #if defined(ENABLE_INTRP)
1006         u1 *intrp_thread_stack;
1007
1008         /* create interpreter stack */
1009
1010         if (opt_intrp) {
1011                 intrp_thread_stack = GCMNEW(u1, opt_stacksize);
1012                 MSET(intrp_thread_stack, 0, u1, opt_stacksize);
1013         }
1014         else
1015                 intrp_thread_stack = NULL;
1016 #endif
1017
1018         /* get passed startupinfo structure and the values in there */
1019
1020         startup = arg;
1021
1022         thread   = startup->thread;
1023         function = startup->function;
1024         psem     = startup->psem;
1025
1026         /* Seems like we've encountered a situation where thread->tid was
1027            not set by pthread_create. We alleviate this problem by waiting
1028            for pthread_create to return. */
1029
1030         threads_sem_wait(startup->psem_first);
1031
1032 #if defined(__DARWIN__)
1033         thread->mach_thread = mach_thread_self();
1034 #endif
1035
1036         /* store the internal thread data-structure in the TSD */
1037
1038         threads_set_current_threadobject(thread);
1039
1040         /* set our priority */
1041
1042         threads_set_thread_priority(thread->tid, LLNI_field_direct(thread->object, priority));
1043
1044         /* thread is completely initialized */
1045
1046         threads_thread_state_runnable(thread);
1047
1048         /* tell threads_startup_thread that we registered ourselves */
1049         /* CAUTION: *startup becomes invalid with this!             */
1050
1051         startup = NULL;
1052         threads_sem_post(psem);
1053
1054 #if defined(ENABLE_INTRP)
1055         /* set interpreter stack */
1056
1057         if (opt_intrp)
1058                 thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
1059 #endif
1060
1061 #if defined(ENABLE_JVMTI)
1062         /* fire thread start event */
1063
1064         if (jvmti) 
1065                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
1066 #endif
1067
1068 #if !defined(NDEBUG)
1069         if (opt_verbosethreads) {
1070                 printf("[Starting thread ");
1071                 threads_thread_print_info(thread);
1072                 printf("]\n");
1073         }
1074 #endif
1075
1076         /* find and run the Thread.run()V method if no other function was passed */
1077
1078         if (function == NULL) {
1079 #if defined(WITH_CLASSPATH_GNU)
1080                 /* We need to start the run method of
1081                    java.lang.VMThread. Since this is a final class, we can use
1082                    the class object directly. */
1083
1084                 c = class_java_lang_VMThread;
1085 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1086                 c = thread->object->header.vftbl->class;
1087 #else
1088 # error unknown classpath configuration
1089 #endif
1090
1091                 m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
1092
1093                 if (m == NULL)
1094                         vm_abort("threads_startup_thread: run() method not found in class");
1095
1096                 /* set ThreadMXBean variables */
1097
1098                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1099                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1100
1101                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1102                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1103                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1104                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1105
1106 #if defined(WITH_CLASSPATH_GNU)
1107                 /* we need to start the run method of java.lang.VMThread */
1108
1109                 vmt = (java_lang_VMThread *) LLNI_field_direct(thread->object, vmThread);
1110                 o   = (java_handle_t *) vmt;
1111
1112 #elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
1113                 o   = (java_handle_t *) thread->object;
1114 #else
1115 # error unknown classpath configuration
1116 #endif
1117
1118                 /* run the thread */
1119
1120                 (void) vm_call_method(m, o);
1121         }
1122         else {
1123                 /* set ThreadMXBean variables */
1124
1125                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
1126                 _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
1127
1128                 if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
1129                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
1130                         _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
1131                                 _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
1132
1133                 /* call passed function, e.g. finalizer_thread */
1134
1135                 (function)();
1136         }
1137
1138 #if !defined(NDEBUG)
1139         if (opt_verbosethreads) {
1140                 printf("[Stopping thread ");
1141                 threads_thread_print_info(thread);
1142                 printf("]\n");
1143         }
1144 #endif
1145
1146 #if defined(ENABLE_JVMTI)
1147         /* fire thread end event */
1148
1149         if (jvmti)
1150                 jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
1151 #endif
1152
1153         /* We ignore the return value. */
1154
1155         (void) threads_detach_thread(thread);
1156
1157         /* set ThreadMXBean variables */
1158
1159         _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
1160
1161         return NULL;
1162 }
1163
1164
1165 /* threads_impl_thread_start ***************************************************
1166
1167    Start a thread in the JVM.  Both (vm internal and java) thread
1168    objects exist.
1169
1170    IN:
1171       thread....the thread object
1172           f.........function to run in the new thread. NULL means that the
1173                     "run" method of the object `t` should be called
1174
1175 ******************************************************************************/
1176
1177 void threads_impl_thread_start(threadobject *thread, functionptr f)
1178 {
1179         sem_t          sem;
1180         sem_t          sem_first;
1181         pthread_attr_t attr;
1182         startupinfo    startup;
1183         int            ret;
1184
1185         /* fill startupinfo structure passed by pthread_create to
1186          * threads_startup_thread */
1187
1188         startup.thread     = thread;
1189         startup.function   = f;              /* maybe we don't call Thread.run()V */
1190         startup.psem       = &sem;
1191         startup.psem_first = &sem_first;
1192
1193         threads_sem_init(&sem, 0, 0);
1194         threads_sem_init(&sem_first, 0, 0);
1195
1196         /* initialize thread attributes */
1197
1198         if (pthread_attr_init(&attr) != 0)
1199                 vm_abort("threads_impl_thread_start: pthread_attr_init failed: %s",
1200                                  strerror(errno));
1201
1202     if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
1203                 vm_abort("threads_impl_thread_start: pthread_attr_setdetachstate failed: %s",
1204                                  strerror(errno));
1205
1206         /* initialize thread stacksize */
1207
1208         if (pthread_attr_setstacksize(&attr, opt_stacksize))
1209                 vm_abort("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
1210                                  strerror(errno));
1211
1212         /* create the thread */
1213
1214         ret = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
1215
1216         /* destroy the thread attributes */
1217
1218         if (pthread_attr_destroy(&attr) != 0)
1219                 vm_abort("threads_impl_thread_start: pthread_attr_destroy failed: %s",
1220                                  strerror(errno));
1221
1222         /* check for pthread_create error */
1223
1224         if (ret != 0)
1225                 vm_abort("threads_impl_thread_start: pthread_create failed: %s",
1226                                  strerror(errno));
1227
1228         /* signal that pthread_create has returned, so thread->tid is valid */
1229
1230         threads_sem_post(&sem_first);
1231
1232         /* wait here until the thread has entered itself into the thread list */
1233
1234         threads_sem_wait(&sem);
1235
1236         /* cleanup */
1237
1238         sem_destroy(&sem);
1239         sem_destroy(&sem_first);
1240 }
1241
1242
1243 /* threads_set_thread_priority *************************************************
1244
1245    Set the priority of the given thread.
1246
1247    IN:
1248       tid..........thread id
1249           priority.....priority to set
1250
1251 ******************************************************************************/
1252
1253 void threads_set_thread_priority(pthread_t tid, int priority)
1254 {
1255         struct sched_param schedp;
1256         int policy;
1257
1258         pthread_getschedparam(tid, &policy, &schedp);
1259         schedp.sched_priority = priority;
1260         pthread_setschedparam(tid, policy, &schedp);
1261 }
1262
1263
1264 /* threads_attach_current_thread ***********************************************
1265
1266    Attaches the current thread to the VM.  Used in JNI.
1267
1268 *******************************************************************************/
1269
1270 bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
1271 {
1272         threadobject          *thread;
1273         utf                   *u;
1274         java_handle_t         *s;
1275         java_handle_t         *o;
1276         java_lang_Thread      *t;
1277
1278 #if defined(ENABLE_JAVASE)
1279         java_lang_ThreadGroup *group;
1280         threadobject          *mainthread;
1281         classinfo             *c;
1282         methodinfo            *m;
1283 #endif
1284
1285 #if defined(WITH_CLASSPATH_GNU)
1286         java_lang_VMThread    *vmt;
1287 #endif
1288
1289         /* Enter the join-mutex, so if the main-thread is currently
1290            waiting to join all threads, the number of non-daemon threads
1291            is correct. */
1292
1293         threads_mutex_join_lock();
1294
1295         /* create internal thread data-structure */
1296
1297         thread = threads_thread_new();
1298
1299         /* thread is a Java thread and running */
1300
1301         thread->flags = THREAD_FLAG_JAVA;
1302
1303         if (isdaemon)
1304                 thread->flags |= THREAD_FLAG_DAEMON;
1305
1306         /* The thread is flagged and (non-)daemon thread, we can leave the
1307            mutex. */
1308
1309         threads_mutex_join_unlock();
1310
1311         /* create a java.lang.Thread object */
1312
1313         t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
1314
1315         /* XXX memory leak!!! */
1316         if (t == NULL)
1317                 return false;
1318
1319         thread->object = t;
1320
1321         /* thread is completely initialized */
1322
1323         threads_thread_state_runnable(thread);
1324
1325 #if !defined(NDEBUG)
1326         if (opt_verbosethreads) {
1327                 printf("[Attaching thread ");
1328                 threads_thread_print_info(thread);
1329                 printf("]\n");
1330         }
1331 #endif
1332
1333 #if defined(ENABLE_INTRP)
1334         /* create interpreter stack */
1335
1336         if (opt_intrp) {
1337                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
1338                 thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
1339         }
1340 #endif
1341
1342 #if defined(WITH_CLASSPATH_GNU)
1343
1344         /* create a java.lang.VMThread object */
1345
1346         vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
1347
1348         /* XXX memory leak!!! */
1349         if (vmt == NULL)
1350                 return false;
1351
1352         /* set the thread */
1353
1354         LLNI_field_set_ref(vmt, thread, t);
1355         LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
1356
1357 #elif defined(WITH_CLASSPATH_SUN)
1358
1359         vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
1360
1361 #elif defined(WITH_CLASSPATH_CLDC1_1)
1362
1363         LLNI_field_set_val(t, vm_thread, (java_lang_Object *) thread);
1364
1365 #else
1366 # error unknown classpath configuration
1367 #endif
1368
1369         if (vm_aargs != NULL) {
1370                 u     = utf_new_char(vm_aargs->name);
1371 #if defined(ENABLE_JAVASE)
1372                 group = (java_lang_ThreadGroup *) vm_aargs->group;
1373 #endif
1374         }
1375         else {
1376                 u     = utf_null;
1377 #if defined(ENABLE_JAVASE)
1378                 /* get the main thread */
1379
1380                 mainthread = threads_list_first();
1381                 group = LLNI_field_direct(mainthread->object, group);
1382 #endif
1383         }
1384
1385         /* the the thread name */
1386
1387         s = javastring_new(u);
1388
1389         /* for convenience */
1390
1391         o = (java_handle_t *) thread->object;
1392
1393 #if defined(WITH_CLASSPATH_GNU)
1394         (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
1395                                                   isdaemon);
1396 #elif defined(WITH_CLASSPATH_CLDC1_1)
1397         (void) vm_call_method(method_thread_init, o, s);
1398 #endif
1399
1400         if (exceptions_get_exception())
1401                 return false;
1402
1403 #if defined(ENABLE_JAVASE)
1404         /* store the thread group in the object */
1405
1406         LLNI_field_direct(thread->object, group) = group;
1407
1408         /* add thread to given thread-group */
1409
1410         LLNI_class_get(group, c);
1411
1412         m = class_resolveclassmethod(c,
1413                                                                  utf_addThread,
1414                                                                  utf_java_lang_Thread__V,
1415                                                                  class_java_lang_ThreadGroup,
1416                                                                  true);
1417
1418         o = (java_handle_t *) group;
1419
1420         (void) vm_call_method(m, o, t);
1421
1422         if (exceptions_get_exception())
1423                 return false;
1424 #endif
1425
1426         return true;
1427 }
1428
1429
1430 /* threads_detach_thread *******************************************************
1431
1432    Detaches the passed thread from the VM.  Used in JNI.
1433
1434 *******************************************************************************/
1435
1436 bool threads_detach_thread(threadobject *t)
1437 {
1438 #if defined(ENABLE_JAVASE)
1439         java_lang_Thread      *object;
1440         java_lang_ThreadGroup *group;
1441         java_handle_t         *e;
1442         java_lang_Object      *handler;
1443         classinfo             *c;
1444         methodinfo            *m;
1445         java_handle_t         *o;
1446 #endif
1447
1448 #if defined(ENABLE_JAVASE)
1449         object = t->object;
1450
1451         group = LLNI_field_direct(object, group);
1452
1453     /* If there's an uncaught exception, call uncaughtException on the
1454        thread's exception handler, or the thread's group if this is
1455        unset. */
1456
1457         e = exceptions_get_and_clear_exception();
1458
1459     if (e != NULL) {
1460                 /* We use a java_lang_Object here, as it's not trivial to
1461                    build the java_lang_Thread_UncaughtExceptionHandler header
1462                    file. */
1463
1464 # if defined(WITH_CLASSPATH_GNU)
1465                 handler = (java_lang_Object *) LLNI_field_direct(object, exceptionHandler);
1466 # elif defined(WITH_CLASSPATH_SUN)
1467                 handler = (java_lang_Object *) LLNI_field_direct(object, uncaughtExceptionHandler);
1468 # endif
1469
1470                 if (handler != NULL) {
1471                         LLNI_class_get(handler, c);
1472                         o = (java_handle_t *) handler;
1473                 }
1474                 else {
1475                         LLNI_class_get(group, c);
1476                         o = (java_handle_t *) group;
1477                 }
1478
1479                 m = class_resolveclassmethod(c,
1480                                                                          utf_uncaughtException,
1481                                                                          utf_java_lang_Thread_java_lang_Throwable__V,
1482                                                                          NULL,
1483                                                                          true);
1484
1485                 if (m == NULL)
1486                         return false;
1487
1488                 (void) vm_call_method(m, o, object, e);
1489
1490                 if (exceptions_get_exception())
1491                         return false;
1492     }
1493
1494         /* XXX TWISTI: should all threads be in a ThreadGroup? */
1495
1496         /* Remove thread from the thread group. */
1497
1498         if (group != NULL) {
1499                 LLNI_class_get(group, c);
1500
1501 # if defined(WITH_CLASSPATH_GNU)
1502                 m = class_resolveclassmethod(c,
1503                                                                          utf_removeThread,
1504                                                                          utf_java_lang_Thread__V,
1505                                                                          class_java_lang_ThreadGroup,
1506                                                                          true);
1507 # elif defined(WITH_CLASSPATH_SUN)
1508                 m = class_resolveclassmethod(c,
1509                                                                          utf_remove,
1510                                                                          utf_java_lang_Thread__V,
1511                                                                          class_java_lang_ThreadGroup,
1512                                                                          true);
1513 # else
1514 #  error unknown classpath configuration
1515 # endif
1516
1517                 if (m == NULL)
1518                         return false;
1519
1520                 o = (java_handle_t *) group;
1521
1522                 (void) vm_call_method(m, o, object);
1523
1524                 if (exceptions_get_exception())
1525                         return false;
1526         }
1527 #endif
1528
1529         /* thread is terminated */
1530
1531         threads_thread_state_terminated(t);
1532
1533 #if !defined(NDEBUG)
1534         if (opt_verbosethreads) {
1535                 printf("[Detaching thread ");
1536                 threads_thread_print_info(t);
1537                 printf("]\n");
1538         }
1539 #endif
1540
1541         /* Enter the join-mutex before calling threads_thread_free, so
1542            threads_join_all_threads gets the correct number of non-daemon
1543            threads. */
1544
1545         threads_mutex_join_lock();
1546
1547         /* free the vm internal thread object */
1548
1549         threads_thread_free(t);
1550
1551         /* Signal that this thread has finished and leave the mutex. */
1552
1553         pthread_cond_signal(&cond_join);
1554         threads_mutex_join_unlock();
1555
1556         return true;
1557 }
1558
1559
1560 /* threads_join_all_threads ****************************************************
1561
1562    Join all non-daemon threads.
1563
1564 *******************************************************************************/
1565
1566 void threads_join_all_threads(void)
1567 {
1568         threadobject *t;
1569
1570         /* get current thread */
1571
1572         t = THREADOBJECT;
1573
1574         /* this thread is waiting for all non-daemon threads to exit */
1575
1576         threads_thread_state_waiting(t);
1577
1578         /* enter join mutex */
1579
1580         threads_mutex_join_lock();
1581
1582         /* Wait for condition as long as we have non-daemon threads.  We
1583            compare against 1 because the current (main thread) is also a
1584            non-daemon thread. */
1585
1586         while (threads_list_get_non_daemons() > 1)
1587                 pthread_cond_wait(&cond_join, &mutex_join);
1588
1589         /* leave join mutex */
1590
1591         threads_mutex_join_unlock();
1592 }
1593
1594
1595 /* threads_timespec_earlier ****************************************************
1596
1597    Return true if timespec tv1 is earlier than timespec tv2.
1598
1599    IN:
1600       tv1..........first timespec
1601           tv2..........second timespec
1602
1603    RETURN VALUE:
1604       true, if the first timespec is earlier
1605
1606 *******************************************************************************/
1607
1608 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1609                                                                                         const struct timespec *tv2)
1610 {
1611         return (tv1->tv_sec < tv2->tv_sec)
1612                                 ||
1613                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1614 }
1615
1616
1617 /* threads_current_time_is_earlier_than ****************************************
1618
1619    Check if the current time is earlier than the given timespec.
1620
1621    IN:
1622       tv...........the timespec to compare against
1623
1624    RETURN VALUE:
1625       true, if the current time is earlier
1626
1627 *******************************************************************************/
1628
1629 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1630 {
1631         struct timeval tvnow;
1632         struct timespec tsnow;
1633
1634         /* get current time */
1635
1636         if (gettimeofday(&tvnow, NULL) != 0)
1637                 vm_abort("gettimeofday failed: %s\n", strerror(errno));
1638
1639         /* convert it to a timespec */
1640
1641         tsnow.tv_sec = tvnow.tv_sec;
1642         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1643
1644         /* compare current time with the given timespec */
1645
1646         return threads_timespec_earlier(&tsnow, tv);
1647 }
1648
1649
1650 /* threads_wait_with_timeout ***************************************************
1651
1652    Wait until the given point in time on a monitor until either
1653    we are notified, we are interrupted, or the time is up.
1654
1655    IN:
1656       t............the current thread
1657           wakeupTime...absolute (latest) wakeup time
1658                            If both tv_sec and tv_nsec are zero, this function
1659                                            waits for an unlimited amount of time.
1660
1661    RETURN VALUE:
1662       true.........if the wait has been interrupted,
1663           false........if the wait was ended by notification or timeout
1664
1665 *******************************************************************************/
1666
1667 static bool threads_wait_with_timeout(threadobject *thread,
1668                                                                           struct timespec *wakeupTime)
1669 {
1670         bool wasinterrupted;
1671
1672         /* acquire the waitmutex */
1673
1674         pthread_mutex_lock(&thread->waitmutex);
1675
1676         /* mark us as sleeping */
1677
1678         thread->sleeping = true;
1679
1680         /* wait on waitcond */
1681
1682         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1683                 /* with timeout */
1684                 while (!thread->interrupted && !thread->signaled
1685                            && threads_current_time_is_earlier_than(wakeupTime))
1686                 {
1687                         threads_thread_state_timed_waiting(thread);
1688
1689                         pthread_cond_timedwait(&thread->waitcond, &thread->waitmutex,
1690                                                                    wakeupTime);
1691
1692                         threads_thread_state_runnable(thread);
1693                 }
1694         }
1695         else {
1696                 /* no timeout */
1697                 while (!thread->interrupted && !thread->signaled) {
1698                         threads_thread_state_waiting(thread);
1699
1700                         pthread_cond_wait(&thread->waitcond, &thread->waitmutex);
1701
1702                         threads_thread_state_runnable(thread);
1703                 }
1704         }
1705
1706         /* check if we were interrupted */
1707
1708         wasinterrupted = thread->interrupted;
1709
1710         /* reset all flags */
1711
1712         thread->interrupted = false;
1713         thread->signaled    = false;
1714         thread->sleeping    = false;
1715
1716         /* release the waitmutex */
1717
1718         pthread_mutex_unlock(&thread->waitmutex);
1719
1720         return wasinterrupted;
1721 }
1722
1723
1724 /* threads_wait_with_timeout_relative ******************************************
1725
1726    Wait for the given maximum amount of time on a monitor until either
1727    we are notified, we are interrupted, or the time is up.
1728
1729    IN:
1730       t............the current thread
1731           millis.......milliseconds to wait
1732           nanos........nanoseconds to wait
1733
1734    RETURN VALUE:
1735       true.........if the wait has been interrupted,
1736           false........if the wait was ended by notification or timeout
1737
1738 *******************************************************************************/
1739
1740 bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
1741                                                                                 s4 nanos)
1742 {
1743         struct timespec wakeupTime;
1744
1745         /* calculate the the (latest) wakeup time */
1746
1747         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1748
1749         /* wait */
1750
1751         return threads_wait_with_timeout(thread, &wakeupTime);
1752 }
1753
1754
1755 /* threads_calc_absolute_time **************************************************
1756
1757    Calculate the absolute point in time a given number of ms and ns from now.
1758
1759    IN:
1760       millis............milliseconds from now
1761           nanos.............nanoseconds from now
1762
1763    OUT:
1764       *tm...............receives the timespec of the absolute point in time
1765
1766 *******************************************************************************/
1767
1768 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1769 {
1770         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1771                 struct timeval tv;
1772                 long nsec;
1773                 gettimeofday(&tv, NULL);
1774                 tv.tv_sec += millis / 1000;
1775                 millis %= 1000;
1776                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1777                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1778                 tm->tv_nsec = nsec % 1000000000;
1779         }
1780         else {
1781                 tm->tv_sec = 0;
1782                 tm->tv_nsec = 0;
1783         }
1784 }
1785
1786
1787 /* threads_thread_interrupt ****************************************************
1788
1789    Interrupt the given thread.
1790
1791    The thread gets the "waitcond" signal and 
1792    its interrupted flag is set to true.
1793
1794    IN:
1795       thread............the thread to interrupt
1796
1797 *******************************************************************************/
1798
1799 void threads_thread_interrupt(threadobject *thread)
1800 {
1801         /* Signal the thread a "waitcond" and tell it that it has been
1802            interrupted. */
1803
1804         pthread_mutex_lock(&thread->waitmutex);
1805
1806         /* Interrupt blocking system call using a signal. */
1807
1808         pthread_kill(thread->tid, SIGHUP);
1809
1810         if (thread->sleeping)
1811                 pthread_cond_signal(&thread->waitcond);
1812
1813         thread->interrupted = true;
1814
1815         pthread_mutex_unlock(&thread->waitmutex);
1816 }
1817
1818
1819 /* threads_check_if_interrupted_and_reset **************************************
1820
1821    Check if the current thread has been interrupted and reset the
1822    interruption flag.
1823
1824    RETURN VALUE:
1825       true, if the current thread had been interrupted
1826
1827 *******************************************************************************/
1828
1829 bool threads_check_if_interrupted_and_reset(void)
1830 {
1831         threadobject *thread;
1832         bool intr;
1833
1834         thread = THREADOBJECT;
1835
1836         /* get interrupted flag */
1837
1838         intr = thread->interrupted;
1839
1840         /* reset interrupted flag */
1841
1842         thread->interrupted = false;
1843
1844         return intr;
1845 }
1846
1847
1848 /* threads_thread_has_been_interrupted *****************************************
1849
1850    Check if the given thread has been interrupted
1851
1852    IN:
1853       t............the thread to check
1854
1855    RETURN VALUE:
1856       true, if the given thread had been interrupted
1857
1858 *******************************************************************************/
1859
1860 bool threads_thread_has_been_interrupted(threadobject *thread)
1861 {
1862         return thread->interrupted;
1863 }
1864
1865
1866 /* threads_sleep ***************************************************************
1867
1868    Sleep the current thread for the specified amount of time.
1869
1870 *******************************************************************************/
1871
1872 void threads_sleep(s8 millis, s4 nanos)
1873 {
1874         threadobject    *thread;
1875         struct timespec  wakeupTime;
1876         bool             wasinterrupted;
1877
1878         thread = THREADOBJECT;
1879
1880         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1881
1882         wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
1883
1884         if (wasinterrupted)
1885                 exceptions_throw_interruptedexception();
1886 }
1887
1888
1889 /* threads_yield ***************************************************************
1890
1891    Yield to the scheduler.
1892
1893 *******************************************************************************/
1894
1895 void threads_yield(void)
1896 {
1897         sched_yield();
1898 }
1899
1900
1901 /*
1902  * These are local overrides for various environment variables in Emacs.
1903  * Please do not remove this and leave it at the end of the file, where
1904  * Emacs will automagically detect them.
1905  * ---------------------------------------------------------------------
1906  * Local variables:
1907  * mode: c
1908  * indent-tabs-mode: t
1909  * c-basic-offset: 4
1910  * tab-width: 4
1911  * End:
1912  * vim:noexpandtab:sw=4:ts=4:
1913  */