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