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