* src/vm/hashtable.h,
[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 4921 2006-05-15 14:24:36Z 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         fprintf(stderr,"error: sem_init returned unexpected error %d: %s\n",
328                         errno, strerror(errno));
329         abort();
330 }
331
332
333 /* threads_sem_wait ************************************************************
334  
335    Wait for a semaphore, non-interruptible.
336
337    IMPORTANT: Always use this function instead of `sem_wait` directly, as
338               `sem_wait` may be interrupted by signals!
339   
340    IN:
341        sem..............the semaphore to wait on
342    
343 *******************************************************************************/
344
345 void threads_sem_wait(sem_t *sem)
346 {
347         int r;
348
349         assert(sem);
350
351         do {
352                 r = sem_wait(sem);
353                 if (r == 0)
354                         return;
355         } while (errno == EINTR);
356
357         fprintf(stderr,"error: sem_wait returned unexpected error %d: %s\n",
358                         errno, strerror(errno));
359         abort();
360 }
361
362
363 /* threads_sem_post ************************************************************
364  
365    Increase the count of a semaphore. Checks for errors.
366
367    IN:
368        sem..............the semaphore to increase the count of
369    
370 *******************************************************************************/
371
372 void threads_sem_post(sem_t *sem)
373 {
374         int r;
375
376         assert(sem);
377
378         /* unlike sem_wait, sem_post is not interruptible */
379
380         r = sem_post(sem);
381         if (r == 0)
382                 return;
383
384         fprintf(stderr,"error: sem_post returned unexpected error %d: %s\n",
385                         errno, strerror(errno));
386         abort();
387 }
388
389
390 /* threads_set_thread_priority *************************************************
391
392    Set the priority of the given thread.
393
394    IN:
395       tid..........thread id
396           priority.....priority to set
397
398 ******************************************************************************/
399
400 static void threads_set_thread_priority(pthread_t tid, int priority)
401 {
402         struct sched_param schedp;
403         int policy;
404
405         pthread_getschedparam(tid, &policy, &schedp);
406         schedp.sched_priority = priority;
407         pthread_setschedparam(tid, policy, &schedp);
408 }
409
410
411 /* compiler_lock ***************************************************************
412
413    Enter the compiler lock.
414
415 ******************************************************************************/
416
417 void compiler_lock(void)
418 {
419         pthread_mutex_lock_rec(&compiler_mutex);
420 }
421
422
423 /* compiler_unlock *************************************************************
424
425    Release the compiler lock.
426
427 ******************************************************************************/
428
429 void compiler_unlock(void)
430 {
431         pthread_mutex_unlock_rec(&compiler_mutex);
432 }
433
434
435 /* lock_stopworld **************************************************************
436
437    Enter the stopworld lock, specifying why the world shall be stopped.
438
439    IN:
440       where........ STOPWORLD_FROM_GC              (1) from within GC
441                     STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
442
443 ******************************************************************************/
444
445 void lock_stopworld(int where)
446 {
447         pthread_mutex_lock(&stopworldlock);
448         stopworldwhere = where;
449 }
450
451
452 /* unlock_stopworld ************************************************************
453
454    Release the stopworld lock.
455
456 ******************************************************************************/
457
458 void unlock_stopworld(void)
459 {
460         stopworldwhere = 0;
461         pthread_mutex_unlock(&stopworldlock);
462 }
463
464 #if !defined(__DARWIN__)
465 /* Caller must hold threadlistlock */
466 static int threads_cast_sendsignals(int sig, int count)
467 {
468         /* Count threads */
469         threadobject *tobj = mainthreadobj;
470         threadobject *self = THREADOBJECT;
471
472         if (count == 0) {
473                 do {
474                         count++;
475                         tobj = tobj->next;
476                 } while (tobj != mainthreadobj);
477         }
478
479         assert(tobj == mainthreadobj);
480
481         do {
482                 if (tobj != self)
483                         pthread_kill(tobj->tid, sig);
484                 tobj = tobj->next;
485         } while (tobj != mainthreadobj);
486
487         return count - 1;
488 }
489
490 #else
491
492 static void threads_cast_darwinstop(void)
493 {
494         threadobject *tobj = mainthreadobj;
495         threadobject *self = THREADOBJECT;
496
497         do {
498                 if (tobj != self)
499                 {
500                         thread_state_flavor_t flavor = PPC_THREAD_STATE;
501                         mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
502                         ppc_thread_state_t thread_state;
503                         mach_port_t thread = tobj->mach_thread;
504                         kern_return_t r;
505
506                         r = thread_suspend(thread);
507                         if (r != KERN_SUCCESS) {
508                                 log_text("thread_suspend failed");
509                                 assert(0);
510                         }
511
512                         r = thread_get_state(thread, flavor,
513                                 (natural_t*)&thread_state, &thread_state_count);
514                         if (r != KERN_SUCCESS) {
515                                 log_text("thread_get_state failed");
516                                 assert(0);
517                         }
518
519                         thread_restartcriticalsection(&thread_state);
520
521                         r = thread_set_state(thread, flavor,
522                                 (natural_t*)&thread_state, thread_state_count);
523                         if (r != KERN_SUCCESS) {
524                                 log_text("thread_set_state failed");
525                                 assert(0);
526                         }
527                 }
528                 tobj = tobj->next;
529         } while (tobj != mainthreadobj);
530 }
531
532 static void threads_cast_darwinresume(void)
533 {
534         threadobject *tobj = mainthreadobj;
535         threadobject *self = THREADOBJECT;
536
537         do {
538                 if (tobj != self)
539                 {
540                         mach_port_t thread = tobj->mach_thread;
541                         kern_return_t r;
542
543                         r = thread_resume(thread);
544                         if (r != KERN_SUCCESS) {
545                                 log_text("thread_resume failed");
546                                 assert(0);
547                         }
548                 }
549                 tobj = tobj->next;
550         } while (tobj != mainthreadobj);
551 }
552
553 #endif
554
555 #if defined(__MIPS__)
556 static void threads_cast_irixresume(void)
557 {
558         pthread_mutex_lock(&suspend_ack_lock);
559         pthread_cond_broadcast(&suspend_cond);
560         pthread_mutex_unlock(&suspend_ack_lock);
561 }
562 #endif
563
564 void threads_cast_stopworld(void)
565 {
566         int count, i;
567         lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
568         pthread_mutex_lock(&threadlistlock);
569 #if defined(__DARWIN__)
570         threads_cast_darwinstop();
571 #else
572         count = threads_cast_sendsignals(GC_signum1(), 0);
573         for (i=0; i<count; i++)
574                 threads_sem_wait(&suspend_ack);
575 #endif
576         pthread_mutex_unlock(&threadlistlock);
577 }
578
579 void threads_cast_startworld(void)
580 {
581         pthread_mutex_lock(&threadlistlock);
582 #if defined(__DARWIN__)
583         threads_cast_darwinresume();
584 #elif defined(__MIPS__)
585         threads_cast_irixresume();
586 #else
587         threads_cast_sendsignals(GC_signum2(), -1);
588 #endif
589         pthread_mutex_unlock(&threadlistlock);
590         unlock_stopworld();
591 }
592
593 #if !defined(__DARWIN__)
594 static void threads_sigsuspend_handler(ucontext_t *ctx)
595 {
596         int sig;
597         sigset_t sigs;
598
599         /* XXX TWISTI: this is just a quick hack */
600 #if defined(ENABLE_JIT)
601         thread_restartcriticalsection(ctx);
602 #endif
603
604         /* Do as Boehm does. On IRIX a condition variable is used for wake-up
605            (not POSIX async-safe). */
606 #if defined(__IRIX__)
607         pthread_mutex_lock(&suspend_ack_lock);
608         threads_sem_post(&suspend_ack);
609         pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
610         pthread_mutex_unlock(&suspend_ack_lock);
611 #else
612         threads_sem_post(&suspend_ack);
613
614         sig = GC_signum2();
615         sigfillset(&sigs);
616         sigdelset(&sigs, sig);
617         sigsuspend(&sigs);
618 #endif
619 }
620
621 /* This function is called from Boehm GC code. */
622
623 int cacao_suspendhandler(ucontext_t *ctx)
624 {
625         if (stopworldwhere != STOPWORLD_FROM_CLASS_NUMBERING)
626                 return 0;
627
628         threads_sigsuspend_handler(ctx);
629         return 1;
630 }
631 #endif
632
633
634 /* threads_set_current_threadobject ********************************************
635
636    Set the current thread object.
637    
638    IN:
639       thread.......the thread object to set
640
641 *******************************************************************************/
642
643 #if !defined(ENABLE_JVMTI)
644 static void threads_set_current_threadobject(threadobject *thread)
645 #else
646 void threads_set_current_threadobject(threadobject *thread)
647 #endif
648 {
649 #if !defined(HAVE___THREAD)
650         pthread_setspecific(threads_current_threadobject_key, thread);
651 #else
652         threads_current_threadobject = thread;
653 #endif
654 }
655
656
657 /* threads_get_current_threadobject ********************************************
658
659    Return the threadobject of the current thread.
660    
661    RETURN VALUE:
662        the current threadobject * (an instance of java.lang.VMThread)
663
664 *******************************************************************************/
665
666 threadobject *threads_get_current_threadobject(void)
667 {
668         return THREADOBJECT;
669 }
670
671
672 /* threads_preinit *************************************************************
673
674    Do some early initialization of stuff required.
675
676 *******************************************************************************/
677
678 void threads_preinit(void)
679 {
680 #ifndef MUTEXSIM
681         pthread_mutexattr_t mutexattr;
682         pthread_mutexattr_init(&mutexattr);
683         pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
684         pthread_mutex_init(&compiler_mutex, &mutexattr);
685         pthread_mutexattr_destroy(&mutexattr);
686 #else
687         pthread_mutex_init_rec(&compiler_mutex);
688 #endif
689
690         pthread_mutex_init(&threadlistlock, NULL);
691         pthread_mutex_init(&stopworldlock, NULL);
692
693         /* Allocate something so the garbage collector's signal handlers
694            are installed. */
695         heap_allocate(1, false, NULL);
696
697         mainthreadobj = NEW(threadobject);
698         mainthreadobj->tid = pthread_self();
699         mainthreadobj->index = 1;
700         mainthreadobj->thinlock = lock_pre_compute_thinlock(mainthreadobj->index);
701         
702 #if !defined(HAVE___THREAD)
703         pthread_key_create(&threads_current_threadobject_key, NULL);
704 #endif
705         threads_set_current_threadobject(mainthreadobj);
706
707         threads_sem_init(&suspend_ack, 0, 0);
708
709         /* initialize the threads table */
710
711         threads_table_init();
712
713         /* initialize subsystems */
714
715         lock_init();
716
717         critical_init();
718 }
719
720
721 /* threads_init ****************************************************************
722
723    Initializes the threads required by the JVM: main, finalizer.
724
725 *******************************************************************************/
726
727 bool threads_init(void)
728 {
729         java_lang_String      *threadname;
730         java_lang_Thread      *mainthread;
731         java_lang_ThreadGroup *threadgroup;
732         threadobject          *tempthread;
733         methodinfo            *method;
734
735         tempthread = mainthreadobj;
736
737         /* XXX We have to find a new way to free lock records */
738         /*     with the new locking algorithm.                */
739         /* lock_record_free_pools(mainthreadobj->ee.lockrecordpools); */
740
741         /* This is kinda tricky, we grow the java.lang.Thread object so we
742            can keep the execution environment there. No Thread object must
743            have been created at an earlier time. */
744
745         class_java_lang_VMThread->instancesize = sizeof(threadobject);
746
747         /* create a VMThread */
748
749         mainthreadobj = (threadobject *) builtin_new(class_java_lang_VMThread);
750
751         if (!mainthreadobj)
752                 return false;
753
754         FREE(tempthread, threadobject);
755
756         threads_init_threadobject(&mainthreadobj->o);
757
758         threads_set_current_threadobject(mainthreadobj);
759
760         lock_init_execution_env(mainthreadobj);
761
762         mainthreadobj->next = mainthreadobj;
763         mainthreadobj->prev = mainthreadobj;
764
765         threads_table_add(mainthreadobj);
766
767 #if defined(ENABLE_INTRP)
768         /* create interpreter stack */
769
770         if (opt_intrp) {
771                 MSET(intrp_main_stack, 0, u1, opt_stacksize);
772                 mainthreadobj->_global_sp = intrp_main_stack + opt_stacksize;
773         }
774 #endif
775
776         threadname = javastring_new(utf_new_char("main"));
777
778         /* allocate and init ThreadGroup */
779
780         threadgroup = (java_lang_ThreadGroup *)
781                 native_new_and_init(class_java_lang_ThreadGroup);
782
783         if (!threadgroup)
784                 throw_exception_exit();
785
786         /* create a Thread */
787
788         mainthread = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
789
790         if (!mainthread)
791                 throw_exception_exit();
792
793         mainthreadobj->o.thread = mainthread;
794
795         /* call Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
796
797         method = class_resolveclassmethod(class_java_lang_Thread,
798                                                                           utf_init,
799                                                                           utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
800                                                                           class_java_lang_Thread,
801                                                                           true);
802
803         if (!method)
804                 return false;
805
806         (void) vm_call_method(method, (java_objectheader *) mainthread,
807                                                   mainthreadobj, threadname, 5, false);
808
809         if (*exceptionptr)
810                 return false;
811
812         mainthread->group = threadgroup;
813
814         /* add mainthread to ThreadGroup */
815
816         method = class_resolveclassmethod(class_java_lang_ThreadGroup,
817                                                                           utf_new_char("addThread"),
818                                                                           utf_new_char("(Ljava/lang/Thread;)V"),
819                                                                           class_java_lang_ThreadGroup,
820                                                                           true);
821
822         if (!method)
823                 return false;
824
825         (void) vm_call_method(method, (java_objectheader *) threadgroup,
826                                                   mainthread);
827
828         if (*exceptionptr)
829                 return false;
830
831         threads_set_thread_priority(pthread_self(), 5);
832
833         pthread_attr_init(&threadattr);
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         startupinfo   startup;
1156         threadobject *thread;
1157
1158         thread = (threadobject *) t->vmThread;
1159
1160         /* fill startupinfo structure passed by pthread_create to
1161          * threads_startup_thread */
1162
1163         startup.thread     = thread;
1164         startup.function   = function;       /* maybe we don't call Thread.run()V */
1165         startup.psem       = &sem;
1166         startup.psem_first = &sem_first;
1167
1168         threads_sem_init(&sem, 0, 0);
1169         threads_sem_init(&sem_first, 0, 0);
1170
1171         /* create the thread */
1172
1173         if (pthread_create(&thread->tid, &threadattr, threads_startup_thread,
1174                                            &startup)) {
1175                 log_text("pthread_create failed");
1176                 assert(0);
1177         }
1178
1179         /* signal that pthread_create has returned, so thread->tid is valid */
1180
1181         threads_sem_post(&sem_first);
1182
1183         /* wait here until the thread has entered itself into the thread list */
1184
1185         threads_sem_wait(&sem);
1186
1187         /* cleanup */
1188
1189         sem_destroy(&sem);
1190         sem_destroy(&sem_first);
1191 }
1192
1193
1194 /* threads_find_non_daemon_thread **********************************************
1195
1196    Helper function used by threads_join_all_threads for finding non-daemon threads
1197    that are still running.
1198
1199 *******************************************************************************/
1200
1201 /* At the end of the program, we wait for all running non-daemon threads to die
1202  */
1203
1204 static threadobject *threads_find_non_daemon_thread(threadobject *thread)
1205 {
1206         while (thread != mainthreadobj) {
1207                 if (!thread->o.thread->daemon)
1208                         return thread;
1209                 thread = thread->prev;
1210         }
1211
1212         return NULL;
1213 }
1214
1215
1216 /* threads_join_all_threads ****************************************************
1217
1218    Join all non-daemon threads.
1219
1220 *******************************************************************************/
1221
1222 void threads_join_all_threads(void)
1223 {
1224         threadobject *thread;
1225
1226         pthread_mutex_lock(&threadlistlock);
1227
1228         while ((thread = threads_find_non_daemon_thread(mainthreadobj->prev)) != NULL) {
1229
1230                 pthread_mutex_lock(&thread->joinmutex);
1231
1232                 pthread_mutex_unlock(&threadlistlock);
1233
1234                 while (thread->tid)
1235                         pthread_cond_wait(&thread->joincond, &thread->joinmutex);
1236
1237                 pthread_mutex_unlock(&thread->joinmutex);
1238
1239                 pthread_mutex_lock(&threadlistlock);
1240         }
1241
1242         pthread_mutex_unlock(&threadlistlock);
1243 }
1244
1245
1246 /* threads_timespec_earlier ****************************************************
1247
1248    Return true if timespec tv1 is earlier than timespec tv2.
1249
1250    IN:
1251       tv1..........first timespec
1252           tv2..........second timespec
1253
1254    RETURN VALUE:
1255       true, if the first timespec is earlier
1256
1257 *******************************************************************************/
1258
1259 static inline bool threads_timespec_earlier(const struct timespec *tv1,
1260                                                                                         const struct timespec *tv2)
1261 {
1262         return (tv1->tv_sec < tv2->tv_sec)
1263                                 ||
1264                 (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
1265 }
1266
1267
1268 /* threads_current_time_is_earlier_than ****************************************
1269
1270    Check if the current time is earlier than the given timespec.
1271
1272    IN:
1273       tv...........the timespec to compare against
1274
1275    RETURN VALUE:
1276       true, if the current time is earlier
1277
1278 *******************************************************************************/
1279
1280 static bool threads_current_time_is_earlier_than(const struct timespec *tv)
1281 {
1282         struct timeval tvnow;
1283         struct timespec tsnow;
1284
1285         /* get current time */
1286
1287         if (gettimeofday(&tvnow, NULL) != 0) {
1288                 fprintf(stderr,"error: gettimeofday returned unexpected error %d: %s\n",
1289                                 errno, strerror(errno));
1290                 abort();
1291         }
1292
1293         /* convert it to a timespec */
1294
1295         tsnow.tv_sec = tvnow.tv_sec;
1296         tsnow.tv_nsec = tvnow.tv_usec * 1000;
1297
1298         /* compare current time with the given timespec */
1299
1300         return threads_timespec_earlier(&tsnow, tv);
1301 }
1302
1303
1304 /* threads_wait_with_timeout ***************************************************
1305
1306    Wait until the given point in time on a monitor until either
1307    we are notified, we are interrupted, or the time is up.
1308
1309    IN:
1310       t............the current thread
1311           wakeupTime...absolute (latest) wakeup time
1312                            If both tv_sec and tv_nsec are zero, this function
1313                                            waits for an unlimited amount of time.
1314
1315    RETURN VALUE:
1316       true.........if the wait has been interrupted,
1317           false........if the wait was ended by notification or timeout
1318
1319 *******************************************************************************/
1320
1321 static bool threads_wait_with_timeout(threadobject *t,
1322                                                                           struct timespec *wakeupTime)
1323 {
1324         bool wasinterrupted;
1325
1326         /* acquire the waitmutex */
1327
1328         pthread_mutex_lock(&t->waitmutex);
1329
1330         /* mark us as sleeping */
1331
1332         t->sleeping = true;
1333
1334         /* wait on waitcond */
1335
1336         if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
1337                 /* with timeout */
1338                 while (!t->interrupted && !t->signaled
1339                            && threads_current_time_is_earlier_than(wakeupTime))
1340                 {
1341                         pthread_cond_timedwait(&t->waitcond, &t->waitmutex, wakeupTime);
1342                 }
1343         }
1344         else {
1345                 /* no timeout */
1346                 while (!t->interrupted && !t->signaled)
1347                         pthread_cond_wait(&t->waitcond, &t->waitmutex);
1348         }
1349
1350         /* check if we were interrupted */
1351
1352         wasinterrupted = t->interrupted;
1353
1354         /* reset all flags */
1355
1356         t->interrupted = false;
1357         t->signaled = false;
1358         t->sleeping = false;
1359
1360         /* release the waitmutex */
1361
1362         pthread_mutex_unlock(&t->waitmutex);
1363
1364         return wasinterrupted;
1365 }
1366
1367
1368 /* threads_wait_with_timeout_relative ******************************************
1369
1370    Wait for the given maximum amount of time on a monitor until either
1371    we are notified, we are interrupted, or the time is up.
1372
1373    IN:
1374       t............the current thread
1375           millis.......milliseconds to wait
1376           nanos........nanoseconds to wait
1377
1378    RETURN VALUE:
1379       true.........if the wait has been interrupted,
1380           false........if the wait was ended by notification or timeout
1381
1382 *******************************************************************************/
1383
1384 bool threads_wait_with_timeout_relative(threadobject *t,
1385                                                                                 s8 millis,
1386                                                                                 s4 nanos)
1387 {
1388         struct timespec wakeupTime;
1389
1390         /* calculate the the (latest) wakeup time */
1391
1392         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1393
1394         /* wait */
1395
1396         return threads_wait_with_timeout(t, &wakeupTime);
1397 }
1398
1399
1400 /* threads_calc_absolute_time **************************************************
1401
1402    Calculate the absolute point in time a given number of ms and ns from now.
1403
1404    IN:
1405       millis............milliseconds from now
1406           nanos.............nanoseconds from now
1407
1408    OUT:
1409       *tm...............receives the timespec of the absolute point in time
1410
1411 *******************************************************************************/
1412
1413 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
1414 {
1415         if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
1416                 struct timeval tv;
1417                 long nsec;
1418                 gettimeofday(&tv, NULL);
1419                 tv.tv_sec += millis / 1000;
1420                 millis %= 1000;
1421                 nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
1422                 tm->tv_sec = tv.tv_sec + nsec / 1000000000;
1423                 tm->tv_nsec = nsec % 1000000000;
1424         }
1425         else {
1426                 tm->tv_sec = 0;
1427                 tm->tv_nsec = 0;
1428         }
1429 }
1430
1431
1432 /* threads_interrupt_thread ****************************************************
1433
1434    Interrupt the given thread.
1435
1436    The thread gets the "waitcond" signal and 
1437    its interrupted flag is set to true.
1438
1439    IN:
1440       thread............the thread to interrupt
1441
1442 *******************************************************************************/
1443
1444 void threads_interrupt_thread(java_lang_VMThread *thread)
1445 {
1446         threadobject *t = (threadobject*) thread;
1447
1448         /* signal the thread a "waitcond" and tell it that it has been */
1449         /* interrupted                                                 */
1450
1451         pthread_mutex_lock(&t->waitmutex);
1452         if (t->sleeping)
1453                 pthread_cond_signal(&t->waitcond);
1454         t->interrupted = true;
1455         pthread_mutex_unlock(&t->waitmutex);
1456 }
1457
1458
1459 /* threads_check_if_interrupted_and_reset **************************************
1460
1461    Check if the current thread has been interrupted and reset the
1462    interruption flag.
1463
1464    RETURN VALUE:
1465       true, if the current thread had been interrupted
1466
1467 *******************************************************************************/
1468
1469 bool threads_check_if_interrupted_and_reset(void)
1470 {
1471         threadobject *t;
1472         bool intr;
1473
1474         t = (threadobject*) THREADOBJECT;
1475
1476         intr = t->interrupted;
1477
1478         t->interrupted = false;
1479
1480         return intr;
1481 }
1482
1483
1484 /* threads_thread_has_been_interrupted *********************************************************
1485
1486    Check if the given thread has been interrupted
1487
1488    IN:
1489       t............the thread to check
1490
1491    RETURN VALUE:
1492       true, if the given thread had been interrupted
1493
1494 *******************************************************************************/
1495
1496 bool threads_thread_has_been_interrupted(java_lang_VMThread *thread)
1497 {
1498         threadobject *t;
1499
1500         t = (threadobject*) thread;
1501
1502         return t->interrupted;
1503 }
1504
1505
1506 /* threads_sleep ***************************************************************
1507
1508    Sleep the current thread for the specified amount of time.
1509
1510 *******************************************************************************/
1511
1512 void threads_sleep(s8 millis, s4 nanos)
1513 {
1514         threadobject       *t;
1515         struct timespec    wakeupTime;
1516         bool               wasinterrupted;
1517
1518         t = (threadobject *) THREADOBJECT;
1519
1520         threads_calc_absolute_time(&wakeupTime, millis, nanos);
1521
1522         wasinterrupted = threads_wait_with_timeout(t, &wakeupTime);
1523
1524         if (wasinterrupted)
1525                 *exceptionptr = new_exception(string_java_lang_InterruptedException);
1526 }
1527
1528
1529 /* threads_yield *****************************************************************
1530
1531    Yield to the scheduler.
1532
1533 *******************************************************************************/
1534
1535 void threads_yield(void)
1536 {
1537         sched_yield();
1538 }
1539
1540
1541 /* threads_java_lang_Thread_set_priority ***********************************************************
1542
1543    Set the priority for the given java.lang.Thread.
1544
1545    IN:
1546       t............the java.lang.Thread
1547           priority.....the priority
1548
1549 *******************************************************************************/
1550
1551 void threads_java_lang_Thread_set_priority(java_lang_Thread *t, s4 priority)
1552 {
1553         threadobject *thread;
1554
1555         thread = (threadobject*) t->vmThread;
1556
1557         threads_set_thread_priority(thread->tid, priority);
1558 }
1559
1560
1561 /* threads_dump ****************************************************************
1562
1563    Dumps info for all threads running in the JVM. This function is
1564    called when SIGQUIT (<ctrl>-\) is sent to CACAO.
1565
1566 *******************************************************************************/
1567
1568 void threads_dump(void)
1569 {
1570         threadobject       *tobj;
1571         java_lang_VMThread *vmt;
1572         java_lang_Thread   *t;
1573         utf                *name;
1574
1575         tobj = mainthreadobj;
1576
1577         printf("Full thread dump CACAO "VERSION":\n");
1578
1579         /* iterate over all started threads */
1580
1581         do {
1582                 /* get thread objects */
1583
1584                 vmt = &tobj->o;
1585                 t   = vmt->thread;
1586
1587                 /* the thread may be currently in initalization, don't print it */
1588
1589                 if (t) {
1590                         /* get thread name */
1591
1592                         name = javastring_toutf(t->name, false);
1593
1594                         printf("\n\"");
1595                         utf_display_printable_ascii(name);
1596                         printf("\" ");
1597
1598                         if (t->daemon)
1599                                 printf("daemon ");
1600
1601 #if SIZEOF_VOID_P == 8
1602                         printf("prio=%d tid=0x%016lx\n", t->priority, tobj->tid);
1603 #else
1604                         printf("prio=%d tid=0x%08lx\n", t->priority, tobj->tid);
1605 #endif
1606
1607                         /* send SIGUSR1 to thread to print stacktrace */
1608
1609                         pthread_kill(tobj->tid, SIGUSR1);
1610
1611                         /* sleep this thread a bit, so the signal can reach the thread */
1612
1613                         threads_sleep(10, 0);
1614                 }
1615
1616                 tobj = tobj->next;
1617         } while (tobj && (tobj != mainthreadobj));
1618 }
1619
1620
1621 /* threads_table_dump *********************************************************
1622
1623    Dump the threads table for debugging purposes.
1624
1625    IN:
1626       file..............stream to write to
1627
1628 ******************************************************************************/
1629
1630 #if !defined(NDEBUG)
1631 static void threads_table_dump(FILE *file)
1632 {
1633         s4 i;
1634         s4 size;
1635         ptrint index;
1636
1637         pthread_mutex_lock(&threadlistlock);
1638
1639         size = threads_table.size;
1640
1641         fprintf(file, "======== THREADS TABLE (size %d) ========\n", size);
1642
1643         for (i=0; i<size; ++i) {
1644                 index = threads_table.table[i].nextfree;
1645
1646                 fprintf(file, "%4d: ", i);
1647
1648                 if (index < size) {
1649                         fprintf(file, "free, nextfree = %d\n", index);
1650                 }
1651                 else {
1652                         fprintf(file, "thread %p\n", (void*) threads_table.table[i].thread);
1653                 }
1654         }
1655
1656         fprintf(file, "======== END OF THREADS TABLE ========\n");
1657
1658         pthread_mutex_unlock(&threadlistlock);
1659 }
1660 #endif
1661
1662 /*
1663  * These are local overrides for various environment variables in Emacs.
1664  * Please do not remove this and leave it at the end of the file, where
1665  * Emacs will automagically detect them.
1666  * ---------------------------------------------------------------------
1667  * Local variables:
1668  * mode: c
1669  * indent-tabs-mode: t
1670  * c-basic-offset: 4
1671  * tab-width: 4
1672  * End:
1673  * vim:noexpandtab:sw=4:ts=4:
1674  */