Wed Feb 1 18:23:55 CET 2006 Paolo Molaro <lupus@ximian.com>
[mono.git] / libgc / pthread_support.c
1 /* 
2  * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
3  * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
4  * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
5  * Copyright (c) 2000-2004 by Hewlett-Packard Company.  All rights reserved.
6  *
7  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
8  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
9  *
10  * Permission is hereby granted to use or copy this program
11  * for any purpose,  provided the above notices are retained on all copies.
12  * Permission to modify the code and to distribute modified code is granted,
13  * provided the above notices are retained, and a notice that the code was
14  * modified is included with the above copyright notice.
15  */
16 /*
17  * Support code for LinuxThreads, the clone()-based kernel
18  * thread package for Linux which is included in libc6.
19  *
20  * This code relies on implementation details of LinuxThreads,
21  * (i.e. properties not guaranteed by the Pthread standard),
22  * though this version now does less of that than the other Pthreads
23  * support code.
24  *
25  * Note that there is a lot of code duplication between linux_threads.c
26  * and thread support for some of the other Posix platforms; any changes
27  * made here may need to be reflected there too.
28  */
29  /* DG/UX ix86 support <takis@xfree86.org> */
30 /*
31  * Linux_threads.c now also includes some code to support HPUX and
32  * OSF1 (Compaq Tru64 Unix, really).  The OSF1 support is based on Eric Benson's
33  * patch.
34  *
35  * Eric also suggested an alternate basis for a lock implementation in
36  * his code:
37  * + #elif defined(OSF1)
38  * +    unsigned long GC_allocate_lock = 0;
39  * +    msemaphore GC_allocate_semaphore;
40  * + #  define GC_TRY_LOCK() \
41  * +    ((msem_lock(&GC_allocate_semaphore, MSEM_IF_NOWAIT) == 0) \
42  * +     ? (GC_allocate_lock = 1) \
43  * +     : 0)
44  * + #  define GC_LOCK_TAKEN GC_allocate_lock
45  */
46
47 /*#define DEBUG_THREADS 1*/
48 /*#define GC_ASSERTIONS*/
49
50 # include "private/pthread_support.h"
51
52 # if defined(GC_PTHREADS) && !defined(GC_SOLARIS_THREADS) \
53      && !defined(GC_WIN32_THREADS)
54
55 # if defined(GC_HPUX_THREADS) && !defined(USE_PTHREAD_SPECIFIC) \
56      && !defined(USE_COMPILER_TLS)
57 #   ifdef __GNUC__
58 #     define USE_PTHREAD_SPECIFIC
59       /* Empirically, as of gcc 3.3, USE_COMPILER_TLS doesn't work.     */
60 #   else
61 #     define USE_COMPILER_TLS
62 #   endif
63 # endif
64
65 # if defined USE_HPUX_TLS
66     --> Macro replaced by USE_COMPILER_TLS
67 # endif
68
69 # if (defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) || \
70       defined(GC_DARWIN_THREADS) || defined(GC_AIX_THREADS)) \
71       && !defined(USE_PTHREAD_SPECIFIC)
72 #   define USE_PTHREAD_SPECIFIC
73 # endif
74
75 # if defined(GC_DGUX386_THREADS) && !defined(_POSIX4A_DRAFT10_SOURCE)
76 #   define _POSIX4A_DRAFT10_SOURCE 1
77 # endif
78
79 # if defined(GC_DGUX386_THREADS) && !defined(_USING_POSIX4A_DRAFT10)
80 #   define _USING_POSIX4A_DRAFT10 1
81 # endif
82
83 # ifdef THREAD_LOCAL_ALLOC
84 #   if !defined(USE_PTHREAD_SPECIFIC) && !defined(USE_COMPILER_TLS)
85 #     include "private/specific.h"
86 #   endif
87
88 /* Note that these macros should be used only to get/set the GC_thread pointer.
89  * We need to use both tls and pthread because we use the pthread_create function hook to
90  * free the data for foreign threads. When that doesn't happen, libgc could have old
91  * pthread_t that get reused...
92  */
93 #   if defined(USE_PTHREAD_SPECIFIC)
94 #     define GC_getspecific pthread_getspecific
95 #     define GC_setspecific pthread_setspecific
96 #     define GC_key_create pthread_key_create
97       typedef pthread_key_t GC_key_t;
98 #   endif
99 #   if defined(USE_COMPILER_TLS)
100 #     define GC_getspecific(x) (GC_thread_tls)
101 #     define GC_setspecific(key, v) (GC_thread_tls = (v), pthread_setspecific ((key), (v)))
102 #     define GC_key_create pthread_key_create
103       typedef void * GC_key_t;
104 #   endif
105 # endif
106 # include <stdlib.h>
107 # include <pthread.h>
108 # include <sched.h>
109 # include <time.h>
110 # include <errno.h>
111 # include <unistd.h>
112 # include <sys/mman.h>
113 # include <sys/time.h>
114 # include <sys/types.h>
115 # include <sys/stat.h>
116 # include <fcntl.h>
117 # include <signal.h>
118
119 #if defined(GC_DARWIN_THREADS)
120 # include "private/darwin_semaphore.h"
121 #else
122 # include <semaphore.h>
123 #endif /* !GC_DARWIN_THREADS */
124
125 #if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
126 # include <sys/sysctl.h>
127 #endif /* GC_DARWIN_THREADS */
128
129
130
131 #if defined(GC_DGUX386_THREADS)
132 # include <sys/dg_sys_info.h>
133 # include <sys/_int_psem.h>
134   /* sem_t is an uint in DG/UX */
135   typedef unsigned int  sem_t;
136 #endif /* GC_DGUX386_THREADS */
137
138 #ifndef __GNUC__
139 #   define __inline__
140 #endif
141
142 #ifdef GC_USE_LD_WRAP
143 #   define WRAP_FUNC(f) __wrap_##f
144 #   define REAL_FUNC(f) __real_##f
145 #else
146 #   define WRAP_FUNC(f) GC_##f
147 #   if !defined(GC_DGUX386_THREADS)
148 #     define REAL_FUNC(f) f
149 #   else /* GC_DGUX386_THREADS */
150 #     define REAL_FUNC(f) __d10_##f
151 #   endif /* GC_DGUX386_THREADS */
152 #   undef pthread_create
153 #   if !defined(GC_DARWIN_THREADS)
154 #     undef pthread_sigmask
155 #   endif
156 #   undef pthread_join
157 #   undef pthread_detach
158 #   if defined(GC_OSF1_THREADS) && defined(_PTHREAD_USE_MANGLED_NAMES_) \
159        && !defined(_PTHREAD_USE_PTDNAM_)
160 /* Restore the original mangled names on Tru64 UNIX.  */
161 #     define pthread_create __pthread_create
162 #     define pthread_join __pthread_join
163 #     define pthread_detach __pthread_detach
164 #   endif
165 #endif
166
167 void GC_thr_init();
168
169 static GC_bool parallel_initialized = FALSE;
170
171 void GC_init_parallel();
172
173 # if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
174
175 /* We don't really support thread-local allocation with DBG_HDRS_ALL */
176
177 /* work around a dlopen issue (bug #75390), undefs to avoid warnings with redefinitions */
178 #undef PACKAGE_BUGREPORT
179 #undef PACKAGE_NAME
180 #undef PACKAGE_STRING
181 #undef PACKAGE_TARNAME
182 #undef PACKAGE_VERSION
183 #include "mono/utils/mono-compiler.h"
184
185 static
186 GC_key_t GC_thread_key;
187
188 #ifdef USE_COMPILER_TLS
189 static __thread MONO_TLS_FAST void* GC_thread_tls;
190 #endif
191
192 static GC_bool keys_initialized;
193
194 /* Recover the contents of the freelist array fl into the global one gfl.*/
195 /* Note that the indexing scheme differs, in that gfl has finer size    */
196 /* resolution, even if not all entries are used.                        */
197 /* We hold the allocator lock.                                          */
198 static void return_freelists(ptr_t *fl, ptr_t *gfl)
199 {
200     int i;
201     ptr_t q, *qptr;
202     size_t nwords;
203
204     for (i = 1; i < NFREELISTS; ++i) {
205         nwords = i * (GRANULARITY/sizeof(word));
206         qptr = fl + i;  
207         q = *qptr;
208         if ((word)q >= HBLKSIZE) {
209           if (gfl[nwords] == 0) {
210             gfl[nwords] = q;
211           } else {
212             /* Concatenate: */
213             for (; (word)q >= HBLKSIZE; qptr = &(obj_link(q)), q = *qptr);
214             GC_ASSERT(0 == q);
215             *qptr = gfl[nwords];
216             gfl[nwords] = fl[i];
217           }
218         }
219         /* Clear fl[i], since the thread structure may hang around.     */
220         /* Do it in a way that is likely to trap if we access it.       */
221         fl[i] = (ptr_t)HBLKSIZE;
222     }
223 }
224
225 /* We statically allocate a single "size 0" object. It is linked to     */
226 /* itself, and is thus repeatedly reused for all size 0 allocation      */
227 /* requests.  (Size 0 gcj allocation requests are incorrect, and        */
228 /* we arrange for those to fault asap.)                                 */
229 static ptr_t size_zero_object = (ptr_t)(&size_zero_object);
230
231 void GC_delete_gc_thread(pthread_t id, GC_thread gct);
232
233 void GC_thread_deregister_foreign (void *data)
234 {
235     GC_thread me = (GC_thread)data;
236  /*   GC_fprintf1( "\n\n\n\n --- Deregister %x ---\n\n\n\n\n", me->flags ); */
237     if (me -> flags & FOREIGN_THREAD) {
238         LOCK();
239  /*     GC_fprintf0( "\n\n\n\n --- FOO ---\n\n\n\n\n" ); */
240 #if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
241         GC_destroy_thread_local (me);
242 #endif
243         GC_delete_gc_thread(me->id, me);
244         UNLOCK();
245     }
246 }
247
248 /* Each thread structure must be initialized.   */
249 /* This call must be made from the new thread.  */
250 /* Caller holds allocation lock.                */
251 void GC_init_thread_local(GC_thread p)
252 {
253     int i;
254
255     if (!keys_initialized) {
256         if (0 != GC_key_create(&GC_thread_key, GC_thread_deregister_foreign)) {
257             ABORT("Failed to create key for local allocator");
258         }
259         keys_initialized = TRUE;
260     }
261     if (0 != GC_setspecific(GC_thread_key, p)) {
262         ABORT("Failed to set thread specific allocation pointers");
263     }
264     for (i = 1; i < NFREELISTS; ++i) {
265         p -> ptrfree_freelists[i] = (ptr_t)1;
266         p -> normal_freelists[i] = (ptr_t)1;
267 #       ifdef GC_GCJ_SUPPORT
268           p -> gcj_freelists[i] = (ptr_t)1;
269 #       endif
270     }   
271     /* Set up the size 0 free lists.    */
272     p -> ptrfree_freelists[0] = (ptr_t)(&size_zero_object);
273     p -> normal_freelists[0] = (ptr_t)(&size_zero_object);
274 #   ifdef GC_GCJ_SUPPORT
275         p -> gcj_freelists[0] = (ptr_t)(-1);
276 #   endif
277 }
278
279 #ifdef GC_GCJ_SUPPORT
280   extern ptr_t * GC_gcjobjfreelist;
281 #endif
282
283 /* We hold the allocator lock.  */
284 void GC_destroy_thread_local(GC_thread p)
285 {
286     /* We currently only do this from the thread itself or from */
287     /* the fork handler for a child process.                    */
288 #   ifndef HANDLE_FORK
289       GC_ASSERT(GC_getspecific(GC_thread_key) == (void *)p);
290 #   endif
291     return_freelists(p -> ptrfree_freelists, GC_aobjfreelist);
292     return_freelists(p -> normal_freelists, GC_objfreelist);
293 #   ifdef GC_GCJ_SUPPORT
294         return_freelists(p -> gcj_freelists, GC_gcjobjfreelist);
295 #   endif
296 }
297
298 extern GC_PTR GC_generic_malloc_many();
299
300 GC_PTR GC_local_malloc(size_t bytes)
301 {
302     if (EXPECT(!SMALL_ENOUGH(bytes),0)) {
303         return(GC_malloc(bytes));
304     } else {
305         int index = INDEX_FROM_BYTES(bytes);
306         ptr_t * my_fl;
307         ptr_t my_entry;
308 #       if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
309         GC_key_t k = GC_thread_key;
310 #       endif
311         void * tsd;
312
313 #       if defined(REDIRECT_MALLOC) && !defined(USE_PTHREAD_SPECIFIC)
314             if (EXPECT(0 == k, 0)) {
315                 /* This can happen if we get called when the world is   */
316                 /* being initialized.  Whether we can actually complete */
317                 /* the initialization then is unclear.                  */
318                 GC_init_parallel();
319                 k = GC_thread_key;
320             }
321 #       endif
322         tsd = GC_getspecific(GC_thread_key);
323 #       ifdef GC_ASSERTIONS
324           LOCK();
325           GC_ASSERT(tsd == (void *)GC_lookup_thread(pthread_self()));
326           UNLOCK();
327 #       endif
328         my_fl = ((GC_thread)tsd) -> normal_freelists + index;
329         my_entry = *my_fl;
330         if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
331             ptr_t next = obj_link(my_entry);
332             GC_PTR result = (GC_PTR)my_entry;
333             *my_fl = next;
334             obj_link(my_entry) = 0;
335             PREFETCH_FOR_WRITE(next);
336             return result;
337         } else if ((word)my_entry - 1 < DIRECT_GRANULES) {
338             *my_fl = my_entry + index + 1;
339             return GC_malloc(bytes);
340         } else {
341             GC_generic_malloc_many(BYTES_FROM_INDEX(index), NORMAL, my_fl);
342             if (*my_fl == 0) return GC_oom_fn(bytes);
343             return GC_local_malloc(bytes);
344         }
345     }
346 }
347
348 GC_PTR GC_local_malloc_atomic(size_t bytes)
349 {
350     if (EXPECT(!SMALL_ENOUGH(bytes), 0)) {
351         return(GC_malloc_atomic(bytes));
352     } else {
353         int index = INDEX_FROM_BYTES(bytes);
354         ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
355                         -> ptrfree_freelists + index;
356         ptr_t my_entry = *my_fl;
357     
358         if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
359             GC_PTR result = (GC_PTR)my_entry;
360             *my_fl = obj_link(my_entry);
361             return result;
362         } else if ((word)my_entry - 1 < DIRECT_GRANULES) {
363             *my_fl = my_entry + index + 1;
364         return GC_malloc_atomic(bytes);
365         } else {
366             GC_generic_malloc_many(BYTES_FROM_INDEX(index), PTRFREE, my_fl);
367             /* *my_fl is updated while the collector is excluded;       */
368             /* the free list is always visible to the collector as      */
369             /* such.                                                    */
370             if (*my_fl == 0) return GC_oom_fn(bytes);
371             return GC_local_malloc_atomic(bytes);
372         }
373     }
374 }
375
376 #ifdef GC_GCJ_SUPPORT
377
378 #include "include/gc_gcj.h"
379
380 #ifdef GC_ASSERTIONS
381   extern GC_bool GC_gcj_malloc_initialized;
382 #endif
383
384 extern int GC_gcj_kind;
385
386 GC_PTR GC_local_gcj_malloc(size_t bytes,
387                            void * ptr_to_struct_containing_descr)
388 {
389     GC_ASSERT(GC_gcj_malloc_initialized);
390     if (EXPECT(!SMALL_ENOUGH(bytes), 0)) {
391         return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr);
392     } else {
393         int index = INDEX_FROM_BYTES(bytes);
394         ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
395                         -> gcj_freelists + index;
396         ptr_t my_entry = *my_fl;
397         if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
398             GC_PTR result = (GC_PTR)my_entry;
399             GC_ASSERT(!GC_incremental);
400             /* We assert that any concurrent marker will stop us.       */
401             /* Thus it is impossible for a mark procedure to see the    */
402             /* allocation of the next object, but to see this object    */
403             /* still containing a free list pointer.  Otherwise the     */
404             /* marker might find a random "mark descriptor".            */
405             *(volatile ptr_t *)my_fl = obj_link(my_entry);
406             /* We must update the freelist before we store the pointer. */
407             /* Otherwise a GC at this point would see a corrupted       */
408             /* free list.                                               */
409             /* A memory barrier is probably never needed, since the     */
410             /* action of stopping this thread will cause prior writes   */
411             /* to complete.                                             */
412             GC_ASSERT(((void * volatile *)result)[1] == 0); 
413             *(void * volatile *)result = ptr_to_struct_containing_descr; 
414             return result;
415         } else if ((word)my_entry - 1 < DIRECT_GRANULES) {
416             if (!GC_incremental) *my_fl = my_entry + index + 1;
417                 /* In the incremental case, we always have to take this */
418                 /* path.  Thus we leave the counter alone.              */
419             return GC_gcj_malloc(bytes, ptr_to_struct_containing_descr);
420         } else {
421             GC_generic_malloc_many(BYTES_FROM_INDEX(index), GC_gcj_kind, my_fl);
422             if (*my_fl == 0) return GC_oom_fn(bytes);
423             return GC_local_gcj_malloc(bytes, ptr_to_struct_containing_descr);
424         }
425     }
426 }
427
428 /* Similar to GC_local_gcj_malloc, but the size is in words, and we don't       */
429 /* adjust it.  The size is assumed to be such that it can be    */
430 /* allocated as a small object.                                 */
431 void * GC_local_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
432 {
433         ptr_t * my_fl = ((GC_thread)GC_getspecific(GC_thread_key))
434                 -> gcj_freelists + lw;
435         ptr_t my_entry = *my_fl;
436
437     GC_ASSERT(GC_gcj_malloc_initialized);
438
439         if (EXPECT((word)my_entry >= HBLKSIZE, 1)) {
440             GC_PTR result = (GC_PTR)my_entry;
441             GC_ASSERT(!GC_incremental);
442             /* We assert that any concurrent marker will stop us.       */
443             /* Thus it is impossible for a mark procedure to see the    */
444             /* allocation of the next object, but to see this object    */
445             /* still containing a free list pointer.  Otherwise the     */
446             /* marker might find a random "mark descriptor".            */
447             *(volatile ptr_t *)my_fl = obj_link(my_entry);
448             /* We must update the freelist before we store the pointer. */
449             /* Otherwise a GC at this point would see a corrupted       */
450             /* free list.                                               */
451             /* A memory barrier is probably never needed, since the     */
452             /* action of stopping this thread will cause prior writes   */
453             /* to complete.                                             */
454             GC_ASSERT(((void * volatile *)result)[1] == 0); 
455             *(void * volatile *)result = ptr_to_struct_containing_descr; 
456             return result;
457         } else if ((word)my_entry - 1 < DIRECT_GRANULES) {
458             if (!GC_incremental) *my_fl = my_entry + lw + 1;
459                 /* In the incremental case, we always have to take this */
460                 /* path.  Thus we leave the counter alone.              */
461             return GC_gcj_fast_malloc(lw, ptr_to_struct_containing_descr);
462         } else {
463             GC_generic_malloc_many(BYTES_FROM_INDEX(lw), GC_gcj_kind, my_fl);
464             if (*my_fl == 0) return GC_oom_fn(BYTES_FROM_INDEX(lw));
465             return GC_local_gcj_fast_malloc(lw, ptr_to_struct_containing_descr);
466         }
467 }
468
469 #endif /* GC_GCJ_SUPPORT */
470
471 # else  /* !THREAD_LOCAL_ALLOC  && !DBG_HDRS_ALL */
472
473 #   define GC_destroy_thread_local(t)
474
475 # endif /* !THREAD_LOCAL_ALLOC */
476
477 #if 0
478 /*
479 To make sure that we're using LinuxThreads and not some other thread
480 package, we generate a dummy reference to `pthread_kill_other_threads_np'
481 (was `__pthread_initial_thread_bos' but that disappeared),
482 which is a symbol defined in LinuxThreads, but (hopefully) not in other
483 thread packages.
484
485 We no longer do this, since this code is now portable enough that it might
486 actually work for something else.
487 */
488 void (*dummy_var_to_force_linux_threads)() = pthread_kill_other_threads_np;
489 #endif /* 0 */
490
491 long GC_nprocs = 1;     /* Number of processors.  We may not have       */
492                         /* access to all of them, but this is as good   */
493                         /* a guess as any ...                           */
494
495 #ifdef PARALLEL_MARK
496
497 # ifndef MAX_MARKERS
498 #   define MAX_MARKERS 16
499 # endif
500
501 static ptr_t marker_sp[MAX_MARKERS] = {0};
502
503 void * GC_mark_thread(void * id)
504 {
505   word my_mark_no = 0;
506
507   marker_sp[(word)id] = GC_approx_sp();
508   for (;; ++my_mark_no) {
509     /* GC_mark_no is passed only to allow GC_help_marker to terminate   */
510     /* promptly.  This is important if it were called from the signal   */
511     /* handler or from the GC lock acquisition code.  Under Linux, it's */
512     /* not safe to call it from a signal handler, since it uses mutexes */
513     /* and condition variables.  Since it is called only here, the      */
514     /* argument is unnecessary.                                         */
515     if (my_mark_no < GC_mark_no || my_mark_no > GC_mark_no + 2) {
516         /* resynchronize if we get far off, e.g. because GC_mark_no     */
517         /* wrapped.                                                     */
518         my_mark_no = GC_mark_no;
519     }
520 #   ifdef DEBUG_THREADS
521         GC_printf1("Starting mark helper for mark number %ld\n", my_mark_no);
522 #   endif
523     GC_help_marker(my_mark_no);
524   }
525 }
526
527 extern long GC_markers;         /* Number of mark threads we would      */
528                                 /* like to have.  Includes the          */
529                                 /* initiating thread.                   */
530
531 pthread_t GC_mark_threads[MAX_MARKERS];
532
533 #define PTHREAD_CREATE REAL_FUNC(pthread_create)
534
535 static void start_mark_threads()
536 {
537     unsigned i;
538     pthread_attr_t attr;
539
540     if (GC_markers > MAX_MARKERS) {
541         WARN("Limiting number of mark threads\n", 0);
542         GC_markers = MAX_MARKERS;
543     }
544     if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
545         
546     if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
547         ABORT("pthread_attr_setdetachstate failed");
548
549 #   if defined(HPUX) || defined(GC_DGUX386_THREADS)
550       /* Default stack size is usually too small: fix it. */
551       /* Otherwise marker threads or GC may run out of    */
552       /* space.                                           */
553 #     define MIN_STACK_SIZE (8*HBLKSIZE*sizeof(word))
554       {
555         size_t old_size;
556         int code;
557
558         if (pthread_attr_getstacksize(&attr, &old_size) != 0)
559           ABORT("pthread_attr_getstacksize failed\n");
560         if (old_size < MIN_STACK_SIZE) {
561           if (pthread_attr_setstacksize(&attr, MIN_STACK_SIZE) != 0)
562                   ABORT("pthread_attr_setstacksize failed\n");
563         }
564       }
565 #   endif /* HPUX || GC_DGUX386_THREADS */
566 #   ifdef CONDPRINT
567       if (GC_print_stats) {
568         GC_printf1("Starting %ld marker threads\n", GC_markers - 1);
569       }
570 #   endif
571     for (i = 0; i < GC_markers - 1; ++i) {
572       if (0 != PTHREAD_CREATE(GC_mark_threads + i, &attr,
573                               GC_mark_thread, (void *)(word)i)) {
574         WARN("Marker thread creation failed, errno = %ld.\n", errno);
575       }
576     }
577 }
578
579 #else  /* !PARALLEL_MARK */
580
581 static __inline__ void start_mark_threads()
582 {
583 }
584
585 #endif /* !PARALLEL_MARK */
586
587 GC_bool GC_thr_initialized = FALSE;
588
589 volatile GC_thread GC_threads[THREAD_TABLE_SZ];
590
591 /* 
592  * gcc-3.3.6 miscompiles the &GC_thread_key+sizeof(&GC_thread_key) expression so
593  * put it into a separate function.
594  */
595 #   if defined(__GNUC__) && defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
596 static __attribute__((noinline)) unsigned char* get_gc_thread_key_addr GC_PROTO((void))
597 {
598         return (unsigned char*)&GC_thread_key;
599 }
600
601 void GC_push_thread_structures GC_PROTO((void))
602 {
603     GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
604 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
605       GC_push_all((ptr_t)get_gc_thread_key_addr(),
606           (ptr_t)(get_gc_thread_key_addr())+sizeof(&GC_thread_key));
607 #   endif
608 }
609
610 #else
611
612 void GC_push_thread_structures GC_PROTO((void))
613 {
614     GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
615 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
616       GC_push_all((ptr_t)(&GC_thread_key),
617           (ptr_t)(&GC_thread_key)+sizeof(&GC_thread_key));
618 #   endif
619 }
620
621 #endif
622
623 #ifdef THREAD_LOCAL_ALLOC
624 /* We must explicitly mark ptrfree and gcj free lists, since the free   */
625 /* list links wouldn't otherwise be found.  We also set them in the     */
626 /* normal free lists, since that involves touching less memory than if  */
627 /* we scanned them normally.                                            */
628 void GC_mark_thread_local_free_lists(void)
629 {
630     int i, j;
631     GC_thread p;
632     ptr_t q;
633     
634     for (i = 0; i < THREAD_TABLE_SZ; ++i) {
635       for (p = GC_threads[i]; 0 != p; p = p -> next) {
636         for (j = 1; j < NFREELISTS; ++j) {
637           q = p -> ptrfree_freelists[j];
638           if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
639           q = p -> normal_freelists[j];
640           if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
641 #         ifdef GC_GCJ_SUPPORT
642             q = p -> gcj_freelists[j];
643             if ((word)q > HBLKSIZE) GC_set_fl_marks(q);
644 #         endif /* GC_GCJ_SUPPORT */
645         }
646       }
647     }
648 }
649 #endif /* THREAD_LOCAL_ALLOC */
650
651 static struct GC_Thread_Rep first_thread;
652
653 /* Add a thread to GC_threads.  We assume it wasn't already there.      */
654 /* Caller holds allocation lock.                                        */
655 GC_thread GC_new_thread(pthread_t id)
656 {
657     int hv = ((word)id) % THREAD_TABLE_SZ;
658     GC_thread result;
659     static GC_bool first_thread_used = FALSE;
660     
661     if (!first_thread_used) {
662         result = &first_thread;
663         first_thread_used = TRUE;
664     } else {
665         result = (struct GC_Thread_Rep *)
666                  GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
667     }
668     if (result == 0) return(0);
669     result -> id = id;
670     result -> next = GC_threads[hv];
671     GC_threads[hv] = result;
672     GC_ASSERT(result -> flags == 0 && result -> thread_blocked == 0);
673     return(result);
674 }
675
676 /* Delete a thread from GC_threads.  We assume it is there.     */
677 /* (The code intentionally traps if it wasn't.)                 */
678 /* Caller holds allocation lock.                                */
679 void GC_delete_thread(pthread_t id)
680 {
681     int hv = ((word)id) % THREAD_TABLE_SZ;
682     register GC_thread p = GC_threads[hv];
683     register GC_thread prev = 0;
684     
685     while (!pthread_equal(p -> id, id)) {
686         prev = p;
687         p = p -> next;
688     }
689     if (prev == 0) {
690         GC_threads[hv] = p -> next;
691     } else {
692         prev -> next = p -> next;
693     }
694     GC_INTERNAL_FREE(p);
695 }
696
697 /* If a thread has been joined, but we have not yet             */
698 /* been notified, then there may be more than one thread        */
699 /* in the table with the same pthread id.                       */
700 /* This is OK, but we need a way to delete a specific one.      */
701 void GC_delete_gc_thread(pthread_t id, GC_thread gc_id)
702 {
703     int hv = ((word)id) % THREAD_TABLE_SZ;
704     register GC_thread p = GC_threads[hv];
705     register GC_thread prev = 0;
706
707     while (p != gc_id) {
708         prev = p;
709         p = p -> next;
710     }
711     if (prev == 0) {
712         GC_threads[hv] = p -> next;
713     } else {
714         prev -> next = p -> next;
715     }
716     GC_INTERNAL_FREE(p);
717 }
718
719 /* Return a GC_thread corresponding to a given pthread_t.       */
720 /* Returns 0 if it's not there.                                 */
721 /* Caller holds  allocation lock or otherwise inhibits          */
722 /* updates.                                                     */
723 /* If there is more than one thread with the given id we        */
724 /* return the most recent one.                                  */
725 GC_thread GC_lookup_thread(pthread_t id)
726 {
727     int hv = ((word)id) % THREAD_TABLE_SZ;
728     register GC_thread p = GC_threads[hv];
729     
730     while (p != 0 && !pthread_equal(p -> id, id)) p = p -> next;
731     return(p);
732 }
733
734 int GC_thread_is_registered (void)
735 {
736         void *ptr;
737
738         LOCK();
739         ptr = (void *)GC_lookup_thread(pthread_self());
740         UNLOCK();
741
742         return ptr ? 1 : 0;
743 }
744
745 #ifdef HANDLE_FORK
746 /* Remove all entries from the GC_threads table, except the     */
747 /* one for the current thread.  We need to do this in the child */
748 /* process after a fork(), since only the current thread        */
749 /* survives in the child.                                       */
750 void GC_remove_all_threads_but_me(void)
751 {
752     pthread_t self = pthread_self();
753     int hv;
754     GC_thread p, next, me;
755
756     for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
757       me = 0;
758       for (p = GC_threads[hv]; 0 != p; p = next) {
759         next = p -> next;
760         if (p -> id == self) {
761           me = p;
762           p -> next = 0;
763         } else {
764 #         ifdef THREAD_LOCAL_ALLOC
765             if (!(p -> flags & FINISHED)) {
766               GC_destroy_thread_local(p);
767             }
768 #         endif /* THREAD_LOCAL_ALLOC */
769           if (p != &first_thread) GC_INTERNAL_FREE(p);
770         }
771       }
772       GC_threads[hv] = me;
773     }
774 }
775 #endif /* HANDLE_FORK */
776
777 #ifdef USE_PROC_FOR_LIBRARIES
778 int GC_segment_is_thread_stack(ptr_t lo, ptr_t hi)
779 {
780     int i;
781     GC_thread p;
782     
783 #   ifdef PARALLEL_MARK
784       for (i = 0; i < GC_markers; ++i) {
785         if (marker_sp[i] > lo & marker_sp[i] < hi) return 1;
786       }
787 #   endif
788     for (i = 0; i < THREAD_TABLE_SZ; i++) {
789       for (p = GC_threads[i]; p != 0; p = p -> next) {
790         if (0 != p -> stack_end) {
791 #         ifdef STACK_GROWS_UP
792             if (p -> stack_end >= lo && p -> stack_end < hi) return 1;
793 #         else /* STACK_GROWS_DOWN */
794             if (p -> stack_end > lo && p -> stack_end <= hi) return 1;
795 #         endif
796         }
797       }
798     }
799     return 0;
800 }
801 #endif /* USE_PROC_FOR_LIBRARIES */
802
803 #ifdef GC_LINUX_THREADS
804 /* Return the number of processors, or i<= 0 if it can't be determined. */
805 int GC_get_nprocs()
806 {
807     /* Should be "return sysconf(_SC_NPROCESSORS_ONLN);" but that       */
808     /* appears to be buggy in many cases.                               */
809     /* We look for lines "cpu<n>" in /proc/stat.                        */
810 #   define STAT_BUF_SIZE 4096
811 #   define STAT_READ read
812         /* If read is wrapped, this may need to be redefined to call    */
813         /* the real one.                                                */
814     char stat_buf[STAT_BUF_SIZE];
815     int f;
816     word result = 1;
817         /* Some old kernels only have a single "cpu nnnn ..."   */
818         /* entry in /proc/stat.  We identify those as           */
819         /* uniprocessors.                                       */
820     size_t i, len = 0;
821
822     f = open("/proc/stat", O_RDONLY);
823     if (f < 0 || (len = STAT_READ(f, stat_buf, STAT_BUF_SIZE)) < 100) {
824         WARN("Couldn't read /proc/stat\n", 0);
825         return -1;
826     }
827     for (i = 0; i < len - 100; ++i) {
828         if (stat_buf[i] == '\n' && stat_buf[i+1] == 'c'
829             && stat_buf[i+2] == 'p' && stat_buf[i+3] == 'u') {
830             int cpu_no = atoi(stat_buf + i + 4);
831             if (cpu_no >= result) result = cpu_no + 1;
832         }
833     }
834     close(f);
835     return result;
836 }
837 #endif /* GC_LINUX_THREADS */
838
839 /* We hold the GC lock.  Wait until an in-progress GC has finished.     */
840 /* Repeatedly RELEASES GC LOCK in order to wait.                        */
841 /* If wait_for_all is true, then we exit with the GC lock held and no   */
842 /* collection in progress; otherwise we just wait for the current GC    */
843 /* to finish.                                                           */
844 extern GC_bool GC_collection_in_progress();
845 void GC_wait_for_gc_completion(GC_bool wait_for_all)
846 {
847     if (GC_incremental && GC_collection_in_progress()) {
848         int old_gc_no = GC_gc_no;
849
850         /* Make sure that no part of our stack is still on the mark stack, */
851         /* since it's about to be unmapped.                                */
852         while (GC_incremental && GC_collection_in_progress()
853                && (wait_for_all || old_gc_no == GC_gc_no)) {
854             ENTER_GC();
855             GC_in_thread_creation = TRUE;
856             GC_collect_a_little_inner(1);
857             GC_in_thread_creation = FALSE;
858             EXIT_GC();
859             UNLOCK();
860             sched_yield();
861             LOCK();
862         }
863     }
864 }
865
866 #ifdef HANDLE_FORK
867 /* Procedures called before and after a fork.  The goal here is to make */
868 /* it safe to call GC_malloc() in a forked child.  It's unclear that is */
869 /* attainable, since the single UNIX spec seems to imply that one       */
870 /* should only call async-signal-safe functions, and we probably can't  */
871 /* quite guarantee that.  But we give it our best shot.  (That same     */
872 /* spec also implies that it's not safe to call the system malloc       */
873 /* between fork() and exec().  Thus we're doing no worse than it.       */
874
875 /* Called before a fork()               */
876 void GC_fork_prepare_proc(void)
877 {
878     /* Acquire all relevant locks, so that after releasing the locks    */
879     /* the child will see a consistent state in which monitor           */
880     /* invariants hold.  Unfortunately, we can't acquire libc locks     */
881     /* we might need, and there seems to be no guarantee that libc      */
882     /* must install a suitable fork handler.                            */
883     /* Wait for an ongoing GC to finish, since we can't finish it in    */
884     /* the (one remaining thread in) the child.                         */
885       LOCK();
886 #     if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
887         GC_wait_for_reclaim();
888 #     endif
889       GC_wait_for_gc_completion(TRUE);
890 #     if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
891         GC_acquire_mark_lock();
892 #     endif
893 }
894
895 /* Called in parent after a fork()      */
896 void GC_fork_parent_proc(void)
897 {
898 #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
899       GC_release_mark_lock();
900 #   endif
901     UNLOCK();
902 }
903
904 /* Called in child after a fork()       */
905 void GC_fork_child_proc(void)
906 {
907     /* Clean up the thread table, so that just our thread is left. */
908 #   if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
909       GC_release_mark_lock();
910 #   endif
911     GC_remove_all_threads_but_me();
912 #   ifdef PARALLEL_MARK
913       /* Turn off parallel marking in the child, since we are probably  */
914       /* just going to exec, and we would have to restart mark threads. */
915         GC_markers = 1;
916         GC_parallel = FALSE;
917 #   endif /* PARALLEL_MARK */
918     UNLOCK();
919 }
920 #endif /* HANDLE_FORK */
921
922 #if defined(GC_DGUX386_THREADS)
923 /* Return the number of processors, or i<= 0 if it can't be determined. */
924 int GC_get_nprocs()
925 {
926     /* <takis@XFree86.Org> */
927     int numCpus;
928     struct dg_sys_info_pm_info pm_sysinfo;
929     int status =0;
930
931     status = dg_sys_info((long int *) &pm_sysinfo,
932         DG_SYS_INFO_PM_INFO_TYPE, DG_SYS_INFO_PM_CURRENT_VERSION);
933     if (status < 0)
934        /* set -1 for error */
935        numCpus = -1;
936     else
937       /* Active CPUs */
938       numCpus = pm_sysinfo.idle_vp_count;
939
940 #  ifdef DEBUG_THREADS
941     GC_printf1("Number of active CPUs in this system: %d\n", numCpus);
942 #  endif
943     return(numCpus);
944 }
945 #endif /* GC_DGUX386_THREADS */
946
947 /* We hold the allocation lock. */
948 void GC_thr_init()
949 {
950 #   ifndef GC_DARWIN_THREADS
951       int dummy;
952 #   endif
953     GC_thread t;
954
955     if (GC_thr_initialized) return;
956     GC_thr_initialized = TRUE;
957     
958 #   ifdef HANDLE_FORK
959       /* Prepare for a possible fork.   */
960         pthread_atfork(GC_fork_prepare_proc, GC_fork_parent_proc,
961                        GC_fork_child_proc);
962 #   endif /* HANDLE_FORK */
963     /* Add the initial thread, so we can stop it.       */
964       t = GC_new_thread(pthread_self());
965 #     ifdef GC_DARWIN_THREADS
966          t -> stop_info.mach_thread = mach_thread_self();
967 #     else
968          t -> stop_info.stack_ptr = (ptr_t)(&dummy);
969 #     endif
970       t -> flags = DETACHED | MAIN_THREAD;
971
972     GC_stop_init();
973
974     /* Set GC_nprocs.  */
975       {
976         char * nprocs_string = GETENV("GC_NPROCS");
977         GC_nprocs = -1;
978         if (nprocs_string != NULL) GC_nprocs = atoi(nprocs_string);
979       }
980       if (GC_nprocs <= 0) {
981 #       if defined(GC_HPUX_THREADS)
982           GC_nprocs = pthread_num_processors_np();
983 #       endif
984 #       if defined(GC_OSF1_THREADS) || defined(GC_AIX_THREADS)
985           GC_nprocs = sysconf(_SC_NPROCESSORS_ONLN);
986           if (GC_nprocs <= 0) GC_nprocs = 1;
987 #       endif
988 #       if defined(GC_IRIX_THREADS)
989           GC_nprocs = sysconf(_SC_NPROC_ONLN);
990           if (GC_nprocs <= 0) GC_nprocs = 1;
991 #       endif
992 #       if defined(GC_DARWIN_THREADS) || defined(GC_FREEBSD_THREADS)
993           int ncpus = 1;
994           size_t len = sizeof(ncpus);
995           sysctl((int[2]) {CTL_HW, HW_NCPU}, 2, &ncpus, &len, NULL, 0);
996           GC_nprocs = ncpus;
997 #       endif
998 #       if defined(GC_LINUX_THREADS) || defined(GC_DGUX386_THREADS)
999           GC_nprocs = GC_get_nprocs();
1000 #       endif
1001       }
1002       if (GC_nprocs <= 0) {
1003         WARN("GC_get_nprocs() returned %ld\n", GC_nprocs);
1004         GC_nprocs = 2;
1005 #       ifdef PARALLEL_MARK
1006           GC_markers = 1;
1007 #       endif
1008       } else {
1009 #       ifdef PARALLEL_MARK
1010           {
1011             char * markers_string = GETENV("GC_MARKERS");
1012             if (markers_string != NULL) {
1013               GC_markers = atoi(markers_string);
1014             } else {
1015               GC_markers = GC_nprocs;
1016             }
1017           }
1018 #       endif
1019       }
1020 #   ifdef PARALLEL_MARK
1021 #     ifdef CONDPRINT
1022         if (GC_print_stats) {
1023           GC_printf2("Number of processors = %ld, "
1024                  "number of marker threads = %ld\n", GC_nprocs, GC_markers);
1025         }
1026 #     endif
1027       if (GC_markers == 1) {
1028         GC_parallel = FALSE;
1029 #       ifdef CONDPRINT
1030           if (GC_print_stats) {
1031             GC_printf0("Single marker thread, turning off parallel marking\n");
1032           }
1033 #       endif
1034       } else {
1035         GC_parallel = TRUE;
1036         /* Disable true incremental collection, but generational is OK. */
1037         GC_time_limit = GC_TIME_UNLIMITED;
1038       }
1039       /* If we are using a parallel marker, actually start helper threads.  */
1040         if (GC_parallel) start_mark_threads();
1041 #   endif
1042 }
1043
1044
1045 /* Perform all initializations, including those that    */
1046 /* may require allocation.                              */
1047 /* Called without allocation lock.                      */
1048 /* Must be called before a second thread is created.    */
1049 /* Called without allocation lock.                      */
1050 void GC_init_parallel()
1051 {
1052     if (parallel_initialized) return;
1053     parallel_initialized = TRUE;
1054
1055     /* GC_init() calls us back, so set flag first.      */
1056     if (!GC_is_initialized) GC_init();
1057     /* Initialize thread local free lists if used.      */
1058 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
1059       LOCK();
1060       GC_init_thread_local(GC_lookup_thread(pthread_self()));
1061       UNLOCK();
1062 #   endif
1063 }
1064
1065
1066 #if !defined(GC_DARWIN_THREADS)
1067 int WRAP_FUNC(pthread_sigmask)(int how, const sigset_t *set, sigset_t *oset)
1068 {
1069     sigset_t fudged_set;
1070     
1071     if (set != NULL && (how == SIG_BLOCK || how == SIG_SETMASK)) {
1072         fudged_set = *set;
1073         sigdelset(&fudged_set, SIG_SUSPEND);
1074         set = &fudged_set;
1075     }
1076     return(REAL_FUNC(pthread_sigmask)(how, set, oset));
1077 }
1078 #endif /* !GC_DARWIN_THREADS */
1079
1080 /* Wrappers for functions that are likely to block for an appreciable   */
1081 /* length of time.  Must be called in pairs, if at all.                 */
1082 /* Nothing much beyond the system call itself should be executed        */
1083 /* between these.                                                       */
1084
1085 void GC_start_blocking(void) {
1086 #   define SP_SLOP 128
1087     GC_thread me;
1088     LOCK();
1089     me = GC_lookup_thread(pthread_self());
1090     GC_ASSERT(!(me -> thread_blocked));
1091 #   ifdef SPARC
1092         me -> stop_info.stack_ptr = (ptr_t)GC_save_regs_in_stack();
1093 #   else
1094 #   ifndef GC_DARWIN_THREADS
1095         me -> stop_info.stack_ptr = (ptr_t)GC_approx_sp();
1096 #   endif
1097 #   endif
1098 #   ifdef IA64
1099         me -> backing_store_ptr = (ptr_t)GC_save_regs_in_stack() + SP_SLOP;
1100 #   endif
1101     /* Add some slop to the stack pointer, since the wrapped call may   */
1102     /* end up pushing more callee-save registers.                       */
1103 #   ifndef GC_DARWIN_THREADS
1104 #   ifdef STACK_GROWS_UP
1105         me -> stop_info.stack_ptr += SP_SLOP;
1106 #   else
1107         me -> stop_info.stack_ptr -= SP_SLOP;
1108 #   endif
1109 #   endif
1110     me -> thread_blocked = TRUE;
1111     UNLOCK();
1112 }
1113
1114 void GC_end_blocking(void) {
1115     GC_thread me;
1116     LOCK();   /* This will block if the world is stopped.       */
1117     me = GC_lookup_thread(pthread_self());
1118     GC_ASSERT(me -> thread_blocked);
1119     me -> thread_blocked = FALSE;
1120     UNLOCK();
1121 }
1122     
1123 #if defined(GC_DGUX386_THREADS)
1124 #define __d10_sleep sleep
1125 #endif /* GC_DGUX386_THREADS */
1126
1127 /* A wrapper for the standard C sleep function  */
1128 int WRAP_FUNC(sleep) (unsigned int seconds)
1129 {
1130     int result;
1131
1132     GC_start_blocking();
1133     result = REAL_FUNC(sleep)(seconds);
1134     GC_end_blocking();
1135     return result;
1136 }
1137
1138 struct start_info {
1139     void *(*start_routine)(void *);
1140     void *arg;
1141     word flags;
1142     sem_t registered;           /* 1 ==> in our thread table, but       */
1143                                 /* parent hasn't yet noticed.           */
1144 };
1145
1146 /* Called at thread exit.                               */
1147 /* Never called for main thread.  That's OK, since it   */
1148 /* results in at most a tiny one-time leak.  And        */
1149 /* linuxthreads doesn't reclaim the main threads        */
1150 /* resources or id anyway.                              */
1151 void GC_thread_exit_proc(void *arg)
1152 {
1153     GC_thread me;
1154
1155     LOCK();
1156     me = GC_lookup_thread(pthread_self());
1157     GC_destroy_thread_local(me);
1158     if (me -> flags & DETACHED) {
1159         GC_delete_thread(pthread_self());
1160     } else {
1161         me -> flags |= FINISHED;
1162     }
1163 #   if defined(THREAD_LOCAL_ALLOC) && !defined(USE_PTHREAD_SPECIFIC) \
1164        && !defined(USE_COMPILER_TLS) && !defined(DBG_HDRS_ALL)
1165       GC_remove_specific(GC_thread_key);
1166 #   endif
1167     /* The following may run the GC from "nonexistent" thread.  */
1168     GC_wait_for_gc_completion(FALSE);
1169     UNLOCK();
1170 }
1171
1172 int WRAP_FUNC(pthread_join)(pthread_t thread, void **retval)
1173 {
1174     int result;
1175     GC_thread thread_gc_id;
1176     
1177     LOCK();
1178     thread_gc_id = GC_lookup_thread(thread);
1179     /* This is guaranteed to be the intended one, since the thread id   */
1180     /* cant have been recycled by pthreads.                             */
1181     UNLOCK();
1182     result = REAL_FUNC(pthread_join)(thread, retval);
1183 # if defined (GC_FREEBSD_THREADS)
1184     /* On FreeBSD, the wrapped pthread_join() sometimes returns (what
1185        appears to be) a spurious EINTR which caused the test and real code
1186        to gratuitously fail.  Having looked at system pthread library source
1187        code, I see how this return code may be generated.  In one path of
1188        code, pthread_join() just returns the errno setting of the thread
1189        being joined.  This does not match the POSIX specification or the
1190        local man pages thus I have taken the liberty to catch this one
1191        spurious return value properly conditionalized on GC_FREEBSD_THREADS. */
1192     if (result == EINTR) result = 0;
1193 # endif
1194     if (result == 0) {
1195         LOCK();
1196         /* Here the pthread thread id may have been recycled. */
1197         GC_delete_gc_thread(thread, thread_gc_id);
1198         UNLOCK();
1199     }
1200     return result;
1201 }
1202
1203 int
1204 WRAP_FUNC(pthread_detach)(pthread_t thread)
1205 {
1206     int result;
1207     GC_thread thread_gc_id;
1208     
1209     LOCK();
1210     thread_gc_id = GC_lookup_thread(thread);
1211     UNLOCK();
1212     result = REAL_FUNC(pthread_detach)(thread);
1213     if (result == 0) {
1214       LOCK();
1215       thread_gc_id -> flags |= DETACHED;
1216       /* Here the pthread thread id may have been recycled. */
1217       if (thread_gc_id -> flags & FINISHED) {
1218         GC_delete_gc_thread(thread, thread_gc_id);
1219       }
1220       UNLOCK();
1221     }
1222     return result;
1223 }
1224
1225 GC_bool GC_in_thread_creation = FALSE;
1226
1227 typedef void *(*ThreadStartFn)(void *);
1228 void * GC_start_routine_head(void * arg, void *base_addr,
1229                              ThreadStartFn *start, void **start_arg )
1230 {
1231     struct start_info * si = arg;
1232     void * result;
1233     GC_thread me;
1234     pthread_t my_pthread;
1235
1236     my_pthread = pthread_self();
1237 #   ifdef DEBUG_THREADS
1238         GC_printf1("Starting thread 0x%lx\n", my_pthread);
1239         GC_printf1("pid = %ld\n", (long) getpid());
1240         GC_printf1("sp = 0x%lx\n", (long) &arg);
1241 #   endif
1242     LOCK();
1243     GC_in_thread_creation = TRUE;
1244     me = GC_new_thread(my_pthread);
1245     GC_in_thread_creation = FALSE;
1246 #ifdef GC_DARWIN_THREADS
1247     me -> stop_info.mach_thread = mach_thread_self();
1248 #else
1249     me -> stop_info.stack_ptr = 0;
1250 #endif
1251     me -> flags = si -> flags;
1252     /* me -> stack_end = GC_linux_stack_base(); -- currently (11/99)    */
1253     /* doesn't work because the stack base in /proc/self/stat is the    */
1254     /* one for the main thread.  There is a strong argument that that's */
1255     /* a kernel bug, but a pervasive one.                               */
1256 #   ifdef STACK_GROWS_DOWN
1257       me -> stack_end = (ptr_t)(((word)(base_addr) + (GC_page_size - 1))
1258                                 & ~(GC_page_size - 1));
1259 #         ifndef GC_DARWIN_THREADS
1260         me -> stop_info.stack_ptr = me -> stack_end - 0x10;
1261 #         endif
1262         /* Needs to be plausible, since an asynchronous stack mark      */
1263         /* should not crash.                                            */
1264 #   else
1265       me -> stack_end = (ptr_t)((word)(base_addr) & ~(GC_page_size - 1));
1266       me -> stop_info.stack_ptr = me -> stack_end + 0x10;
1267 #   endif
1268     /* This is dubious, since we may be more than a page into the stack, */
1269     /* and hence skip some of it, though it's not clear that matters.    */
1270 #   ifdef IA64
1271       me -> backing_store_end = (ptr_t)
1272                         (GC_save_regs_in_stack() & ~(GC_page_size - 1));
1273       /* This is also < 100% convincing.  We should also read this      */
1274       /* from /proc, but the hook to do so isn't there yet.             */
1275 #   endif /* IA64 */
1276     UNLOCK();
1277
1278     if (start) *start = si -> start_routine;
1279     if (start_arg) *start_arg = si -> arg;
1280
1281     sem_post(&(si -> registered));      /* Last action on si.   */
1282                                         /* OK to deallocate.    */
1283 #   if defined(THREAD_LOCAL_ALLOC) && !defined(DBG_HDRS_ALL)
1284         LOCK();
1285         GC_init_thread_local(me);
1286         UNLOCK();
1287 #   endif
1288
1289     return me;
1290 }
1291
1292 int GC_thread_register_foreign (void *base_addr)
1293 {
1294     struct start_info si = { 0, }; /* stacked for legibility & locking */
1295     GC_thread me;
1296
1297 #   ifdef DEBUG_THREADS
1298         GC_printf1( "GC_thread_register_foreign %p\n", &si );
1299 #   endif
1300
1301     si.flags = FOREIGN_THREAD;
1302
1303     if (!parallel_initialized) GC_init_parallel();
1304     LOCK();
1305     if (!GC_thr_initialized) GC_thr_init();
1306
1307     UNLOCK();
1308
1309     me = GC_start_routine_head(&si, base_addr, NULL, NULL);
1310
1311     return me != NULL;
1312 }
1313
1314 void * GC_start_routine(void * arg)
1315 {
1316     int dummy;
1317     struct start_info * si = arg;
1318     void * result;
1319     GC_thread me;
1320     ThreadStartFn start;
1321     void *start_arg;
1322
1323     me = GC_start_routine_head (arg, &dummy, &start, &start_arg);
1324
1325     pthread_cleanup_push(GC_thread_exit_proc, 0);
1326 #   ifdef DEBUG_THREADS
1327         GC_printf1("start_routine = 0x%lx\n", start);
1328 #   endif
1329     result = (*start)(start_arg);
1330 #if DEBUG_THREADS
1331         GC_printf1("Finishing thread 0x%x\n", pthread_self());
1332 #endif
1333     me -> status = result;
1334     pthread_cleanup_pop(1);
1335     /* Cleanup acquires lock, ensuring that we can't exit               */
1336     /* while a collection that thinks we're alive is trying to stop     */
1337     /* us.                                                              */
1338     return(result);
1339 }
1340
1341 int
1342 WRAP_FUNC(pthread_create)(pthread_t *new_thread,
1343                   const pthread_attr_t *attr,
1344                   void *(*start_routine)(void *), void *arg)
1345 {
1346     int result;
1347     int detachstate;
1348     word my_flags = 0;
1349     struct start_info * si; 
1350         /* This is otherwise saved only in an area mmapped by the thread */
1351         /* library, which isn't visible to the collector.                */
1352  
1353     /* We resist the temptation to muck with the stack size here,       */
1354     /* even if the default is unreasonably small.  That's the client's  */
1355     /* responsibility.                                                  */
1356
1357     LOCK();
1358     si = (struct start_info *)GC_INTERNAL_MALLOC(sizeof(struct start_info),
1359                                                  NORMAL);
1360     UNLOCK();
1361     if (!parallel_initialized) GC_init_parallel();
1362     if (0 == si) return(ENOMEM);
1363     sem_init(&(si -> registered), 0, 0);
1364     si -> start_routine = start_routine;
1365     si -> arg = arg;
1366     LOCK();
1367     if (!GC_thr_initialized) GC_thr_init();
1368 #   ifdef GC_ASSERTIONS
1369       {
1370         size_t stack_size;
1371         if (NULL == attr) {
1372            pthread_attr_t my_attr;
1373            pthread_attr_init(&my_attr);
1374            pthread_attr_getstacksize(&my_attr, &stack_size);
1375         } else {
1376            pthread_attr_getstacksize(attr, &stack_size);
1377         }
1378 #       ifdef PARALLEL_MARK
1379           GC_ASSERT(stack_size >= (8*HBLKSIZE*sizeof(word)));
1380 #       else
1381           /* FreeBSD-5.3/Alpha: default pthread stack is 64K,   */
1382           /* HBLKSIZE=8192, sizeof(word)=8                      */
1383           GC_ASSERT(stack_size >= 65536);
1384 #       endif
1385         /* Our threads may need to do some work for the GC.     */
1386         /* Ridiculously small threads won't work, and they      */
1387         /* probably wouldn't work anyway.                       */
1388       }
1389 #   endif
1390     if (NULL == attr) {
1391         detachstate = PTHREAD_CREATE_JOINABLE;
1392     } else { 
1393         pthread_attr_getdetachstate(attr, &detachstate);
1394     }
1395     if (PTHREAD_CREATE_DETACHED == detachstate) my_flags |= DETACHED;
1396     si -> flags = my_flags;
1397     UNLOCK();
1398 #   ifdef DEBUG_THREADS
1399         GC_printf1("About to start new thread from thread 0x%X\n",
1400                    pthread_self());
1401 #   endif
1402
1403     result = REAL_FUNC(pthread_create)(new_thread, attr, GC_start_routine, si);
1404
1405 #   ifdef DEBUG_THREADS
1406         GC_printf1("Started thread 0x%X\n", *new_thread);
1407 #   endif
1408     /* Wait until child has been added to the thread table.             */
1409     /* This also ensures that we hold onto si until the child is done   */
1410     /* with it.  Thus it doesn't matter whether it is otherwise         */
1411     /* visible to the collector.                                        */
1412     if (0 == result) {
1413         while (0 != sem_wait(&(si -> registered))) {
1414             if (EINTR != errno) ABORT("sem_wait failed");
1415         }
1416     }
1417     sem_destroy(&(si -> registered));
1418     LOCK();
1419     GC_INTERNAL_FREE(si);
1420     UNLOCK();
1421
1422     return(result);
1423 }
1424
1425 #ifdef GENERIC_COMPARE_AND_SWAP
1426   pthread_mutex_t GC_compare_and_swap_lock = PTHREAD_MUTEX_INITIALIZER;
1427
1428   GC_bool GC_compare_and_exchange(volatile GC_word *addr,
1429                                   GC_word old, GC_word new_val)
1430   {
1431     GC_bool result;
1432     pthread_mutex_lock(&GC_compare_and_swap_lock);
1433     if (*addr == old) {
1434       *addr = new_val;
1435       result = TRUE;
1436     } else {
1437       result = FALSE;
1438     }
1439     pthread_mutex_unlock(&GC_compare_and_swap_lock);
1440     return result;
1441   }
1442   
1443   GC_word GC_atomic_add(volatile GC_word *addr, GC_word how_much)
1444   {
1445     GC_word old;
1446     pthread_mutex_lock(&GC_compare_and_swap_lock);
1447     old = *addr;
1448     *addr = old + how_much;
1449     pthread_mutex_unlock(&GC_compare_and_swap_lock);
1450     return old;
1451   }
1452
1453 #endif /* GENERIC_COMPARE_AND_SWAP */
1454 /* Spend a few cycles in a way that can't introduce contention with     */
1455 /* othre threads.                                                       */
1456 void GC_pause()
1457 {
1458     int i;
1459 #   if !defined(__GNUC__) || defined(__INTEL_COMPILER)
1460       volatile word dummy = 0;
1461 #   endif
1462
1463     for (i = 0; i < 10; ++i) { 
1464 #     if defined(__GNUC__) && !defined(__INTEL_COMPILER)
1465         __asm__ __volatile__ (" " : : : "memory");
1466 #     else
1467         /* Something that's unlikely to be optimized away. */
1468         GC_noop(++dummy);
1469 #     endif
1470     }
1471 }
1472     
1473 #define SPIN_MAX 128    /* Maximum number of calls to GC_pause before   */
1474                         /* give up.                                     */
1475
1476 VOLATILE GC_bool GC_collecting = 0;
1477                         /* A hint that we're in the collector and       */
1478                         /* holding the allocation lock for an           */
1479                         /* extended period.                             */
1480
1481 #if !defined(USE_SPIN_LOCK) || defined(PARALLEL_MARK)
1482 /* If we don't want to use the below spinlock implementation, either    */
1483 /* because we don't have a GC_test_and_set implementation, or because   */
1484 /* we don't want to risk sleeping, we can still try spinning on         */
1485 /* pthread_mutex_trylock for a while.  This appears to be very          */
1486 /* beneficial in many cases.                                            */
1487 /* I suspect that under high contention this is nearly always better    */
1488 /* than the spin lock.  But it's a bit slower on a uniprocessor.        */
1489 /* Hence we still default to the spin lock.                             */
1490 /* This is also used to acquire the mark lock for the parallel          */
1491 /* marker.                                                              */
1492
1493 /* Here we use a strict exponential backoff scheme.  I don't know       */
1494 /* whether that's better or worse than the above.  We eventually        */
1495 /* yield by calling pthread_mutex_lock(); it never makes sense to       */
1496 /* explicitly sleep.                                                    */
1497
1498 #define LOCK_STATS
1499 #ifdef LOCK_STATS
1500   unsigned long GC_spin_count = 0;
1501   unsigned long GC_block_count = 0;
1502   unsigned long GC_unlocked_count = 0;
1503 #endif
1504
1505 void GC_generic_lock(pthread_mutex_t * lock)
1506 {
1507 #ifndef NO_PTHREAD_TRYLOCK
1508     unsigned pause_length = 1;
1509     unsigned i;
1510     
1511     if (0 == pthread_mutex_trylock(lock)) {
1512 #       ifdef LOCK_STATS
1513             ++GC_unlocked_count;
1514 #       endif
1515         return;
1516     }
1517     for (; pause_length <= SPIN_MAX; pause_length <<= 1) {
1518         for (i = 0; i < pause_length; ++i) {
1519             GC_pause();
1520         }
1521         switch(pthread_mutex_trylock(lock)) {
1522             case 0:
1523 #               ifdef LOCK_STATS
1524                     ++GC_spin_count;
1525 #               endif
1526                 return;
1527             case EBUSY:
1528                 break;
1529             default:
1530                 ABORT("Unexpected error from pthread_mutex_trylock");
1531         }
1532     }
1533 #endif /* !NO_PTHREAD_TRYLOCK */
1534 #   ifdef LOCK_STATS
1535         ++GC_block_count;
1536 #   endif
1537     pthread_mutex_lock(lock);
1538 }
1539
1540 #endif /* !USE_SPIN_LOCK || PARALLEL_MARK */
1541
1542 #if defined(USE_SPIN_LOCK)
1543
1544 /* Reasonably fast spin locks.  Basically the same implementation */
1545 /* as STL alloc.h.  This isn't really the right way to do this.   */
1546 /* but until the POSIX scheduling mess gets straightened out ...  */
1547
1548 volatile unsigned int GC_allocate_lock = 0;
1549
1550
1551 void GC_lock()
1552 {
1553 #   define low_spin_max 30  /* spin cycles if we suspect uniprocessor */
1554 #   define high_spin_max SPIN_MAX /* spin cycles for multiprocessor */
1555     static unsigned spin_max = low_spin_max;
1556     unsigned my_spin_max;
1557     static unsigned last_spins = 0;
1558     unsigned my_last_spins;
1559     int i;
1560
1561     if (!GC_test_and_set(&GC_allocate_lock)) {
1562         return;
1563     }
1564     my_spin_max = spin_max;
1565     my_last_spins = last_spins;
1566     for (i = 0; i < my_spin_max; i++) {
1567         if (GC_collecting || GC_nprocs == 1) goto yield;
1568         if (i < my_last_spins/2 || GC_allocate_lock) {
1569             GC_pause();
1570             continue;
1571         }
1572         if (!GC_test_and_set(&GC_allocate_lock)) {
1573             /*
1574              * got it!
1575              * Spinning worked.  Thus we're probably not being scheduled
1576              * against the other process with which we were contending.
1577              * Thus it makes sense to spin longer the next time.
1578              */
1579             last_spins = i;
1580             spin_max = high_spin_max;
1581             return;
1582         }
1583     }
1584     /* We are probably being scheduled against the other process.  Sleep. */
1585     spin_max = low_spin_max;
1586 yield:
1587     for (i = 0;; ++i) {
1588         if (!GC_test_and_set(&GC_allocate_lock)) {
1589             return;
1590         }
1591 #       define SLEEP_THRESHOLD 12
1592                 /* Under Linux very short sleeps tend to wait until     */
1593                 /* the current time quantum expires.  On old Linux      */
1594                 /* kernels nanosleep(<= 2ms) just spins under Linux.    */
1595                 /* (Under 2.4, this happens only for real-time          */
1596                 /* processes.)  We want to minimize both behaviors      */
1597                 /* here.                                                */
1598         if (i < SLEEP_THRESHOLD) {
1599             sched_yield();
1600         } else {
1601             struct timespec ts;
1602         
1603             if (i > 24) i = 24;
1604                         /* Don't wait for more than about 15msecs, even */
1605                         /* under extreme contention.                    */
1606             ts.tv_sec = 0;
1607             ts.tv_nsec = 1 << i;
1608             nanosleep(&ts, 0);
1609         }
1610     }
1611 }
1612
1613 #else  /* !USE_SPINLOCK */
1614 void GC_lock()
1615 {
1616 #ifndef NO_PTHREAD_TRYLOCK
1617     if (1 == GC_nprocs || GC_collecting) {
1618         pthread_mutex_lock(&GC_allocate_ml);
1619     } else {
1620         GC_generic_lock(&GC_allocate_ml);
1621     }
1622 #else  /* !NO_PTHREAD_TRYLOCK */
1623     pthread_mutex_lock(&GC_allocate_ml);
1624 #endif /* !NO_PTHREAD_TRYLOCK */
1625 }
1626
1627 #endif /* !USE_SPINLOCK */
1628
1629 #if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC)
1630
1631 #ifdef GC_ASSERTIONS
1632   pthread_t GC_mark_lock_holder = NO_THREAD;
1633 #endif
1634
1635 #if 0
1636   /* Ugly workaround for a linux threads bug in the final versions      */
1637   /* of glibc2.1.  Pthread_mutex_trylock sets the mutex owner           */
1638   /* field even when it fails to acquire the mutex.  This causes        */
1639   /* pthread_cond_wait to die.  Remove for glibc2.2.                    */
1640   /* According to the man page, we should use                           */
1641   /* PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, but that isn't actually   */
1642   /* defined.                                                           */
1643   static pthread_mutex_t mark_mutex =
1644         {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, {0, 0}};
1645 #else
1646   static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
1647 #endif
1648
1649 static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
1650
1651 void GC_acquire_mark_lock()
1652 {
1653 /*
1654     if (pthread_mutex_lock(&mark_mutex) != 0) {
1655         ABORT("pthread_mutex_lock failed");
1656     }
1657 */
1658     GC_generic_lock(&mark_mutex);
1659 #   ifdef GC_ASSERTIONS
1660         GC_mark_lock_holder = pthread_self();
1661 #   endif
1662 }
1663
1664 void GC_release_mark_lock()
1665 {
1666     GC_ASSERT(GC_mark_lock_holder == pthread_self());
1667 #   ifdef GC_ASSERTIONS
1668         GC_mark_lock_holder = NO_THREAD;
1669 #   endif
1670     if (pthread_mutex_unlock(&mark_mutex) != 0) {
1671         ABORT("pthread_mutex_unlock failed");
1672     }
1673 }
1674
1675 /* Collector must wait for a freelist builders for 2 reasons:           */
1676 /* 1) Mark bits may still be getting examined without lock.             */
1677 /* 2) Partial free lists referenced only by locals may not be scanned   */
1678 /*    correctly, e.g. if they contain "pointer-free" objects, since the */
1679 /*    free-list link may be ignored.                                    */
1680 void GC_wait_builder()
1681 {
1682     GC_ASSERT(GC_mark_lock_holder == pthread_self());
1683 #   ifdef GC_ASSERTIONS
1684         GC_mark_lock_holder = NO_THREAD;
1685 #   endif
1686     if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) {
1687         ABORT("pthread_cond_wait failed");
1688     }
1689     GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
1690 #   ifdef GC_ASSERTIONS
1691         GC_mark_lock_holder = pthread_self();
1692 #   endif
1693 }
1694
1695 void GC_wait_for_reclaim()
1696 {
1697     GC_acquire_mark_lock();
1698     while (GC_fl_builder_count > 0) {
1699         GC_wait_builder();
1700     }
1701     GC_release_mark_lock();
1702 }
1703
1704 void GC_notify_all_builder()
1705 {
1706     GC_ASSERT(GC_mark_lock_holder == pthread_self());
1707     if (pthread_cond_broadcast(&builder_cv) != 0) {
1708         ABORT("pthread_cond_broadcast failed");
1709     }
1710 }
1711
1712 #endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */
1713
1714 #ifdef PARALLEL_MARK
1715
1716 static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
1717
1718 void GC_wait_marker()
1719 {
1720     GC_ASSERT(GC_mark_lock_holder == pthread_self());
1721 #   ifdef GC_ASSERTIONS
1722         GC_mark_lock_holder = NO_THREAD;
1723 #   endif
1724     if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
1725         ABORT("pthread_cond_wait failed");
1726     }
1727     GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
1728 #   ifdef GC_ASSERTIONS
1729         GC_mark_lock_holder = pthread_self();
1730 #   endif
1731 }
1732
1733 void GC_notify_all_marker()
1734 {
1735     if (pthread_cond_broadcast(&mark_cv) != 0) {
1736         ABORT("pthread_cond_broadcast failed");
1737     }
1738 }
1739
1740 #endif /* PARALLEL_MARK */
1741
1742 # endif /* GC_LINUX_THREADS and friends */
1743