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