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