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