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