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