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