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