New macro (CONSOLE_LOG) to enable logging to console on Win32
[platform/upstream/libgc.git] / win32_threads.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-2008 by Hewlett-Packard Development Company.
6  * All rights reserved.
7  *
8  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
9  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
10  *
11  * Permission is hereby granted to use or copy this program
12  * for any purpose,  provided the above notices are retained on all copies.
13  * Permission to modify the code and to distribute modified code is granted,
14  * provided the above notices are retained, and a notice that the code was
15  * modified is included with the above copyright notice.
16  */
17
18 #include "private/gc_priv.h"
19
20 #if defined(GC_WIN32_THREADS)
21
22 #ifndef WIN32_LEAN_AND_MEAN
23 # define WIN32_LEAN_AND_MEAN 1
24 #endif
25 #define NOSERVICE
26 #include <windows.h>
27
28 #ifdef THREAD_LOCAL_ALLOC
29 # include "private/thread_local_alloc.h"
30 #endif /* THREAD_LOCAL_ALLOC */
31
32 /* Allocation lock declarations.        */
33 #if !defined(USE_PTHREAD_LOCKS)
34   GC_INNER CRITICAL_SECTION GC_allocate_ml;
35 # ifdef GC_ASSERTIONS
36     GC_INNER DWORD GC_lock_holder = NO_THREAD;
37         /* Thread id for current holder of allocation lock */
38 # endif
39 #else
40   GC_INNER pthread_mutex_t GC_allocate_ml = PTHREAD_MUTEX_INITIALIZER;
41 # ifdef GC_ASSERTIONS
42     GC_INNER unsigned long GC_lock_holder = NO_THREAD;
43 # endif
44 #endif
45
46 #undef CreateThread
47 #undef ExitThread
48 #undef _beginthreadex
49 #undef _endthreadex
50
51 #ifdef GC_PTHREADS
52 # include <errno.h> /* for EAGAIN */
53
54  /* Cygwin-specific forward decls */
55 # undef pthread_create
56 # undef pthread_join
57 # undef pthread_detach
58
59 # ifndef GC_NO_PTHREAD_SIGMASK
60 #   undef pthread_sigmask
61 # endif
62
63   STATIC void * GC_pthread_start(void * arg);
64   STATIC void GC_thread_exit_proc(void *arg);
65
66 # include <pthread.h>
67 # ifdef CAN_CALL_ATFORK
68 #   include <unistd.h>
69 # endif
70
71 #elif !defined(MSWINCE)
72 # include <process.h>  /* For _beginthreadex, _endthreadex */
73 # include <errno.h> /* for errno, EAGAIN */
74
75 #endif /* !GC_PTHREADS && !MSWINCE */
76
77 /* PUSHED_REGS_COUNT is the number of copied registers in copy_ptr_regs. */
78 static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext);
79 #if defined(I386)
80 # ifdef WOW64_THREAD_CONTEXT_WORKAROUND
81 #   define PUSHED_REGS_COUNT 9
82 # else
83 #   define PUSHED_REGS_COUNT 7
84 # endif
85 #elif defined(X86_64) || defined(SHx)
86 # define PUSHED_REGS_COUNT 15
87 #elif defined(ARM32)
88 # define PUSHED_REGS_COUNT 13
89 #elif defined(AARCH64)
90 # define PUSHED_REGS_COUNT 30
91 #elif defined(MIPS) || defined(ALPHA)
92 # define PUSHED_REGS_COUNT 28
93 #elif defined(PPC)
94 # define PUSHED_REGS_COUNT 29
95 #endif
96
97 /* DllMain-based thread registration is currently incompatible  */
98 /* with thread-local allocation, pthreads and WinCE.            */
99 #if (defined(GC_DLL) || defined(GC_INSIDE_DLL)) && !defined(NO_CRT) \
100         && !defined(GC_NO_THREADS_DISCOVERY) && !defined(MSWINCE) \
101         && !defined(THREAD_LOCAL_ALLOC) && !defined(GC_PTHREADS)
102
103   /* This code operates in two distinct modes, depending on     */
104   /* the setting of GC_win32_dll_threads.                       */
105   /* If GC_win32_dll_threads is set, all threads in the process */
106   /* are implicitly registered with the GC by DllMain.          */
107   /* No explicit registration is required, and attempts at      */
108   /* explicit registration are ignored.  This mode is           */
109   /* very different from the Posix operation of the collector.  */
110   /* In this mode access to the thread table is lock-free.      */
111   /* Hence there is a static limit on the number of threads.    */
112
113 # ifdef GC_DISCOVER_TASK_THREADS
114     /* GC_DISCOVER_TASK_THREADS should be used if DllMain-based */
115     /* thread registration is required but it is impossible to  */
116     /* call GC_use_threads_discovery before other GC routines.  */
117 #   define GC_win32_dll_threads TRUE
118 # else
119     STATIC GC_bool GC_win32_dll_threads = FALSE;
120     /* GC_win32_dll_threads must be set (if needed) at the      */
121     /* application initialization time, i.e. before any         */
122     /* collector or thread calls.  We make it a "dynamic"       */
123     /* option only to avoid multiple library versions.          */
124 # endif
125
126 #else
127   /* If GC_win32_dll_threads is FALSE (or the collector is      */
128   /* built without GC_DLL defined), things operate in a way     */
129   /* that is very similar to Posix platforms, and new threads   */
130   /* must be registered with the collector, e.g. by using       */
131   /* preprocessor-based interception of the thread primitives.  */
132   /* In this case, we use a real data structure for the thread  */
133   /* table.  Note that there is no equivalent of linker-based   */
134   /* call interception, since we don't have ELF-like            */
135   /* facilities.  The Windows analog appears to be "API         */
136   /* hooking", which really seems to be a standard way to       */
137   /* do minor binary rewriting (?).  I'd prefer not to have     */
138   /* the basic collector rely on such facilities, but an        */
139   /* optional package that intercepts thread calls this way     */
140   /* would probably be nice.                                    */
141 # ifndef GC_NO_THREADS_DISCOVERY
142 #   define GC_NO_THREADS_DISCOVERY
143 # endif
144 # define GC_win32_dll_threads FALSE
145 # undef MAX_THREADS
146 # define MAX_THREADS 1 /* dll_thread_table[] is always empty.   */
147 #endif /* GC_NO_THREADS_DISCOVERY */
148
149 /* We have two versions of the thread table.  Which one */
150 /* we us depends on whether or not GC_win32_dll_threads */
151 /* is set.  Note that before initialization, we don't   */
152 /* add any entries to either table, even if DllMain is  */
153 /* called.  The main thread will be added on            */
154 /* initialization.                                      */
155
156 /* The type of the first argument to InterlockedExchange.       */
157 /* Documented to be LONG volatile *, but at least gcc likes     */
158 /* this better.                                                 */
159 typedef LONG * IE_t;
160
161 STATIC GC_bool GC_thr_initialized = FALSE;
162
163 #ifndef GC_ALWAYS_MULTITHREADED
164   GC_INNER GC_bool GC_need_to_lock = FALSE;
165 #endif
166
167 static GC_bool parallel_initialized = FALSE;
168
169 /* GC_use_threads_discovery() is currently incompatible with pthreads   */
170 /* and WinCE.  It might be possible to get DllMain-based thread         */
171 /* registration to work with Cygwin, but if you try it then you are on  */
172 /* your own.                                                            */
173 GC_API void GC_CALL GC_use_threads_discovery(void)
174 {
175 # ifdef GC_NO_THREADS_DISCOVERY
176     ABORT("GC DllMain-based thread registration unsupported");
177 # else
178     /* Turn on GC_win32_dll_threads. */
179     GC_ASSERT(!parallel_initialized);
180     /* Note that GC_use_threads_discovery is expected to be called by   */
181     /* the client application (not from DllMain) at start-up.           */
182 #   ifndef GC_DISCOVER_TASK_THREADS
183       GC_win32_dll_threads = TRUE;
184 #   endif
185     GC_init_parallel();
186 # endif
187 }
188
189 #define ADDR_LIMIT ((ptr_t)GC_WORD_MAX)
190
191 struct GC_Thread_Rep {
192   union {
193 #   ifndef GC_NO_THREADS_DISCOVERY
194       volatile AO_t in_use;
195                         /* Updated without lock.                */
196                         /* We assert that unused                */
197                         /* entries have invalid ids of          */
198                         /* zero and zero stack fields.          */
199                         /* Used only with GC_win32_dll_threads. */
200       LONG long_in_use; /* The same but of the type that        */
201                         /* matches the first argument of        */
202                         /* InterlockedExchange(); volatile is   */
203                         /* omitted because the ancient version  */
204                         /* of the prototype lacks the qualifier.*/
205 #   endif
206     struct GC_Thread_Rep * next;
207                         /* Hash table link without              */
208                         /* GC_win32_dll_threads.                */
209                         /* More recently allocated threads      */
210                         /* with a given pthread id come         */
211                         /* first.  (All but the first are       */
212                         /* guaranteed to be dead, but we may    */
213                         /* not yet have registered the join.)   */
214   } tm; /* table_management */
215   DWORD id;
216
217 # ifdef MSWINCE
218     /* According to MSDN specs for WinCE targets:                       */
219     /* - DuplicateHandle() is not applicable to thread handles; and     */
220     /* - the value returned by GetCurrentThreadId() could be used as    */
221     /* a "real" thread handle (for SuspendThread(), ResumeThread() and  */
222     /* GetThreadContext()).                                             */
223 #   define THREAD_HANDLE(t) (HANDLE)(word)(t)->id
224 # else
225     HANDLE handle;
226 #   define THREAD_HANDLE(t) (t)->handle
227 # endif
228
229   ptr_t stack_base;     /* The cold end of the stack.   */
230                         /* 0 ==> entry not valid.       */
231                         /* !in_use ==> stack_base == 0  */
232   ptr_t last_stack_min; /* Last known minimum (hottest) address */
233                         /* in stack or ADDR_LIMIT if unset      */
234 # ifdef IA64
235     ptr_t backing_store_end;
236     ptr_t backing_store_ptr;
237 # elif defined(I386)
238     ptr_t initial_stack_base;
239                         /* The cold end of the stack saved by   */
240                         /* GC_record_stack_base (never modified */
241                         /* by GC_set_stackbottom).              */
242 # endif
243
244   ptr_t thread_blocked_sp;      /* Protected by GC lock.                */
245                                 /* NULL value means thread unblocked.   */
246                                 /* If set to non-NULL, thread will      */
247                                 /* acquire GC lock before doing any     */
248                                 /* pointer manipulations.  Thus it does */
249                                 /* not need to stop this thread.        */
250
251   struct GC_traced_stack_sect_s *traced_stack_sect;
252                                 /* Points to the "stack section" data   */
253                                 /* held in stack by the innermost       */
254                                 /* GC_call_with_gc_active() of this     */
255                                 /* thread.  May be NULL.                */
256
257   unsigned short finalizer_skipped;
258   unsigned char finalizer_nested;
259                                 /* Used by GC_check_finalizer_nested()  */
260                                 /* to minimize the level of recursion   */
261                                 /* when a client finalizer allocates    */
262                                 /* memory (initially both are 0).       */
263
264   unsigned char suspended; /* really of GC_bool type */
265
266 # ifdef GC_PTHREADS
267     unsigned char flags;        /* Protected by GC lock.                */
268 #   define FINISHED 1           /* Thread has exited.                   */
269 #   define DETACHED 2           /* Thread is intended to be detached.   */
270 #   define KNOWN_FINISHED(t) (((t) -> flags) & FINISHED)
271     pthread_t pthread_id;
272     void *status;  /* hold exit value until join in case it's a pointer */
273 # else
274 #   define KNOWN_FINISHED(t) 0
275 # endif
276
277 # ifdef THREAD_LOCAL_ALLOC
278     struct thread_local_freelists tlfs;
279 # endif
280
281 # ifdef RETRY_GET_THREAD_CONTEXT
282     ptr_t context_sp;
283     word context_regs[PUSHED_REGS_COUNT];
284                         /* Populated as part of GC_suspend() as         */
285                         /* resume/suspend loop may be needed for the    */
286                         /* call to GetThreadContext() to succeed.       */
287 # endif
288 };
289
290 typedef struct GC_Thread_Rep * GC_thread;
291 typedef volatile struct GC_Thread_Rep * GC_vthread;
292
293 #ifndef GC_NO_THREADS_DISCOVERY
294   STATIC DWORD GC_main_thread = 0;
295
296   /* We track thread attachments while the world is supposed to be      */
297   /* stopped.  Unfortunately, we cannot stop them from starting, since  */
298   /* blocking in DllMain seems to cause the world to deadlock.  Thus,   */
299   /* we have to recover if we notice this in the middle of marking.     */
300   STATIC volatile AO_t GC_attached_thread = FALSE;
301
302   /* We assumed that volatile ==> memory ordering, at least among       */
303   /* volatiles.  This code should consistently use atomic_ops.          */
304   STATIC volatile GC_bool GC_please_stop = FALSE;
305 #elif defined(GC_ASSERTIONS)
306   STATIC GC_bool GC_please_stop = FALSE;
307 #endif /* GC_NO_THREADS_DISCOVERY && GC_ASSERTIONS */
308
309 #if defined(WRAP_MARK_SOME) && !defined(GC_PTHREADS)
310   /* Return TRUE if an thread was attached since we last asked or */
311   /* since GC_attached_thread was explicitly reset.               */
312   GC_INNER GC_bool GC_started_thread_while_stopped(void)
313   {
314 #   ifndef GC_NO_THREADS_DISCOVERY
315       if (GC_win32_dll_threads) {
316 #       ifdef AO_HAVE_compare_and_swap_release
317           if (AO_compare_and_swap_release(&GC_attached_thread, TRUE,
318                                           FALSE /* stored */))
319             return TRUE;
320 #       else
321           AO_nop_full(); /* Prior heap reads need to complete earlier. */
322           if (AO_load(&GC_attached_thread)) {
323             AO_store(&GC_attached_thread, FALSE);
324             return TRUE;
325           }
326 #       endif
327       }
328 #   endif
329     return FALSE;
330   }
331 #endif /* WRAP_MARK_SOME */
332
333 /* Thread table used if GC_win32_dll_threads is set.    */
334 /* This is a fixed size array.                          */
335 /* Since we use runtime conditionals, both versions     */
336 /* are always defined.                                  */
337 # ifndef MAX_THREADS
338 #   define MAX_THREADS 512
339 # endif
340
341 /* Things may get quite slow for large numbers of threads,      */
342 /* since we look them up with sequential search.                */
343 volatile struct GC_Thread_Rep dll_thread_table[MAX_THREADS];
344
345 STATIC volatile LONG GC_max_thread_index = 0;
346                         /* Largest index in dll_thread_table    */
347                         /* that was ever used.                  */
348
349 /* And now the version used if GC_win32_dll_threads is not set. */
350 /* This is a chained hash table, with much of the code borrowed */
351 /* from the Posix implementation.                               */
352 #ifndef THREAD_TABLE_SZ
353 # define THREAD_TABLE_SZ 256    /* Power of 2 (for speed). */
354 #endif
355 #define THREAD_TABLE_INDEX(id) /* id is of DWORD type */ \
356                 (int)((((id) >> 8) ^ (id)) % THREAD_TABLE_SZ)
357 STATIC GC_thread GC_threads[THREAD_TABLE_SZ];
358
359 /* It may not be safe to allocate when we register the first thread.    */
360 /* Thus we allocated one statically.  It does not contain any field we  */
361 /* need to push ("next" and "status" fields are unused).                */
362 static struct GC_Thread_Rep first_thread;
363 static GC_bool first_thread_used = FALSE;
364
365 /* Add a thread to GC_threads.  We assume it wasn't already there.      */
366 /* Caller holds allocation lock.                                        */
367 /* Unlike the pthreads version, the id field is set by the caller.      */
368 STATIC GC_thread GC_new_thread(DWORD id)
369 {
370   int hv = THREAD_TABLE_INDEX(id);
371   GC_thread result;
372
373 # ifdef DEBUG_THREADS
374     GC_log_printf("Creating thread 0x%lx\n", (long)id);
375     if (GC_threads[hv] != NULL)
376       GC_log_printf("Hash collision at GC_threads[%d]\n", hv);
377 # endif
378   GC_ASSERT(I_HOLD_LOCK());
379   if (!EXPECT(first_thread_used, TRUE)) {
380     result = &first_thread;
381     first_thread_used = TRUE;
382     GC_ASSERT(NULL == GC_threads[hv]);
383   } else {
384     GC_ASSERT(!GC_win32_dll_threads);
385     result = (struct GC_Thread_Rep *)
386                 GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
387     if (result == 0) return(0);
388   }
389   /* result -> id = id; Done by caller.       */
390   result -> tm.next = GC_threads[hv];
391   GC_threads[hv] = result;
392 # ifdef GC_PTHREADS
393     GC_ASSERT(result -> flags == 0);
394 # endif
395   GC_ASSERT(result -> thread_blocked_sp == NULL);
396   if (EXPECT(result != &first_thread, TRUE))
397     GC_dirty(result);
398   return(result);
399 }
400
401 GC_INNER GC_bool GC_in_thread_creation = FALSE;
402                                 /* Protected by allocation lock. */
403
404 GC_INLINE void GC_record_stack_base(GC_vthread me,
405                                     const struct GC_stack_base *sb)
406 {
407   me -> stack_base = (ptr_t)sb->mem_base;
408 # ifdef IA64
409     me -> backing_store_end = (ptr_t)sb->reg_base;
410 # elif defined(I386)
411     me -> initial_stack_base = (ptr_t)sb->mem_base;
412 # endif
413   if (me -> stack_base == NULL)
414     ABORT("Bad stack base in GC_register_my_thread");
415 }
416
417 /* This may be called from DllMain, and hence operates under unusual    */
418 /* constraints.  In particular, it must be lock-free if                 */
419 /* GC_win32_dll_threads is set.  Always called from the thread being    */
420 /* added.  If GC_win32_dll_threads is not set, we already hold the      */
421 /* allocation lock except possibly during single-threaded startup code. */
422 STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
423                                              DWORD thread_id)
424 {
425   GC_vthread me;
426
427   /* The following should be a no-op according to the win32     */
428   /* documentation.  There is empirical evidence that it        */
429   /* isn't.             - HB                                    */
430 # if defined(MPROTECT_VDB) && !defined(CYGWIN32)
431     if (GC_auto_incremental
432 #       ifdef GWW_VDB
433           && !GC_gww_dirty_init()
434 #       endif
435         )
436       GC_set_write_fault_handler();
437 # endif
438
439 # ifndef GC_NO_THREADS_DISCOVERY
440     if (GC_win32_dll_threads) {
441       int i;
442       /* It appears to be unsafe to acquire a lock here, since this     */
443       /* code is apparently not preemptible on some systems.            */
444       /* (This is based on complaints, not on Microsoft's official      */
445       /* documentation, which says this should perform "only simple     */
446       /* initialization tasks".)                                        */
447       /* Hence we make do with nonblocking synchronization.             */
448       /* It has been claimed that DllMain is really only executed with  */
449       /* a particular system lock held, and thus careful use of locking */
450       /* around code that doesn't call back into the system libraries   */
451       /* might be OK.  But this hasn't been tested across all win32     */
452       /* variants.                                                      */
453       for (i = 0;
454            InterlockedExchange(&dll_thread_table[i].tm.long_in_use, 1) != 0;
455            i++) {
456         /* Compare-and-swap would make this cleaner, but that's not     */
457         /* supported before Windows 98 and NT 4.0.  In Windows 2000,    */
458         /* InterlockedExchange is supposed to be replaced by            */
459         /* InterlockedExchangePointer, but that's not really what I     */
460         /* want here.                                                   */
461         /* FIXME: We should eventually declare Win95 dead and use AO_   */
462         /* primitives here.                                             */
463         if (i == MAX_THREADS - 1)
464           ABORT("Too many threads");
465       }
466       /* Update GC_max_thread_index if necessary.  The following is     */
467       /* safe, and unlike CompareExchange-based solutions seems to work */
468       /* on all Windows95 and later platforms.                          */
469       /* Unfortunately, GC_max_thread_index may be temporarily out of   */
470       /* bounds, so readers have to compensate.                         */
471       while (i > GC_max_thread_index) {
472         InterlockedIncrement((IE_t)&GC_max_thread_index);
473       }
474       if (GC_max_thread_index >= MAX_THREADS) {
475         /* We overshot due to simultaneous increments.  */
476         /* Setting it to MAX_THREADS-1 is always safe.  */
477         GC_max_thread_index = MAX_THREADS - 1;
478       }
479       me = dll_thread_table + i;
480     } else
481 # endif
482   /* else */ /* Not using DllMain */ {
483     GC_ASSERT(I_HOLD_LOCK());
484     GC_in_thread_creation = TRUE; /* OK to collect from unknown thread. */
485     me = GC_new_thread(thread_id);
486     GC_in_thread_creation = FALSE;
487     if (me == 0)
488       ABORT("Failed to allocate memory for thread registering");
489   }
490 # ifdef GC_PTHREADS
491     /* me can be NULL -> segfault */
492     me -> pthread_id = pthread_self();
493 # endif
494 # ifndef MSWINCE
495     /* GetCurrentThread() returns a pseudohandle (a const value).       */
496     if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
497                         GetCurrentProcess(),
498                         (HANDLE*)&(me -> handle),
499                         0 /* dwDesiredAccess */, FALSE /* bInheritHandle */,
500                         DUPLICATE_SAME_ACCESS)) {
501         ABORT_ARG1("DuplicateHandle failed",
502                    ": errcode= 0x%X", (unsigned)GetLastError());
503     }
504 # endif
505   me -> last_stack_min = ADDR_LIMIT;
506   GC_record_stack_base(me, sb);
507   /* Up until this point, GC_push_all_stacks considers this thread      */
508   /* invalid.                                                           */
509   /* Up until this point, this entry is viewed as reserved but invalid  */
510   /* by GC_delete_thread.                                               */
511   me -> id = thread_id;
512 # if defined(THREAD_LOCAL_ALLOC)
513     GC_init_thread_local((GC_tlfs)(&(me->tlfs)));
514 # endif
515 # ifndef GC_NO_THREADS_DISCOVERY
516     if (GC_win32_dll_threads) {
517       if (GC_please_stop) {
518         AO_store(&GC_attached_thread, TRUE);
519         AO_nop_full(); /* Later updates must become visible after this. */
520       }
521       /* We'd like to wait here, but can't, since waiting in DllMain    */
522       /* provokes deadlocks.                                            */
523       /* Thus we force marking to be restarted instead.                 */
524     } else
525 # endif
526   /* else */ {
527     GC_ASSERT(!GC_please_stop);
528         /* Otherwise both we and the thread stopping code would be      */
529         /* holding the allocation lock.                                 */
530   }
531   return (GC_thread)(me);
532 }
533
534 /*
535  * GC_max_thread_index may temporarily be larger than MAX_THREADS.
536  * To avoid subscript errors, we check on access.
537  */
538 GC_INLINE LONG GC_get_max_thread_index(void)
539 {
540   LONG my_max = GC_max_thread_index;
541   if (my_max >= MAX_THREADS) return MAX_THREADS - 1;
542   return my_max;
543 }
544
545 /* Return the GC_thread corresponding to a thread id.  May be called    */
546 /* without a lock, but should be called in contexts in which the        */
547 /* requested thread cannot be asynchronously deleted, e.g. from the     */
548 /* thread itself.                                                       */
549 /* This version assumes that either GC_win32_dll_threads is set, or     */
550 /* we hold the allocator lock.                                          */
551 /* Also used (for assertion checking only) from thread_local_alloc.c.   */
552 STATIC GC_thread GC_lookup_thread_inner(DWORD thread_id)
553 {
554 # ifndef GC_NO_THREADS_DISCOVERY
555     if (GC_win32_dll_threads) {
556       int i;
557       LONG my_max = GC_get_max_thread_index();
558       for (i = 0; i <= my_max &&
559                   (!AO_load_acquire(&dll_thread_table[i].tm.in_use)
560                   || dll_thread_table[i].id != thread_id);
561            /* Must still be in_use, since nobody else can store our     */
562            /* thread_id.                                                */
563            i++) {
564         /* empty */
565       }
566       return i <= my_max ? (GC_thread)(dll_thread_table + i) : NULL;
567     } else
568 # endif
569   /* else */ {
570     GC_thread p = GC_threads[THREAD_TABLE_INDEX(thread_id)];
571
572     GC_ASSERT(I_HOLD_LOCK());
573     while (p != 0 && p -> id != thread_id) p = p -> tm.next;
574     return(p);
575   }
576 }
577
578 #ifdef LINT2
579 # define CHECK_LOOKUP_MY_THREAD(me) \
580         if (!(me)) ABORT("GC_lookup_thread_inner(GetCurrentThreadId) failed")
581 #else
582 # define CHECK_LOOKUP_MY_THREAD(me) /* empty */
583 #endif
584
585 /* Called by GC_finalize() (in case of an allocation failure observed). */
586 /* GC_reset_finalizer_nested() is the same as in pthread_support.c.     */
587 GC_INNER void GC_reset_finalizer_nested(void)
588 {
589   GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId());
590   CHECK_LOOKUP_MY_THREAD(me);
591   me->finalizer_nested = 0;
592 }
593
594 /* Checks and updates the thread-local level of finalizers recursion.   */
595 /* Returns NULL if GC_invoke_finalizers() should not be called by the   */
596 /* collector (to minimize the risk of a deep finalizers recursion),     */
597 /* otherwise returns a pointer to the thread-local finalizer_nested.    */
598 /* Called by GC_notify_or_invoke_finalizers() only (the lock is held).  */
599 /* GC_check_finalizer_nested() is the same as in pthread_support.c.     */
600 GC_INNER unsigned char *GC_check_finalizer_nested(void)
601 {
602   GC_thread me = GC_lookup_thread_inner(GetCurrentThreadId());
603   unsigned nesting_level;
604   CHECK_LOOKUP_MY_THREAD(me);
605   nesting_level = me->finalizer_nested;
606   if (nesting_level) {
607     /* We are inside another GC_invoke_finalizers().            */
608     /* Skip some implicitly-called GC_invoke_finalizers()       */
609     /* depending on the nesting (recursion) level.              */
610     if (++me->finalizer_skipped < (1U << nesting_level)) return NULL;
611     me->finalizer_skipped = 0;
612   }
613   me->finalizer_nested = (unsigned char)(nesting_level + 1);
614   return &me->finalizer_nested;
615 }
616
617 #if defined(GC_ASSERTIONS) && defined(THREAD_LOCAL_ALLOC)
618   /* This is called from thread-local GC_malloc(). */
619   GC_bool GC_is_thread_tsd_valid(void *tsd)
620   {
621     GC_thread me;
622     DCL_LOCK_STATE;
623
624     LOCK();
625     me = GC_lookup_thread_inner(GetCurrentThreadId());
626     UNLOCK();
627     return (word)tsd >= (word)(&me->tlfs)
628             && (word)tsd < (word)(&me->tlfs) + sizeof(me->tlfs);
629   }
630 #endif /* GC_ASSERTIONS && THREAD_LOCAL_ALLOC */
631
632 GC_API int GC_CALL GC_thread_is_registered(void)
633 {
634     DWORD thread_id = GetCurrentThreadId();
635     GC_thread me;
636     DCL_LOCK_STATE;
637
638     LOCK();
639     me = GC_lookup_thread_inner(thread_id);
640     UNLOCK();
641     return me != NULL;
642 }
643
644 GC_API void GC_CALL GC_register_altstack(void *stack GC_ATTR_UNUSED,
645                                          GC_word stack_size GC_ATTR_UNUSED,
646                                          void *altstack GC_ATTR_UNUSED,
647                                          GC_word altstack_size GC_ATTR_UNUSED)
648 {
649   /* TODO: Implement */
650 }
651
652 /* Make sure thread descriptor t is not protected by the VDB            */
653 /* implementation.                                                      */
654 /* Used to prevent write faults when the world is (partially) stopped,  */
655 /* since it may have been stopped with a system lock held, and that     */
656 /* lock may be required for fault handling.                             */
657 #if defined(MPROTECT_VDB)
658 # define UNPROTECT_THREAD(t) \
659     if (!GC_win32_dll_threads && GC_auto_incremental \
660         && t != &first_thread) { \
661       GC_ASSERT(SMALL_OBJ(GC_size(t))); \
662       GC_remove_protection(HBLKPTR(t), 1, FALSE); \
663     } else (void)0
664 #else
665 # define UNPROTECT_THREAD(t) (void)0
666 #endif
667
668 #ifdef CYGWIN32
669 # define GC_PTHREAD_PTRVAL(pthread_id) pthread_id
670 #elif defined(GC_WIN32_PTHREADS) || defined(GC_PTHREADS_PARAMARK)
671 # include <pthread.h> /* to check for winpthreads */
672 # if defined(__WINPTHREADS_VERSION_MAJOR)
673 #   define GC_PTHREAD_PTRVAL(pthread_id) pthread_id
674 # else
675 #   define GC_PTHREAD_PTRVAL(pthread_id) pthread_id.p
676 # endif
677 #endif
678
679 /* If a thread has been joined, but we have not yet             */
680 /* been notified, then there may be more than one thread        */
681 /* in the table with the same win32 id.                         */
682 /* This is OK, but we need a way to delete a specific one.      */
683 /* Assumes we hold the allocation lock unless                   */
684 /* GC_win32_dll_threads is set.  Does not actually free         */
685 /* GC_thread entry (only unlinks it).                           */
686 /* If GC_win32_dll_threads is set it should be called from the  */
687 /* thread being deleted.                                        */
688 STATIC void GC_delete_gc_thread_no_free(GC_vthread t)
689 {
690 # ifndef MSWINCE
691     CloseHandle(t->handle);
692 # endif
693 # ifndef GC_NO_THREADS_DISCOVERY
694     if (GC_win32_dll_threads) {
695       /* This is intended to be lock-free.                              */
696       /* It is either called synchronously from the thread being        */
697       /* deleted, or by the joining thread.                             */
698       /* In this branch asynchronous changes to (*t) are possible.      */
699       /* It's not allowed to call GC_printf (and the friends) here,     */
700       /* see GC_stop_world() for the information.                       */
701       t -> stack_base = 0;
702       t -> id = 0;
703       AO_store_release(&t->tm.in_use, FALSE);
704     } else
705 # endif
706   /* else */ {
707     DWORD id = ((GC_thread)t) -> id;
708                 /* Cast away volatile qualifier, since we have lock.    */
709     int hv = THREAD_TABLE_INDEX(id);
710     GC_thread p = GC_threads[hv];
711     GC_thread prev = NULL;
712
713     GC_ASSERT(I_HOLD_LOCK());
714     while (p != (GC_thread)t) {
715       prev = p;
716       p = p -> tm.next;
717     }
718     if (prev == 0) {
719       GC_threads[hv] = p -> tm.next;
720     } else {
721       GC_ASSERT(prev != &first_thread);
722       prev -> tm.next = p -> tm.next;
723       GC_dirty(prev);
724     }
725   }
726 }
727
728 /* Delete a thread from GC_threads.  We assume it is there.     */
729 /* (The code intentionally traps if it wasn't.)  Assumes we     */
730 /* hold the allocation lock unless GC_win32_dll_threads is set. */
731 /* If GC_win32_dll_threads is set then it should be called from */
732 /* the thread being deleted.  It is also safe to delete the     */
733 /* main thread (unless GC_win32_dll_threads).                   */
734 STATIC void GC_delete_thread(DWORD id)
735 {
736   if (GC_win32_dll_threads) {
737     GC_vthread t = GC_lookup_thread_inner(id);
738
739     if (0 == t) {
740       WARN("Removing nonexistent thread, id = %" WARN_PRIdPTR "\n", id);
741     } else {
742       GC_delete_gc_thread_no_free(t);
743     }
744   } else {
745     int hv = THREAD_TABLE_INDEX(id);
746     GC_thread p = GC_threads[hv];
747     GC_thread prev = NULL;
748
749     GC_ASSERT(I_HOLD_LOCK());
750     while (p -> id != id) {
751       prev = p;
752       p = p -> tm.next;
753     }
754 #   ifndef MSWINCE
755       CloseHandle(p->handle);
756 #   endif
757     if (prev == 0) {
758       GC_threads[hv] = p -> tm.next;
759     } else {
760       GC_ASSERT(prev != &first_thread);
761       prev -> tm.next = p -> tm.next;
762       GC_dirty(prev);
763     }
764     if (EXPECT(p != &first_thread, TRUE)) {
765       GC_INTERNAL_FREE(p);
766     }
767   }
768 }
769
770 GC_API void GC_CALL GC_allow_register_threads(void)
771 {
772   /* Check GC is initialized and the current thread is registered. */
773   GC_ASSERT(GC_lookup_thread_inner(GetCurrentThreadId()) != 0);
774 # if !defined(GC_ALWAYS_MULTITHREADED) && !defined(PARALLEL_MARK) \
775      && !defined(GC_NO_THREADS_DISCOVERY)
776       /* GC_init() does not call GC_init_parallel() in this case.   */
777     parallel_initialized = TRUE;
778 # endif
779   set_need_to_lock();
780 }
781
782 GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb)
783 {
784   GC_thread me;
785   DWORD thread_id = GetCurrentThreadId();
786   DCL_LOCK_STATE;
787
788   if (GC_need_to_lock == FALSE)
789     ABORT("Threads explicit registering is not previously enabled");
790
791   /* We lock here, since we want to wait for an ongoing GC.     */
792   LOCK();
793   me = GC_lookup_thread_inner(thread_id);
794   if (me == 0) {
795 #   ifdef GC_PTHREADS
796       me = GC_register_my_thread_inner(sb, thread_id);
797 #     if defined(CPPCHECK)
798         GC_noop1(me->flags);
799 #     endif
800       me -> flags |= DETACHED;
801           /* Treat as detached, since we do not need to worry about     */
802           /* pointer results.                                           */
803 #   else
804       GC_register_my_thread_inner(sb, thread_id);
805 #   endif
806     UNLOCK();
807     return GC_SUCCESS;
808   } else
809 #   ifdef GC_PTHREADS
810       /* else */ if ((me -> flags & FINISHED) != 0) {
811         GC_record_stack_base(me, sb);
812         me -> flags &= ~FINISHED; /* but not DETACHED */
813 #       ifdef THREAD_LOCAL_ALLOC
814           GC_init_thread_local((GC_tlfs)(&me->tlfs));
815 #       endif
816         UNLOCK();
817         return GC_SUCCESS;
818       } else
819 #   endif
820   /* else */ {
821     UNLOCK();
822     return GC_DUPLICATE;
823   }
824 }
825
826 /* Similar to that in pthread_support.c.        */
827 STATIC void GC_wait_for_gc_completion(GC_bool wait_for_all)
828 {
829   GC_ASSERT(I_HOLD_LOCK());
830   if (GC_incremental && GC_collection_in_progress()) {
831     word old_gc_no = GC_gc_no;
832
833     /* Make sure that no part of our stack is still on the mark stack,  */
834     /* since it's about to be unmapped.                                 */
835     do {
836       ENTER_GC();
837       GC_in_thread_creation = TRUE;
838       GC_collect_a_little_inner(1);
839       GC_in_thread_creation = FALSE;
840       EXIT_GC();
841
842       UNLOCK();
843       Sleep(0); /* yield */
844       LOCK();
845     } while (GC_incremental && GC_collection_in_progress()
846              && (wait_for_all || old_gc_no == GC_gc_no));
847   }
848 }
849
850 GC_API int GC_CALL GC_unregister_my_thread(void)
851 {
852   DCL_LOCK_STATE;
853
854 # ifdef DEBUG_THREADS
855     GC_log_printf("Unregistering thread 0x%lx\n", (long)GetCurrentThreadId());
856 # endif
857
858   if (GC_win32_dll_threads) {
859 #   if defined(THREAD_LOCAL_ALLOC)
860       /* Can't happen: see GC_use_threads_discovery(). */
861       GC_ASSERT(FALSE);
862 #   else
863       /* FIXME: Should we just ignore this? */
864       GC_delete_thread(GetCurrentThreadId());
865 #   endif
866   } else {
867 #   if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS)
868       GC_thread me;
869 #   endif
870     DWORD thread_id = GetCurrentThreadId();
871
872     LOCK();
873     GC_wait_for_gc_completion(FALSE);
874 #   if defined(THREAD_LOCAL_ALLOC) || defined(GC_PTHREADS)
875       me = GC_lookup_thread_inner(thread_id);
876       CHECK_LOOKUP_MY_THREAD(me);
877       GC_ASSERT(!KNOWN_FINISHED(me));
878 #   endif
879 #   if defined(THREAD_LOCAL_ALLOC)
880       GC_ASSERT(GC_getspecific(GC_thread_key) == &me->tlfs);
881       GC_destroy_thread_local(&(me->tlfs));
882 #   endif
883 #   ifdef GC_PTHREADS
884       if ((me -> flags & DETACHED) == 0) {
885         me -> flags |= FINISHED;
886       } else
887 #   endif
888     /* else */ {
889       GC_delete_thread(thread_id);
890     }
891 #   if defined(THREAD_LOCAL_ALLOC)
892       /* It is required to call remove_specific defined in specific.c. */
893       GC_remove_specific(GC_thread_key);
894 #   endif
895     UNLOCK();
896   }
897   return GC_SUCCESS;
898 }
899
900 /* Wrapper for functions that are likely to block for an appreciable    */
901 /* length of time.                                                      */
902
903 /* GC_do_blocking_inner() is nearly the same as in pthread_support.c    */
904 GC_INNER void GC_do_blocking_inner(ptr_t data, void * context GC_ATTR_UNUSED)
905 {
906   struct blocking_data * d = (struct blocking_data *) data;
907   DWORD thread_id = GetCurrentThreadId();
908   GC_thread me;
909 # ifdef IA64
910     ptr_t stack_ptr = GC_save_regs_in_stack();
911 # endif
912   DCL_LOCK_STATE;
913
914   LOCK();
915   me = GC_lookup_thread_inner(thread_id);
916   CHECK_LOOKUP_MY_THREAD(me);
917   GC_ASSERT(me -> thread_blocked_sp == NULL);
918 # ifdef IA64
919     me -> backing_store_ptr = stack_ptr;
920 # endif
921   me -> thread_blocked_sp = (ptr_t) &d; /* save approx. sp */
922   /* Save context here if we want to support precise stack marking */
923   UNLOCK();
924   d -> client_data = (d -> fn)(d -> client_data);
925   LOCK();   /* This will block if the world is stopped. */
926 # if defined(CPPCHECK)
927     GC_noop1((word)me->thread_blocked_sp);
928 # endif
929   me -> thread_blocked_sp = NULL;
930   UNLOCK();
931 }
932
933 /* GC_call_with_gc_active() has the opposite to GC_do_blocking()        */
934 /* functionality.  It might be called from a user function invoked by   */
935 /* GC_do_blocking() to temporarily back allow calling any GC function   */
936 /* and/or manipulating pointers to the garbage collected heap.          */
937 GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn,
938                                              void * client_data)
939 {
940   struct GC_traced_stack_sect_s stacksect;
941   DWORD thread_id = GetCurrentThreadId();
942   GC_thread me;
943   DCL_LOCK_STATE;
944
945   LOCK();   /* This will block if the world is stopped.         */
946   me = GC_lookup_thread_inner(thread_id);
947   CHECK_LOOKUP_MY_THREAD(me);
948   /* Adjust our stack bottom pointer (this could happen unless  */
949   /* GC_get_stack_base() was used which returned GC_SUCCESS).   */
950   GC_ASSERT(me -> stack_base != NULL);
951   if ((word)me->stack_base < (word)(&stacksect)) {
952     me -> stack_base = (ptr_t)(&stacksect);
953 #   if defined(I386)
954       me -> initial_stack_base = me -> stack_base;
955 #   endif
956   }
957
958   if (me -> thread_blocked_sp == NULL) {
959     /* We are not inside GC_do_blocking() - do nothing more.    */
960     UNLOCK();
961     client_data = fn(client_data);
962     /* Prevent treating the above as a tail call.       */
963     GC_noop1(COVERT_DATAFLOW(&stacksect));
964     return client_data; /* result */
965   }
966
967   /* Setup new "stack section". */
968   stacksect.saved_stack_ptr = me -> thread_blocked_sp;
969 # ifdef IA64
970     /* This is the same as in GC_call_with_stack_base().        */
971     stacksect.backing_store_end = GC_save_regs_in_stack();
972     /* Unnecessarily flushes register stack,    */
973     /* but that probably doesn't hurt.          */
974     stacksect.saved_backing_store_ptr = me -> backing_store_ptr;
975 # endif
976   stacksect.prev = me -> traced_stack_sect;
977   me -> thread_blocked_sp = NULL;
978   me -> traced_stack_sect = &stacksect;
979
980   UNLOCK();
981   client_data = fn(client_data);
982   GC_ASSERT(me -> thread_blocked_sp == NULL);
983   GC_ASSERT(me -> traced_stack_sect == &stacksect);
984
985   /* Restore original "stack section".  */
986   LOCK();
987 # if defined(CPPCHECK)
988     GC_noop1((word)me->traced_stack_sect);
989 # endif
990   me -> traced_stack_sect = stacksect.prev;
991 # ifdef IA64
992     me -> backing_store_ptr = stacksect.saved_backing_store_ptr;
993 # endif
994   me -> thread_blocked_sp = stacksect.saved_stack_ptr;
995   UNLOCK();
996
997   return client_data; /* result */
998 }
999
1000 GC_API void GC_CALL GC_set_stackbottom(void *gc_thread_handle,
1001                                        const struct GC_stack_base *sb)
1002 {
1003   GC_thread t = (GC_thread)gc_thread_handle;
1004
1005   GC_ASSERT(sb -> mem_base != NULL);
1006   if (!EXPECT(GC_is_initialized, TRUE)) {
1007     GC_ASSERT(NULL == t);
1008     GC_stackbottom = (char *)sb->mem_base;
1009 #   ifdef IA64
1010       GC_register_stackbottom = (ptr_t)sb->reg_base;
1011 #   endif
1012     return;
1013   }
1014
1015   GC_ASSERT(I_HOLD_LOCK());
1016   if (NULL == t) { /* current thread? */
1017     t = GC_lookup_thread_inner(GetCurrentThreadId());
1018     CHECK_LOOKUP_MY_THREAD(t);
1019   }
1020   GC_ASSERT(!KNOWN_FINISHED(t));
1021   GC_ASSERT(NULL == t -> thread_blocked_sp
1022             && NULL == t -> traced_stack_sect); /* for now */
1023   t -> stack_base = (ptr_t)sb->mem_base;
1024   t -> last_stack_min = ADDR_LIMIT; /* reset the known minimum */
1025 # ifdef IA64
1026     t -> backing_store_end = (ptr_t)sb->reg_base;
1027 # endif
1028 }
1029
1030 GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *sb)
1031 {
1032   DWORD thread_id = GetCurrentThreadId();
1033   GC_thread me;
1034   DCL_LOCK_STATE;
1035
1036   LOCK();
1037   me = GC_lookup_thread_inner(thread_id);
1038   CHECK_LOOKUP_MY_THREAD(me); /* the thread is assumed to be registered */
1039   sb -> mem_base = me -> stack_base;
1040 # ifdef IA64
1041     sb -> reg_base = me -> backing_store_end;
1042 # endif
1043   UNLOCK();
1044   return (void *)me; /* gc_thread_handle */
1045 }
1046
1047 #ifdef GC_PTHREADS
1048
1049   /* A quick-and-dirty cache of the mapping between pthread_t   */
1050   /* and win32 thread id.                                       */
1051 # define PTHREAD_MAP_SIZE 512
1052   DWORD GC_pthread_map_cache[PTHREAD_MAP_SIZE] = {0};
1053 # define PTHREAD_MAP_INDEX(pthread_id) \
1054                 ((NUMERIC_THREAD_ID(pthread_id) >> 5) % PTHREAD_MAP_SIZE)
1055         /* It appears pthread_t is really a pointer type ... */
1056 # define SET_PTHREAD_MAP_CACHE(pthread_id, win32_id) \
1057       (void)(GC_pthread_map_cache[PTHREAD_MAP_INDEX(pthread_id)] = (win32_id))
1058 # define GET_PTHREAD_MAP_CACHE(pthread_id) \
1059           GC_pthread_map_cache[PTHREAD_MAP_INDEX(pthread_id)]
1060
1061   /* Return a GC_thread corresponding to a given pthread_t.     */
1062   /* Returns 0 if it's not there.                               */
1063   /* We assume that this is only called for pthread ids that    */
1064   /* have not yet terminated or are still joinable, and         */
1065   /* cannot be concurrently terminated.                         */
1066   /* Assumes we do NOT hold the allocation lock.                */
1067   STATIC GC_thread GC_lookup_pthread(pthread_t id)
1068   {
1069 #   ifndef GC_NO_THREADS_DISCOVERY
1070       if (GC_win32_dll_threads) {
1071         int i;
1072         LONG my_max = GC_get_max_thread_index();
1073
1074         for (i = 0; i <= my_max &&
1075                     (!AO_load_acquire(&dll_thread_table[i].tm.in_use)
1076                     || THREAD_EQUAL(dll_thread_table[i].pthread_id, id));
1077                     /* Must still be in_use, since nobody else can      */
1078                     /* store our thread_id.                             */
1079              i++) {
1080           /* empty */
1081         }
1082         return i <= my_max ? (GC_thread)(dll_thread_table + i) : NULL;
1083       } else
1084 #   endif
1085     /* else */ {
1086       /* We first try the cache.  If that fails, we use a very slow     */
1087       /* approach.                                                      */
1088       DWORD win32_id = GET_PTHREAD_MAP_CACHE(id);
1089       int hv_guess = THREAD_TABLE_INDEX(win32_id);
1090       int hv;
1091       GC_thread p;
1092       DCL_LOCK_STATE;
1093
1094       LOCK();
1095       for (p = GC_threads[hv_guess]; 0 != p; p = p -> tm.next) {
1096         if (THREAD_EQUAL(p -> pthread_id, id))
1097           goto foundit;
1098       }
1099       for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
1100         for (p = GC_threads[hv]; 0 != p; p = p -> tm.next) {
1101           if (THREAD_EQUAL(p -> pthread_id, id))
1102             goto foundit;
1103         }
1104       }
1105       p = 0;
1106      foundit:
1107       UNLOCK();
1108       return p;
1109     }
1110   }
1111
1112 #endif /* GC_PTHREADS */
1113
1114 #ifdef CAN_HANDLE_FORK
1115     /* Similar to that in pthread_support.c but also rehashes the table */
1116     /* since hash map key (thread_id) differs from that in the parent.  */
1117     STATIC void GC_remove_all_threads_but_me(void)
1118     {
1119       int hv;
1120       GC_thread me = NULL;
1121       DWORD thread_id;
1122       pthread_t pthread_id = pthread_self(); /* same as in parent */
1123
1124       GC_ASSERT(!GC_win32_dll_threads);
1125       for (hv = 0; hv < THREAD_TABLE_SZ; ++hv) {
1126         GC_thread p, next;
1127
1128         for (p = GC_threads[hv]; 0 != p; p = next) {
1129           next = p -> tm.next;
1130           if (THREAD_EQUAL(p -> pthread_id, pthread_id)
1131               && me == NULL) { /* ignore dead threads with the same id */
1132             me = p;
1133             p -> tm.next = 0;
1134           } else {
1135 #           ifdef THREAD_LOCAL_ALLOC
1136               if ((p -> flags & FINISHED) == 0) {
1137                 /* Cannot call GC_destroy_thread_local here (see the    */
1138                 /* corresponding comment in pthread_support.c).         */
1139                 GC_remove_specific_after_fork(GC_thread_key, p -> pthread_id);
1140               }
1141 #           endif
1142             if (&first_thread != p)
1143               GC_INTERNAL_FREE(p);
1144           }
1145         }
1146         GC_threads[hv] = NULL;
1147       }
1148
1149       /* Put "me" back to GC_threads.   */
1150       GC_ASSERT(me != NULL);
1151       thread_id = GetCurrentThreadId(); /* differs from that in parent */
1152       GC_threads[THREAD_TABLE_INDEX(thread_id)] = me;
1153
1154       /* Update Win32 thread Id and handle.     */
1155       me -> id = thread_id;
1156 #     ifndef MSWINCE
1157         if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
1158                         GetCurrentProcess(), (HANDLE *)&me->handle,
1159                         0 /* dwDesiredAccess */, FALSE /* bInheritHandle */,
1160                         DUPLICATE_SAME_ACCESS))
1161           ABORT("DuplicateHandle failed");
1162 #     endif
1163
1164 #     if defined(THREAD_LOCAL_ALLOC) && !defined(USE_CUSTOM_SPECIFIC)
1165         /* For Cygwin, we need to re-assign thread-local pointer to     */
1166         /* 'tlfs' (it is OK to call GC_destroy_thread_local and         */
1167         /* GC_free_internal before this action).                        */
1168         if (GC_setspecific(GC_thread_key, &me->tlfs) != 0)
1169           ABORT("GC_setspecific failed (in child)");
1170 #     endif
1171     }
1172
1173     static void fork_prepare_proc(void)
1174     {
1175       LOCK();
1176 #     ifdef PARALLEL_MARK
1177         if (GC_parallel)
1178           GC_wait_for_reclaim();
1179 #     endif
1180       GC_wait_for_gc_completion(TRUE);
1181 #     ifdef PARALLEL_MARK
1182         if (GC_parallel)
1183           GC_acquire_mark_lock();
1184 #     endif
1185     }
1186
1187     static void fork_parent_proc(void)
1188     {
1189 #     ifdef PARALLEL_MARK
1190         if (GC_parallel)
1191           GC_release_mark_lock();
1192 #     endif
1193       UNLOCK();
1194     }
1195
1196     static void fork_child_proc(void)
1197     {
1198 #     ifdef PARALLEL_MARK
1199         if (GC_parallel) {
1200           GC_release_mark_lock();
1201           GC_parallel = FALSE; /* or GC_markers_m1 = 0 */
1202                 /* Turn off parallel marking in the child, since we are */
1203                 /* probably just going to exec, and we would have to    */
1204                 /* restart mark threads.                                */
1205         }
1206 #     endif
1207       GC_remove_all_threads_but_me();
1208       UNLOCK();
1209     }
1210
1211   /* Routines for fork handling by client (no-op if pthread_atfork works). */
1212   GC_API void GC_CALL GC_atfork_prepare(void)
1213   {
1214     if (!EXPECT(GC_is_initialized, TRUE)) GC_init();
1215     if (GC_handle_fork <= 0)
1216       fork_prepare_proc();
1217   }
1218
1219   GC_API void GC_CALL GC_atfork_parent(void)
1220   {
1221     if (GC_handle_fork <= 0)
1222       fork_parent_proc();
1223   }
1224
1225   GC_API void GC_CALL GC_atfork_child(void)
1226   {
1227     if (GC_handle_fork <= 0)
1228       fork_child_proc();
1229   }
1230 #endif /* CAN_HANDLE_FORK */
1231
1232 void GC_push_thread_structures(void)
1233 {
1234   GC_ASSERT(I_HOLD_LOCK());
1235 # ifndef GC_NO_THREADS_DISCOVERY
1236     if (GC_win32_dll_threads) {
1237       /* Unlike the other threads implementations, the thread table     */
1238       /* here contains no pointers to the collectible heap (note also   */
1239       /* that GC_PTHREADS is incompatible with DllMain-based thread     */
1240       /* registration).  Thus we have no private structures we need     */
1241       /* to preserve.                                                   */
1242     } else
1243 # endif
1244   /* else */ {
1245     GC_PUSH_ALL_SYM(GC_threads);
1246   }
1247 # if defined(THREAD_LOCAL_ALLOC)
1248     GC_PUSH_ALL_SYM(GC_thread_key);
1249     /* Just in case we ever use our own TLS implementation.     */
1250 # endif
1251 }
1252
1253 #ifdef WOW64_THREAD_CONTEXT_WORKAROUND
1254 # ifndef CONTEXT_EXCEPTION_ACTIVE
1255 #   define CONTEXT_EXCEPTION_ACTIVE    0x08000000
1256 #   define CONTEXT_EXCEPTION_REQUEST   0x40000000
1257 #   define CONTEXT_EXCEPTION_REPORTING 0x80000000
1258 # endif
1259   static BOOL isWow64;  /* Is running 32-bit code on Win64?     */
1260 # define GET_THREAD_CONTEXT_FLAGS (isWow64 \
1261                         ? CONTEXT_INTEGER | CONTEXT_CONTROL \
1262                           | CONTEXT_EXCEPTION_REQUEST | CONTEXT_SEGMENTS \
1263                         : CONTEXT_INTEGER | CONTEXT_CONTROL)
1264 #else
1265 # define GET_THREAD_CONTEXT_FLAGS (CONTEXT_INTEGER | CONTEXT_CONTROL)
1266 #endif /* !WOW64_THREAD_CONTEXT_WORKAROUND */
1267
1268 /* Suspend the given thread, if it's still active.      */
1269 STATIC void GC_suspend(GC_thread t)
1270 {
1271 # ifndef MSWINCE
1272     /* Apparently the Windows 95 GetOpenFileName call creates           */
1273     /* a thread that does not properly get cleaned up, and              */
1274     /* SuspendThread on its descriptor may provoke a crash.             */
1275     /* This reduces the probability of that event, though it still      */
1276     /* appears there's a race here.                                     */
1277     DWORD exitCode;
1278 # endif
1279 # ifdef RETRY_GET_THREAD_CONTEXT
1280     int retry_cnt = 0;
1281 #   define MAX_SUSPEND_THREAD_RETRIES (1000 * 1000)
1282 # endif
1283   UNPROTECT_THREAD(t);
1284 # ifndef MSWINCE
1285     if (GetExitCodeThread(t -> handle, &exitCode) &&
1286         exitCode != STILL_ACTIVE) {
1287 #     ifdef GC_PTHREADS
1288         t -> stack_base = 0; /* prevent stack from being pushed */
1289 #     else
1290         /* this breaks pthread_join on Cygwin, which is guaranteed to  */
1291         /* only see user pthreads                                      */
1292         GC_ASSERT(GC_win32_dll_threads);
1293         GC_delete_gc_thread_no_free(t);
1294 #     endif
1295       return;
1296     }
1297 # endif
1298   GC_acquire_dirty_lock();
1299 # ifdef MSWINCE
1300     /* SuspendThread() will fail if thread is running kernel code.      */
1301     while (SuspendThread(THREAD_HANDLE(t)) == (DWORD)-1)
1302       Sleep(10); /* in millis */
1303 # elif defined(RETRY_GET_THREAD_CONTEXT)
1304     for (;;) {
1305       if (SuspendThread(t->handle) != (DWORD)-1) {
1306         CONTEXT context;
1307
1308         context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;
1309         if (GetThreadContext(t->handle, &context)) {
1310           /* TODO: WoW64 extra workaround: if CONTEXT_EXCEPTION_ACTIVE  */
1311           /* then Sleep(1) and retry.                                   */
1312           t->context_sp = copy_ptr_regs(t->context_regs, &context);
1313           break; /* success; the context pointer registers are saved */
1314         }
1315
1316         /* Resume the thread, try to suspend it in a better location.   */
1317         if (ResumeThread(t->handle) == (DWORD)-1)
1318           ABORT("ResumeThread failed");
1319       }
1320       if (retry_cnt > 1)
1321         Sleep(0); /* yield */
1322       if (++retry_cnt >= MAX_SUSPEND_THREAD_RETRIES)
1323         ABORT("SuspendThread loop failed"); /* something must be wrong */
1324     }
1325 # else
1326     if (SuspendThread(t -> handle) == (DWORD)-1)
1327       ABORT("SuspendThread failed");
1328 # endif
1329   t -> suspended = (unsigned char)TRUE;
1330   GC_release_dirty_lock();
1331   if (GC_on_thread_event)
1332     GC_on_thread_event(GC_EVENT_THREAD_SUSPENDED, THREAD_HANDLE(t));
1333 }
1334
1335 #if defined(GC_ASSERTIONS) \
1336     && ((defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE))
1337   GC_INNER GC_bool GC_write_disabled = FALSE;
1338                 /* TRUE only if GC_stop_world() acquired GC_write_cs.   */
1339 #endif
1340
1341 GC_INNER void GC_stop_world(void)
1342 {
1343   DWORD thread_id = GetCurrentThreadId();
1344
1345   if (!GC_thr_initialized)
1346     ABORT("GC_stop_world() called before GC_thr_init()");
1347   GC_ASSERT(I_HOLD_LOCK());
1348
1349   /* This code is the same as in pthread_stop_world.c */
1350 # ifdef PARALLEL_MARK
1351     if (GC_parallel) {
1352       GC_acquire_mark_lock();
1353       GC_ASSERT(GC_fl_builder_count == 0);
1354       /* We should have previously waited for it to become zero. */
1355     }
1356 # endif /* PARALLEL_MARK */
1357
1358 # if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)
1359     GC_please_stop = TRUE;
1360 # endif
1361 # if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)
1362     GC_ASSERT(!GC_write_disabled);
1363     EnterCriticalSection(&GC_write_cs);
1364     /* It's not allowed to call GC_printf() (and friends) here down to  */
1365     /* LeaveCriticalSection (same applies recursively to GC_suspend,    */
1366     /* GC_delete_gc_thread_no_free, GC_get_max_thread_index, GC_size    */
1367     /* and GC_remove_protection).                                       */
1368 #   ifdef GC_ASSERTIONS
1369       GC_write_disabled = TRUE;
1370 #   endif
1371 # endif
1372 # ifndef GC_NO_THREADS_DISCOVERY
1373     if (GC_win32_dll_threads) {
1374       int i;
1375       int my_max;
1376       /* Any threads being created during this loop will end up setting */
1377       /* GC_attached_thread when they start.  This will force marking   */
1378       /* to restart.  This is not ideal, but hopefully correct.         */
1379       AO_store(&GC_attached_thread, FALSE);
1380       my_max = (int)GC_get_max_thread_index();
1381       for (i = 0; i <= my_max; i++) {
1382         GC_vthread t = dll_thread_table + i;
1383         if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
1384             && t -> id != thread_id) {
1385           GC_suspend((GC_thread)t);
1386         }
1387       }
1388     } else
1389 # endif
1390   /* else */ {
1391     GC_thread t;
1392     int i;
1393
1394     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1395       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1396         if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
1397             && !KNOWN_FINISHED(t) && t -> id != thread_id) {
1398           GC_suspend(t);
1399         }
1400       }
1401     }
1402   }
1403 # if (defined(MSWIN32) && !defined(CONSOLE_LOG)) || defined(MSWINCE)
1404 #   ifdef GC_ASSERTIONS
1405       GC_write_disabled = FALSE;
1406 #   endif
1407     LeaveCriticalSection(&GC_write_cs);
1408 # endif
1409 # ifdef PARALLEL_MARK
1410     if (GC_parallel)
1411       GC_release_mark_lock();
1412 # endif
1413 }
1414
1415 GC_INNER void GC_start_world(void)
1416 {
1417 # ifdef GC_ASSERTIONS
1418     DWORD thread_id = GetCurrentThreadId();
1419 # endif
1420
1421   GC_ASSERT(I_HOLD_LOCK());
1422   if (GC_win32_dll_threads) {
1423     LONG my_max = GC_get_max_thread_index();
1424     int i;
1425
1426     for (i = 0; i <= my_max; i++) {
1427       GC_thread t = (GC_thread)(dll_thread_table + i);
1428       if (t -> suspended) {
1429         GC_ASSERT(t -> stack_base != 0 && t -> id != thread_id);
1430         if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1)
1431           ABORT("ResumeThread failed");
1432         t -> suspended = FALSE;
1433         if (GC_on_thread_event)
1434           GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t));
1435       }
1436     }
1437   } else {
1438     GC_thread t;
1439     int i;
1440
1441     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1442       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1443         if (t -> suspended) {
1444           GC_ASSERT(t -> stack_base != 0 && t -> id != thread_id);
1445           if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1)
1446             ABORT("ResumeThread failed");
1447           UNPROTECT_THREAD(t);
1448           t -> suspended = FALSE;
1449           if (GC_on_thread_event)
1450             GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t));
1451         }
1452       }
1453     }
1454   }
1455 # if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)
1456     GC_please_stop = FALSE;
1457 # endif
1458 }
1459
1460 #ifdef MSWINCE
1461   /* The VirtualQuery calls below won't work properly on some old WinCE */
1462   /* versions, but since each stack is restricted to an aligned 64 KiB  */
1463   /* region of virtual memory we can just take the next lowest multiple */
1464   /* of 64 KiB.  The result of this macro must not be used as its       */
1465   /* argument later and must not be used as the lower bound for sp      */
1466   /* check (since the stack may be bigger than 64 KiB).                 */
1467 # define GC_wince_evaluate_stack_min(s) \
1468                         (ptr_t)(((word)(s) - 1) & ~(word)0xFFFF)
1469 #elif defined(GC_ASSERTIONS)
1470 # define GC_dont_query_stack_min FALSE
1471 #endif
1472
1473 /* A cache holding the results of the recent VirtualQuery call. */
1474 /* Protected by the allocation lock.                            */
1475 static ptr_t last_address = 0;
1476 static MEMORY_BASIC_INFORMATION last_info;
1477
1478 /* Probe stack memory region (starting at "s") to find out its  */
1479 /* lowest address (i.e. stack top).                             */
1480 /* S must be a mapped address inside the region, NOT the first  */
1481 /* unmapped address.                                            */
1482 STATIC ptr_t GC_get_stack_min(ptr_t s)
1483 {
1484   ptr_t bottom;
1485
1486   GC_ASSERT(I_HOLD_LOCK());
1487   if (s != last_address) {
1488     VirtualQuery(s, &last_info, sizeof(last_info));
1489     last_address = s;
1490   }
1491   do {
1492     bottom = (ptr_t)last_info.BaseAddress;
1493     VirtualQuery(bottom - 1, &last_info, sizeof(last_info));
1494     last_address = bottom - 1;
1495   } while ((last_info.Protect & PAGE_READWRITE)
1496            && !(last_info.Protect & PAGE_GUARD));
1497   return(bottom);
1498 }
1499
1500 /* Return true if the page at s has protections appropriate     */
1501 /* for a stack page.                                            */
1502 static GC_bool may_be_in_stack(ptr_t s)
1503 {
1504   GC_ASSERT(I_HOLD_LOCK());
1505   if (s != last_address) {
1506     VirtualQuery(s, &last_info, sizeof(last_info));
1507     last_address = s;
1508   }
1509   return (last_info.Protect & PAGE_READWRITE)
1510           && !(last_info.Protect & PAGE_GUARD);
1511 }
1512
1513 /* Copy all registers that might point into the heap.  Frame    */
1514 /* pointer registers are included in case client code was       */
1515 /* compiled with the 'omit frame pointer' optimization.         */
1516 /* The context register values are stored to regs argument      */
1517 /* which is expected to be of PUSHED_REGS_COUNT length exactly. */
1518 /* The functions returns the context stack pointer value.       */
1519 static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext) {
1520     ptr_t sp;
1521     int cnt = 0;
1522 #   define context (*pcontext)
1523 #   define PUSH1(reg) (regs[cnt++] = (word)pcontext->reg)
1524 #   define PUSH2(r1,r2) (PUSH1(r1), PUSH1(r2))
1525 #   define PUSH4(r1,r2,r3,r4) (PUSH2(r1,r2), PUSH2(r3,r4))
1526 #   if defined(I386)
1527 #     ifdef WOW64_THREAD_CONTEXT_WORKAROUND
1528         PUSH2(ContextFlags, SegFs); /* cannot contain pointers */
1529 #     endif
1530       PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);
1531       sp = (ptr_t)context.Esp;
1532 #   elif defined(X86_64)
1533       PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi);
1534       PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15);
1535       sp = (ptr_t)context.Rsp;
1536 #   elif defined(ARM32)
1537       PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11);
1538       PUSH1(R12);
1539       sp = (ptr_t)context.Sp;
1540 #   elif defined(AARCH64)
1541       PUSH4(X0,X1,X2,X3),PUSH4(X4,X5,X6,X7),PUSH4(X8,X9,X10,X11);
1542       PUSH4(X12,X13,X14,X15),PUSH4(X16,X17,X18,X19),PUSH4(X20,X21,X22,X23);
1543       PUSH4(X24,X25,X26,X27),PUSH1(X28);
1544       PUSH1(Lr);
1545       sp = (ptr_t)context.Sp;
1546 #   elif defined(SHx)
1547       PUSH4(R0,R1,R2,R3), PUSH4(R4,R5,R6,R7), PUSH4(R8,R9,R10,R11);
1548       PUSH2(R12,R13), PUSH1(R14);
1549       sp = (ptr_t)context.R15;
1550 #   elif defined(MIPS)
1551       PUSH4(IntAt,IntV0,IntV1,IntA0), PUSH4(IntA1,IntA2,IntA3,IntT0);
1552       PUSH4(IntT1,IntT2,IntT3,IntT4), PUSH4(IntT5,IntT6,IntT7,IntS0);
1553       PUSH4(IntS1,IntS2,IntS3,IntS4), PUSH4(IntS5,IntS6,IntS7,IntT8);
1554       PUSH4(IntT9,IntK0,IntK1,IntS8);
1555       sp = (ptr_t)context.IntSp;
1556 #   elif defined(PPC)
1557       PUSH4(Gpr0, Gpr3, Gpr4, Gpr5),  PUSH4(Gpr6, Gpr7, Gpr8, Gpr9);
1558       PUSH4(Gpr10,Gpr11,Gpr12,Gpr14), PUSH4(Gpr15,Gpr16,Gpr17,Gpr18);
1559       PUSH4(Gpr19,Gpr20,Gpr21,Gpr22), PUSH4(Gpr23,Gpr24,Gpr25,Gpr26);
1560       PUSH4(Gpr27,Gpr28,Gpr29,Gpr30), PUSH1(Gpr31);
1561       sp = (ptr_t)context.Gpr1;
1562 #   elif defined(ALPHA)
1563       PUSH4(IntV0,IntT0,IntT1,IntT2), PUSH4(IntT3,IntT4,IntT5,IntT6);
1564       PUSH4(IntT7,IntS0,IntS1,IntS2), PUSH4(IntS3,IntS4,IntS5,IntFp);
1565       PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9);
1566       PUSH4(IntT10,IntT11,IntT12,IntAt);
1567       sp = (ptr_t)context.IntSp;
1568 #   elif defined(CPPCHECK)
1569       sp = (ptr_t)(word)cnt; /* to workaround "cnt not used" false positive */
1570 #   else
1571 #     error Architecture is not supported
1572 #   endif
1573 #   undef context
1574     GC_ASSERT(cnt == PUSHED_REGS_COUNT);
1575     return sp;
1576 }
1577
1578 STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
1579 {
1580   ptr_t sp, stack_min;
1581
1582   struct GC_traced_stack_sect_s *traced_stack_sect =
1583                                       thread -> traced_stack_sect;
1584   if (thread -> id == me) {
1585     GC_ASSERT(thread -> thread_blocked_sp == NULL);
1586     sp = GC_approx_sp();
1587   } else if ((sp = thread -> thread_blocked_sp) == NULL) {
1588               /* Use saved sp value for blocked threads. */
1589 #   ifdef RETRY_GET_THREAD_CONTEXT
1590       /* We cache context when suspending the thread since it may       */
1591       /* require looping.                                               */
1592       word *regs = thread->context_regs;
1593
1594       sp = thread->context_sp;
1595 #   else
1596       /* For unblocked threads call GetThreadContext(). */
1597       word regs[PUSHED_REGS_COUNT];
1598       {
1599         CONTEXT context;
1600
1601         context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;
1602         if (!GetThreadContext(THREAD_HANDLE(thread), &context))
1603           ABORT("GetThreadContext failed");
1604         sp = copy_ptr_regs(regs, &context);
1605       }
1606 #   endif
1607
1608 #   ifndef WOW64_THREAD_CONTEXT_WORKAROUND
1609       GC_push_many_regs(regs, PUSHED_REGS_COUNT);
1610 #   else
1611       GC_push_many_regs(regs + 2, PUSHED_REGS_COUNT - 2);
1612                                         /* skip ContextFlags and SegFs */
1613
1614       /* WoW64 workaround. */
1615       if (isWow64) {
1616         DWORD ContextFlags = (DWORD)regs[0];
1617         WORD SegFs = (WORD)regs[1];
1618
1619         if ((ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0
1620             && (ContextFlags & (CONTEXT_EXCEPTION_ACTIVE
1621                                 /* | CONTEXT_SERVICE_ACTIVE */)) != 0) {
1622           LDT_ENTRY selector;
1623           PNT_TIB tib;
1624
1625           if (!GetThreadSelectorEntry(THREAD_HANDLE(thread), SegFs, &selector))
1626             ABORT("GetThreadSelectorEntry failed");
1627           tib = (PNT_TIB)(selector.BaseLow
1628                           | (selector.HighWord.Bits.BaseMid << 16)
1629                           | (selector.HighWord.Bits.BaseHi << 24));
1630 #         ifdef DEBUG_THREADS
1631             GC_log_printf("TIB stack limit/base: %p .. %p\n",
1632                           (void *)tib->StackLimit, (void *)tib->StackBase);
1633 #         endif
1634           GC_ASSERT(!((word)thread->stack_base
1635                       COOLER_THAN (word)tib->StackBase));
1636           if (thread->stack_base != thread->initial_stack_base
1637               /* We are in a coroutine. */
1638               && ((word)thread->stack_base <= (word)tib->StackLimit
1639                   || (word)tib->StackBase < (word)thread->stack_base)) {
1640             /* The coroutine stack is not within TIB stack.   */
1641             WARN("GetThreadContext might return stale register values"
1642                  " including ESP=%p\n", sp);
1643             /* TODO: Because of WoW64 bug, there is no guarantee that   */
1644             /* sp really points to the stack top but, for now, we do    */
1645             /* our best as the TIB stack limit/base cannot be used      */
1646             /* while we are inside a coroutine.                         */
1647           } else {
1648             /* GetThreadContext() might return stale register values,   */
1649             /* so we scan the entire stack region (down to the stack    */
1650             /* limit).  There is no 100% guarantee that all the         */
1651             /* registers are pushed but we do our best (the proper      */
1652             /* solution would be to fix it inside Windows OS).          */
1653             sp = (ptr_t)tib->StackLimit;
1654           }
1655         } /* else */
1656 #       ifdef DEBUG_THREADS
1657           else {
1658             static GC_bool logged;
1659             if (!logged
1660                 && (ContextFlags & CONTEXT_EXCEPTION_REPORTING) == 0) {
1661               GC_log_printf("CONTEXT_EXCEPTION_REQUEST not supported\n");
1662               logged = TRUE;
1663             }
1664           }
1665 #       endif
1666       }
1667 #   endif /* WOW64_THREAD_CONTEXT_WORKAROUND */
1668   } /* ! current thread */
1669
1670   /* Set stack_min to the lowest address in the thread stack,   */
1671   /* or to an address in the thread stack no larger than sp,    */
1672   /* taking advantage of the old value to avoid slow traversals */
1673   /* of large stacks.                                           */
1674   if (thread -> last_stack_min == ADDR_LIMIT) {
1675 #   ifdef MSWINCE
1676       if (GC_dont_query_stack_min) {
1677         stack_min = GC_wince_evaluate_stack_min(traced_stack_sect != NULL ?
1678                       (ptr_t)traced_stack_sect : thread -> stack_base);
1679         /* Keep last_stack_min value unmodified. */
1680       } else
1681 #   endif
1682     /* else */ {
1683       stack_min = GC_get_stack_min(traced_stack_sect != NULL ?
1684                       (ptr_t)traced_stack_sect : thread -> stack_base);
1685       UNPROTECT_THREAD(thread);
1686       thread -> last_stack_min = stack_min;
1687     }
1688   } else {
1689     /* First, adjust the latest known minimum stack address if we       */
1690     /* are inside GC_call_with_gc_active().                             */
1691     if (traced_stack_sect != NULL &&
1692         (word)thread->last_stack_min > (word)traced_stack_sect) {
1693       UNPROTECT_THREAD(thread);
1694       thread -> last_stack_min = (ptr_t)traced_stack_sect;
1695     }
1696
1697     if ((word)sp < (word)thread->stack_base
1698         && (word)sp >= (word)thread->last_stack_min) {
1699       stack_min = sp;
1700     } else {
1701       /* In the current thread it is always safe to use sp value.       */
1702       if (may_be_in_stack(thread -> id == me &&
1703                           (word)sp < (word)thread->last_stack_min ?
1704                           sp : thread -> last_stack_min)) {
1705         stack_min = (ptr_t)last_info.BaseAddress;
1706         /* Do not probe rest of the stack if sp is correct. */
1707         if ((word)sp < (word)stack_min
1708             || (word)sp >= (word)thread->stack_base)
1709           stack_min = GC_get_stack_min(thread -> last_stack_min);
1710       } else {
1711         /* Stack shrunk?  Is this possible? */
1712         stack_min = GC_get_stack_min(thread -> stack_base);
1713       }
1714       UNPROTECT_THREAD(thread);
1715       thread -> last_stack_min = stack_min;
1716     }
1717   }
1718
1719   GC_ASSERT(GC_dont_query_stack_min
1720             || stack_min == GC_get_stack_min(thread -> stack_base)
1721             || ((word)sp >= (word)stack_min
1722                 && (word)stack_min < (word)thread->stack_base
1723                 && (word)stack_min
1724                         > (word)GC_get_stack_min(thread -> stack_base)));
1725
1726   if ((word)sp >= (word)stack_min && (word)sp < (word)thread->stack_base) {
1727 #   ifdef DEBUG_THREADS
1728       GC_log_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n",
1729                     (int)thread->id, (void *)sp, (void *)thread->stack_base,
1730                     (int)me);
1731 #   endif
1732     GC_push_all_stack_sections(sp, thread->stack_base, traced_stack_sect);
1733   } else {
1734     /* If not current thread then it is possible for sp to point to     */
1735     /* the guarded (untouched yet) page just below the current          */
1736     /* stack_min of the thread.                                         */
1737     if (thread -> id == me || (word)sp >= (word)thread->stack_base
1738         || (word)(sp + GC_page_size) < (word)stack_min)
1739       WARN("Thread stack pointer %p out of range, pushing everything\n",
1740            sp);
1741 #   ifdef DEBUG_THREADS
1742       GC_log_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n",
1743                     (int)thread->id, (void *)stack_min,
1744                     (void *)thread->stack_base, (int)me);
1745 #   endif
1746     /* Push everything - ignore "traced stack section" data.            */
1747     GC_push_all_stack(stack_min, thread->stack_base);
1748   }
1749   return thread->stack_base - sp; /* stack grows down */
1750 }
1751
1752 GC_INNER void GC_push_all_stacks(void)
1753 {
1754   DWORD thread_id = GetCurrentThreadId();
1755   GC_bool found_me = FALSE;
1756 # ifndef SMALL_CONFIG
1757     unsigned nthreads = 0;
1758 # endif
1759   word total_size = 0;
1760 # ifndef GC_NO_THREADS_DISCOVERY
1761     if (GC_win32_dll_threads) {
1762       int i;
1763       LONG my_max = GC_get_max_thread_index();
1764
1765       for (i = 0; i <= my_max; i++) {
1766         GC_thread t = (GC_thread)(dll_thread_table + i);
1767         if (t -> tm.in_use && t -> stack_base) {
1768 #         ifndef SMALL_CONFIG
1769             ++nthreads;
1770 #         endif
1771           total_size += GC_push_stack_for(t, thread_id);
1772           if (t -> id == thread_id) found_me = TRUE;
1773         }
1774       }
1775     } else
1776 # endif
1777   /* else */ {
1778     int i;
1779     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1780       GC_thread t;
1781       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1782         if (!KNOWN_FINISHED(t) && t -> stack_base) {
1783 #         ifndef SMALL_CONFIG
1784             ++nthreads;
1785 #         endif
1786           total_size += GC_push_stack_for(t, thread_id);
1787           if (t -> id == thread_id) found_me = TRUE;
1788         }
1789       }
1790     }
1791   }
1792 # ifndef SMALL_CONFIG
1793     GC_VERBOSE_LOG_PRINTF("Pushed %d thread stacks%s\n", nthreads,
1794                           GC_win32_dll_threads ?
1795                                 " based on DllMain thread tracking" : "");
1796 # endif
1797   if (!found_me && !GC_in_thread_creation)
1798     ABORT("Collecting from unknown thread");
1799   GC_total_stacksize = total_size;
1800 }
1801
1802 #ifdef PARALLEL_MARK
1803
1804 # ifndef MAX_MARKERS
1805 #   define MAX_MARKERS 16
1806 # endif
1807
1808   static ptr_t marker_sp[MAX_MARKERS - 1]; /* The cold end of the stack */
1809                                            /* for markers.              */
1810 # ifdef IA64
1811     static ptr_t marker_bsp[MAX_MARKERS - 1];
1812 # endif
1813
1814   static ptr_t marker_last_stack_min[MAX_MARKERS - 1];
1815                                 /* Last known minimum (hottest) address */
1816                                 /* in stack (or ADDR_LIMIT if unset)    */
1817                                 /* for markers.                         */
1818
1819 #endif /* PARALLEL_MARK */
1820
1821 /* Find stack with the lowest address which overlaps the        */
1822 /* interval [start, limit).                                     */
1823 /* Return stack bounds in *lo and *hi.  If no such stack        */
1824 /* is found, both *hi and *lo will be set to an address         */
1825 /* higher than limit.                                           */
1826 GC_INNER void GC_get_next_stack(char *start, char *limit,
1827                                 char **lo, char **hi)
1828 {
1829   int i;
1830   char * current_min = ADDR_LIMIT;  /* Least in-range stack base      */
1831   ptr_t *plast_stack_min = NULL;    /* Address of last_stack_min      */
1832                                     /* field for thread corresponding */
1833                                     /* to current_min.                */
1834   GC_thread thread = NULL;          /* Either NULL or points to the   */
1835                                     /* thread's hash table entry      */
1836                                     /* containing *plast_stack_min.   */
1837
1838   /* First set current_min, ignoring limit. */
1839   if (GC_win32_dll_threads) {
1840     LONG my_max = GC_get_max_thread_index();
1841
1842     for (i = 0; i <= my_max; i++) {
1843       ptr_t s = (ptr_t)(dll_thread_table[i].stack_base);
1844
1845       if ((word)s > (word)start && (word)s < (word)current_min) {
1846         /* Update address of last_stack_min. */
1847         plast_stack_min = (ptr_t * /* no volatile */)
1848                             &dll_thread_table[i].last_stack_min;
1849         current_min = s;
1850 #       if defined(CPPCHECK)
1851           /* To avoid a warning that thread is always null.     */
1852           thread = (GC_thread)&dll_thread_table[i];
1853 #       endif
1854       }
1855     }
1856   } else {
1857     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1858       GC_thread t;
1859
1860       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1861         ptr_t s = t -> stack_base;
1862
1863         if ((word)s > (word)start && (word)s < (word)current_min) {
1864           /* Update address of last_stack_min. */
1865           plast_stack_min = &t -> last_stack_min;
1866           thread = t; /* Remember current thread to unprotect. */
1867           current_min = s;
1868         }
1869       }
1870     }
1871 #   ifdef PARALLEL_MARK
1872       for (i = 0; i < GC_markers_m1; ++i) {
1873         ptr_t s = marker_sp[i];
1874 #       ifdef IA64
1875           /* FIXME: not implemented */
1876 #       endif
1877         if ((word)s > (word)start && (word)s < (word)current_min) {
1878           GC_ASSERT(marker_last_stack_min[i] != NULL);
1879           plast_stack_min = &marker_last_stack_min[i];
1880           current_min = s;
1881           thread = NULL; /* Not a thread's hash table entry. */
1882         }
1883       }
1884 #   endif
1885   }
1886
1887   *hi = current_min;
1888   if (current_min == ADDR_LIMIT) {
1889       *lo = ADDR_LIMIT;
1890       return;
1891   }
1892
1893   GC_ASSERT((word)current_min > (word)start && plast_stack_min != NULL);
1894 # ifdef MSWINCE
1895     if (GC_dont_query_stack_min) {
1896       *lo = GC_wince_evaluate_stack_min(current_min);
1897       /* Keep last_stack_min value unmodified. */
1898       return;
1899     }
1900 # endif
1901
1902   if ((word)current_min > (word)limit && !may_be_in_stack(limit)) {
1903     /* Skip the rest since the memory region at limit address is        */
1904     /* not a stack (so the lowest address of the found stack would      */
1905     /* be above the limit value anyway).                                */
1906     *lo = ADDR_LIMIT;
1907     return;
1908   }
1909
1910   /* Get the minimum address of the found stack by probing its memory   */
1911   /* region starting from the recent known minimum (if set).            */
1912   if (*plast_stack_min == ADDR_LIMIT
1913       || !may_be_in_stack(*plast_stack_min)) {
1914     /* Unsafe to start from last_stack_min value. */
1915     *lo = GC_get_stack_min(current_min);
1916   } else {
1917     /* Use the recent value to optimize search for min address. */
1918     *lo = GC_get_stack_min(*plast_stack_min);
1919   }
1920
1921   /* Remember current stack_min value. */
1922   if (thread != NULL) {
1923     UNPROTECT_THREAD(thread);
1924   }
1925   *plast_stack_min = *lo;
1926 }
1927
1928 #ifdef PARALLEL_MARK
1929
1930 # if defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK)
1931     /* Use pthread-based parallel mark implementation.    */
1932
1933     /* Workaround a deadlock in winpthreads-3.0b internals (observed    */
1934     /* with MinGW 32/64).                                               */
1935 #   if !defined(__MINGW32__)
1936 #     define GC_PTHREADS_PARAMARK
1937 #   endif
1938 # endif
1939
1940 # if !defined(GC_PTHREADS_PARAMARK)
1941     STATIC HANDLE GC_marker_cv[MAX_MARKERS - 1] = {0};
1942                         /* Events with manual reset (one for each       */
1943                         /* mark helper).                                */
1944
1945     STATIC DWORD GC_marker_Id[MAX_MARKERS - 1] = {0};
1946                         /* This table is used for mapping helper        */
1947                         /* threads ID to mark helper index (linear      */
1948                         /* search is used since the mapping contains    */
1949                         /* only a few entries).                         */
1950 # endif
1951
1952   /* GC_mark_thread() is the same as in pthread_support.c */
1953 # ifdef GC_PTHREADS_PARAMARK
1954     STATIC void * GC_mark_thread(void * id)
1955 # elif defined(MSWINCE)
1956     STATIC DWORD WINAPI GC_mark_thread(LPVOID id)
1957 # else
1958     STATIC unsigned __stdcall GC_mark_thread(void * id)
1959 # endif
1960   {
1961     word my_mark_no = 0;
1962
1963     if ((word)id == GC_WORD_MAX) return 0; /* to prevent a compiler warning */
1964     marker_sp[(word)id] = GC_approx_sp();
1965 #   ifdef IA64
1966       marker_bsp[(word)id] = GC_save_regs_in_stack();
1967 #   endif
1968 #   if !defined(GC_PTHREADS_PARAMARK)
1969       GC_marker_Id[(word)id] = GetCurrentThreadId();
1970 #   endif
1971
1972     /* Inform GC_start_mark_threads about completion of marker data init. */
1973     GC_acquire_mark_lock();
1974     if (0 == --GC_fl_builder_count) /* count may have a negative value */
1975       GC_notify_all_builder();
1976
1977     for (;; ++my_mark_no) {
1978       if (my_mark_no - GC_mark_no > (word)2) {
1979         /* resynchronize if we get far off, e.g. because GC_mark_no     */
1980         /* wrapped.                                                     */
1981         my_mark_no = GC_mark_no;
1982       }
1983 #     ifdef DEBUG_THREADS
1984         GC_log_printf("Starting mark helper for mark number %lu\n",
1985                       (unsigned long)my_mark_no);
1986 #     endif
1987       GC_help_marker(my_mark_no);
1988     }
1989   }
1990
1991 # ifndef GC_ASSERTIONS
1992 #   define SET_MARK_LOCK_HOLDER (void)0
1993 #   define UNSET_MARK_LOCK_HOLDER (void)0
1994 # endif
1995
1996   /* GC_mark_threads[] is unused here unlike that in pthread_support.c  */
1997
1998 # ifdef CAN_HANDLE_FORK
1999     static int available_markers_m1 = 0;
2000 # else
2001 #   define available_markers_m1 GC_markers_m1
2002 # endif
2003
2004 # ifdef GC_PTHREADS_PARAMARK
2005 #   include <pthread.h>
2006
2007 #   if defined(GC_ASSERTIONS) && !defined(NUMERIC_THREAD_ID)
2008 #     define NUMERIC_THREAD_ID(id) (unsigned long)(word)GC_PTHREAD_PTRVAL(id)
2009       /* Id not guaranteed to be unique. */
2010 #   endif
2011
2012 #   ifdef CAN_HANDLE_FORK
2013       static pthread_cond_t mark_cv;
2014                         /* initialized by GC_start_mark_threads_inner   */
2015 #   else
2016       static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
2017 #   endif
2018
2019     /* GC_start_mark_threads is the same as in pthread_support.c except */
2020     /* for thread stack that is assumed to be large enough.             */
2021
2022     GC_INNER void GC_start_mark_threads_inner(void)
2023     {
2024       int i;
2025       pthread_attr_t attr;
2026       pthread_t new_thread;
2027 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2028         sigset_t set, oldset;
2029 #     endif
2030
2031       GC_ASSERT(I_DONT_HOLD_LOCK());
2032       if (available_markers_m1 <= 0) return;
2033                 /* Skip if parallel markers disabled or already started. */
2034 #     ifdef CAN_HANDLE_FORK
2035         if (GC_parallel) return;
2036
2037         /* Reset mark_cv state after forking (as in pthread_support.c). */
2038         {
2039           pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER;
2040           BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv));
2041         }
2042 #     endif
2043
2044       GC_ASSERT(GC_fl_builder_count == 0);
2045       if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
2046       if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
2047         ABORT("pthread_attr_setdetachstate failed");
2048
2049 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2050         /* Apply special signal mask to GC marker threads, and don't drop */
2051         /* user defined signals by GC marker threads.                     */
2052         if (sigfillset(&set) != 0)
2053           ABORT("sigfillset failed");
2054         if (pthread_sigmask(SIG_BLOCK, &set, &oldset) < 0) {
2055           WARN("pthread_sigmask set failed, no markers started,"
2056                " errno = %" WARN_PRIdPTR "\n", errno);
2057           GC_markers_m1 = 0;
2058           (void)pthread_attr_destroy(&attr);
2059           return;
2060         }
2061 #     endif /* !NO_MARKER_SPECIAL_SIGMASK */
2062
2063 #     ifdef CAN_HANDLE_FORK
2064         /* To have proper GC_parallel value in GC_help_marker.  */
2065         GC_markers_m1 = available_markers_m1;
2066 #     endif
2067       for (i = 0; i < available_markers_m1; ++i) {
2068         marker_last_stack_min[i] = ADDR_LIMIT;
2069         if (0 != pthread_create(&new_thread, &attr,
2070                                 GC_mark_thread, (void *)(word)i)) {
2071           WARN("Marker thread creation failed\n", 0);
2072           /* Don't try to create other marker threads.    */
2073           GC_markers_m1 = i;
2074           break;
2075         }
2076       }
2077
2078 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2079         /* Restore previous signal mask.        */
2080         if (pthread_sigmask(SIG_SETMASK, &oldset, NULL) < 0) {
2081           WARN("pthread_sigmask restore failed, errno = %" WARN_PRIdPTR "\n",
2082                errno);
2083         }
2084 #     endif
2085
2086       (void)pthread_attr_destroy(&attr);
2087       GC_wait_for_markers_init();
2088       GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1);
2089     }
2090
2091 #   ifdef GC_ASSERTIONS
2092       STATIC unsigned long GC_mark_lock_holder = NO_THREAD;
2093 #     define SET_MARK_LOCK_HOLDER \
2094                 (void)(GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self()))
2095 #     define UNSET_MARK_LOCK_HOLDER \
2096                 do { \
2097                   GC_ASSERT(GC_mark_lock_holder \
2098                                 == NUMERIC_THREAD_ID(pthread_self())); \
2099                   GC_mark_lock_holder = NO_THREAD; \
2100                 } while (0)
2101 #   endif /* GC_ASSERTIONS */
2102
2103     static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
2104
2105     static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
2106
2107     /* GC_acquire/release_mark_lock(), GC_wait_builder/marker(),          */
2108     /* GC_wait_for_reclaim(), GC_notify_all_builder/marker() are the same */
2109     /* as in pthread_support.c except that GC_generic_lock() is not used. */
2110
2111 #   ifdef LOCK_STATS
2112       volatile AO_t GC_block_count = 0;
2113 #   endif
2114
2115     GC_INNER void GC_acquire_mark_lock(void)
2116     {
2117 #     if defined(NUMERIC_THREAD_ID_UNIQUE) && !defined(THREAD_SANITIZER)
2118         GC_ASSERT(GC_mark_lock_holder != NUMERIC_THREAD_ID(pthread_self()));
2119 #     endif
2120       if (pthread_mutex_lock(&mark_mutex) != 0) {
2121         ABORT("pthread_mutex_lock failed");
2122       }
2123 #     ifdef LOCK_STATS
2124         (void)AO_fetch_and_add1(&GC_block_count);
2125 #     endif
2126       /* GC_generic_lock(&mark_mutex); */
2127       SET_MARK_LOCK_HOLDER;
2128     }
2129
2130     GC_INNER void GC_release_mark_lock(void)
2131     {
2132       UNSET_MARK_LOCK_HOLDER;
2133       if (pthread_mutex_unlock(&mark_mutex) != 0) {
2134         ABORT("pthread_mutex_unlock failed");
2135       }
2136     }
2137
2138     /* Collector must wait for a freelist builders for 2 reasons:       */
2139     /* 1) Mark bits may still be getting examined without lock.         */
2140     /* 2) Partial free lists referenced only by locals may not be       */
2141     /* scanned correctly, e.g. if they contain "pointer-free" objects,  */
2142     /* since the free-list link may be ignored.                         */
2143     STATIC void GC_wait_builder(void)
2144     {
2145       UNSET_MARK_LOCK_HOLDER;
2146       if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) {
2147         ABORT("pthread_cond_wait failed");
2148       }
2149       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2150       SET_MARK_LOCK_HOLDER;
2151     }
2152
2153     GC_INNER void GC_wait_for_reclaim(void)
2154     {
2155       GC_acquire_mark_lock();
2156       while (GC_fl_builder_count > 0) {
2157         GC_wait_builder();
2158       }
2159       GC_release_mark_lock();
2160     }
2161
2162     GC_INNER void GC_notify_all_builder(void)
2163     {
2164       GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
2165       if (pthread_cond_broadcast(&builder_cv) != 0) {
2166         ABORT("pthread_cond_broadcast failed");
2167       }
2168     }
2169
2170     GC_INNER void GC_wait_marker(void)
2171     {
2172       GC_ASSERT(GC_parallel);
2173       UNSET_MARK_LOCK_HOLDER;
2174       if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
2175         ABORT("pthread_cond_wait failed");
2176       }
2177       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2178       SET_MARK_LOCK_HOLDER;
2179     }
2180
2181     GC_INNER void GC_notify_all_marker(void)
2182     {
2183       GC_ASSERT(GC_parallel);
2184       if (pthread_cond_broadcast(&mark_cv) != 0) {
2185         ABORT("pthread_cond_broadcast failed");
2186       }
2187     }
2188
2189 # else /* ! GC_PTHREADS_PARAMARK */
2190
2191 #   ifndef MARK_THREAD_STACK_SIZE
2192 #     define MARK_THREAD_STACK_SIZE 0   /* default value */
2193 #   endif
2194
2195     /* mark_mutex_event, builder_cv, mark_cv are initialized in GC_thr_init */
2196     static HANDLE mark_mutex_event = (HANDLE)0; /* Event with auto-reset.   */
2197     static HANDLE builder_cv = (HANDLE)0; /* Event with manual reset.       */
2198     static HANDLE mark_cv = (HANDLE)0; /* Event with manual reset.          */
2199
2200     GC_INNER void GC_start_mark_threads_inner(void)
2201     {
2202       int i;
2203
2204       GC_ASSERT(I_DONT_HOLD_LOCK());
2205       if (available_markers_m1 <= 0) return;
2206
2207       GC_ASSERT(GC_fl_builder_count == 0);
2208       /* Initialize GC_marker_cv[] fully before starting the    */
2209       /* first helper thread.                                   */
2210       for (i = 0; i < GC_markers_m1; ++i) {
2211         if ((GC_marker_cv[i] = CreateEvent(NULL /* attrs */,
2212                                         TRUE /* isManualReset */,
2213                                         FALSE /* initialState */,
2214                                         NULL /* name (A/W) */)) == (HANDLE)0)
2215           ABORT("CreateEvent failed");
2216       }
2217
2218       for (i = 0; i < GC_markers_m1; ++i) {
2219 #       if defined(MSWINCE) || defined(MSWIN_XBOX1)
2220           HANDLE handle;
2221           DWORD thread_id;
2222
2223           marker_last_stack_min[i] = ADDR_LIMIT;
2224           /* There is no _beginthreadex() in WinCE. */
2225           handle = CreateThread(NULL /* lpsa */,
2226                                 MARK_THREAD_STACK_SIZE /* ignored */,
2227                                 GC_mark_thread, (LPVOID)(word)i,
2228                                 0 /* fdwCreate */, &thread_id);
2229           if (handle == NULL) {
2230             WARN("Marker thread creation failed\n", 0);
2231             /* The most probable failure reason is "not enough memory". */
2232             /* Don't try to create other marker threads.                */
2233             break;
2234           } else {
2235             /* It's safe to detach the thread.  */
2236             CloseHandle(handle);
2237           }
2238 #       else
2239           GC_uintptr_t handle;
2240           unsigned thread_id;
2241
2242           marker_last_stack_min[i] = ADDR_LIMIT;
2243           handle = _beginthreadex(NULL /* security_attr */,
2244                                 MARK_THREAD_STACK_SIZE, GC_mark_thread,
2245                                 (void *)(word)i, 0 /* flags */, &thread_id);
2246           if (!handle || handle == (GC_uintptr_t)-1L) {
2247             WARN("Marker thread creation failed\n", 0);
2248             /* Don't try to create other marker threads.                */
2249             break;
2250           } else {/* We may detach the thread (if handle is of HANDLE type) */
2251             /* CloseHandle((HANDLE)handle); */
2252           }
2253 #       endif
2254       }
2255
2256       /* Adjust GC_markers_m1 (and free unused resources) if failed.    */
2257       while (GC_markers_m1 > i) {
2258         GC_markers_m1--;
2259         CloseHandle(GC_marker_cv[GC_markers_m1]);
2260       }
2261       GC_wait_for_markers_init();
2262       GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1);
2263       if (i == 0) {
2264         CloseHandle(mark_cv);
2265         CloseHandle(builder_cv);
2266         CloseHandle(mark_mutex_event);
2267       }
2268     }
2269
2270 #   ifdef GC_ASSERTIONS
2271       STATIC DWORD GC_mark_lock_holder = NO_THREAD;
2272 #     define SET_MARK_LOCK_HOLDER \
2273                 (void)(GC_mark_lock_holder = GetCurrentThreadId())
2274 #     define UNSET_MARK_LOCK_HOLDER \
2275                 do { \
2276                   GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId()); \
2277                   GC_mark_lock_holder = NO_THREAD; \
2278                 } while (0)
2279 #   endif /* GC_ASSERTIONS */
2280
2281     STATIC /* volatile */ LONG GC_mark_mutex_state = 0;
2282                                 /* Mutex state: 0 - unlocked,           */
2283                                 /* 1 - locked and no other waiters,     */
2284                                 /* -1 - locked and waiters may exist.   */
2285                                 /* Accessed by InterlockedExchange().   */
2286
2287     /* #define LOCK_STATS */
2288 #   ifdef LOCK_STATS
2289       volatile AO_t GC_block_count = 0;
2290       volatile AO_t GC_unlocked_count = 0;
2291 #   endif
2292
2293     GC_INNER void GC_acquire_mark_lock(void)
2294     {
2295 #     ifndef THREAD_SANITIZER
2296         GC_ASSERT(GC_mark_lock_holder != GetCurrentThreadId());
2297 #     endif
2298       if (InterlockedExchange(&GC_mark_mutex_state, 1 /* locked */) != 0) {
2299 #       ifdef LOCK_STATS
2300           (void)AO_fetch_and_add1(&GC_block_count);
2301 #       endif
2302         /* Repeatedly reset the state and wait until acquire the lock.  */
2303         while (InterlockedExchange(&GC_mark_mutex_state,
2304                                    -1 /* locked_and_has_waiters */) != 0) {
2305           if (WaitForSingleObject(mark_mutex_event, INFINITE) == WAIT_FAILED)
2306             ABORT("WaitForSingleObject failed");
2307         }
2308       }
2309 #     ifdef LOCK_STATS
2310         else {
2311           (void)AO_fetch_and_add1(&GC_unlocked_count);
2312         }
2313 #     endif
2314
2315       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2316       SET_MARK_LOCK_HOLDER;
2317     }
2318
2319     GC_INNER void GC_release_mark_lock(void)
2320     {
2321       UNSET_MARK_LOCK_HOLDER;
2322       if (InterlockedExchange(&GC_mark_mutex_state, 0 /* unlocked */) < 0) {
2323         /* wake a waiter */
2324         if (SetEvent(mark_mutex_event) == FALSE)
2325           ABORT("SetEvent failed");
2326       }
2327     }
2328
2329     /* In GC_wait_for_reclaim/GC_notify_all_builder() we emulate POSIX    */
2330     /* cond_wait/cond_broadcast() primitives with WinAPI Event object     */
2331     /* (working in "manual reset" mode).  This works here because         */
2332     /* GC_notify_all_builder() is always called holding lock on           */
2333     /* mark_mutex and the checked condition (GC_fl_builder_count == 0)    */
2334     /* is the only one for which broadcasting on builder_cv is performed. */
2335
2336     GC_INNER void GC_wait_for_reclaim(void)
2337     {
2338       GC_ASSERT(builder_cv != 0);
2339       for (;;) {
2340         GC_acquire_mark_lock();
2341         if (GC_fl_builder_count == 0)
2342           break;
2343         if (ResetEvent(builder_cv) == FALSE)
2344           ABORT("ResetEvent failed");
2345         GC_release_mark_lock();
2346         if (WaitForSingleObject(builder_cv, INFINITE) == WAIT_FAILED)
2347           ABORT("WaitForSingleObject failed");
2348       }
2349       GC_release_mark_lock();
2350     }
2351
2352     GC_INNER void GC_notify_all_builder(void)
2353     {
2354       GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId());
2355       GC_ASSERT(builder_cv != 0);
2356       GC_ASSERT(GC_fl_builder_count == 0);
2357       if (SetEvent(builder_cv) == FALSE)
2358         ABORT("SetEvent failed");
2359     }
2360
2361     /* mark_cv is used (for waiting) by a non-helper thread.    */
2362
2363     GC_INNER void GC_wait_marker(void)
2364     {
2365       HANDLE event = mark_cv;
2366       DWORD thread_id = GetCurrentThreadId();
2367       int i = GC_markers_m1;
2368
2369       while (i-- > 0) {
2370         if (GC_marker_Id[i] == thread_id) {
2371           event = GC_marker_cv[i];
2372           break;
2373         }
2374       }
2375
2376       if (ResetEvent(event) == FALSE)
2377         ABORT("ResetEvent failed");
2378       GC_release_mark_lock();
2379       if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED)
2380         ABORT("WaitForSingleObject failed");
2381       GC_acquire_mark_lock();
2382     }
2383
2384     GC_INNER void GC_notify_all_marker(void)
2385     {
2386       DWORD thread_id = GetCurrentThreadId();
2387       int i = GC_markers_m1;
2388
2389       while (i-- > 0) {
2390         /* Notify every marker ignoring self (for efficiency).  */
2391         if (SetEvent(GC_marker_Id[i] != thread_id ? GC_marker_cv[i] :
2392                      mark_cv) == FALSE)
2393           ABORT("SetEvent failed");
2394       }
2395     }
2396
2397 # endif /* ! GC_PTHREADS_PARAMARK */
2398
2399 #endif /* PARALLEL_MARK */
2400
2401   /* We have no DllMain to take care of new threads.  Thus we   */
2402   /* must properly intercept thread creation.                   */
2403
2404   typedef struct {
2405     LPTHREAD_START_ROUTINE start;
2406     LPVOID param;
2407   } thread_args;
2408
2409   STATIC void * GC_CALLBACK GC_win32_start_inner(struct GC_stack_base *sb,
2410                                                  void *arg)
2411   {
2412     void * ret;
2413     LPTHREAD_START_ROUTINE start = ((thread_args *)arg)->start;
2414     LPVOID param = ((thread_args *)arg)->param;
2415
2416     GC_register_my_thread(sb); /* This waits for an in-progress GC.     */
2417
2418 #   ifdef DEBUG_THREADS
2419       GC_log_printf("thread 0x%lx starting...\n", (long)GetCurrentThreadId());
2420 #   endif
2421
2422     GC_free(arg);
2423
2424     /* Clear the thread entry even if we exit with an exception.        */
2425     /* This is probably pointless, since an uncaught exception is       */
2426     /* supposed to result in the process being killed.                  */
2427 #   if !defined(__GNUC__) && !defined(NO_CRT)
2428       ret = NULL; /* to suppress "might be uninitialized" compiler warning */
2429       __try
2430 #   endif
2431     {
2432       ret = (void *)(word)(*start)(param);
2433     }
2434 #   if !defined(__GNUC__) && !defined(NO_CRT)
2435       __finally
2436 #   endif
2437     {
2438       GC_unregister_my_thread();
2439     }
2440
2441 #   ifdef DEBUG_THREADS
2442       GC_log_printf("thread 0x%lx returned from start routine\n",
2443                     (long)GetCurrentThreadId());
2444 #   endif
2445     return ret;
2446   }
2447
2448   STATIC DWORD WINAPI GC_win32_start(LPVOID arg)
2449   {
2450     return (DWORD)(word)GC_call_with_stack_base(GC_win32_start_inner, arg);
2451   }
2452
2453   GC_API HANDLE WINAPI GC_CreateThread(
2454                         LPSECURITY_ATTRIBUTES lpThreadAttributes,
2455                         GC_WIN32_SIZE_T dwStackSize,
2456                         LPTHREAD_START_ROUTINE lpStartAddress,
2457                         LPVOID lpParameter, DWORD dwCreationFlags,
2458                         LPDWORD lpThreadId)
2459   {
2460     if (!EXPECT(parallel_initialized, TRUE))
2461       GC_init_parallel();
2462                 /* make sure GC is initialized (i.e. main thread is     */
2463                 /* attached, tls initialized).                          */
2464
2465 #   ifdef DEBUG_THREADS
2466       GC_log_printf("About to create a thread from 0x%lx\n",
2467                     (long)GetCurrentThreadId());
2468 #   endif
2469     if (GC_win32_dll_threads) {
2470       return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
2471                           lpParameter, dwCreationFlags, lpThreadId);
2472     } else {
2473       thread_args *args =
2474                 (thread_args *)GC_malloc_uncollectable(sizeof(thread_args));
2475                 /* Handed off to and deallocated by child thread.       */
2476       HANDLE thread_h;
2477
2478       if (NULL == args) {
2479         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2480         return NULL;
2481       }
2482
2483       /* set up thread arguments */
2484       args -> start = lpStartAddress;
2485       args -> param = lpParameter;
2486       GC_dirty(args);
2487       REACHABLE_AFTER_DIRTY(lpParameter);
2488
2489       set_need_to_lock();
2490       thread_h = CreateThread(lpThreadAttributes, dwStackSize, GC_win32_start,
2491                               args, dwCreationFlags, lpThreadId);
2492       if (thread_h == 0) GC_free(args);
2493       return thread_h;
2494     }
2495   }
2496
2497   GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread(DWORD dwExitCode)
2498   {
2499     GC_unregister_my_thread();
2500     ExitThread(dwExitCode);
2501   }
2502
2503 # if !defined(CYGWIN32) && !defined(MSWINCE) && !defined(MSWIN_XBOX1) \
2504      && !defined(NO_CRT)
2505     GC_API GC_uintptr_t GC_CALL GC_beginthreadex(
2506                                   void *security, unsigned stack_size,
2507                                   unsigned (__stdcall *start_address)(void *),
2508                                   void *arglist, unsigned initflag,
2509                                   unsigned *thrdaddr)
2510     {
2511       if (!EXPECT(parallel_initialized, TRUE))
2512         GC_init_parallel();
2513                 /* make sure GC is initialized (i.e. main thread is     */
2514                 /* attached, tls initialized).                          */
2515 #     ifdef DEBUG_THREADS
2516         GC_log_printf("About to create a thread from 0x%lx\n",
2517                       (long)GetCurrentThreadId());
2518 #     endif
2519
2520       if (GC_win32_dll_threads) {
2521         return _beginthreadex(security, stack_size, start_address,
2522                               arglist, initflag, thrdaddr);
2523       } else {
2524         GC_uintptr_t thread_h;
2525         thread_args *args =
2526                 (thread_args *)GC_malloc_uncollectable(sizeof(thread_args));
2527                 /* Handed off to and deallocated by child thread.       */
2528
2529         if (NULL == args) {
2530           /* MSDN docs say _beginthreadex() returns 0 on error and sets */
2531           /* errno to either EAGAIN (too many threads) or EINVAL (the   */
2532           /* argument is invalid or the stack size is incorrect), so we */
2533           /* set errno to EAGAIN on "not enough memory".                */
2534           errno = EAGAIN;
2535           return 0;
2536         }
2537
2538         /* set up thread arguments */
2539         args -> start = (LPTHREAD_START_ROUTINE)start_address;
2540         args -> param = arglist;
2541         GC_dirty(args);
2542         REACHABLE_AFTER_DIRTY(arglist);
2543
2544         set_need_to_lock();
2545         thread_h = _beginthreadex(security, stack_size,
2546                         (unsigned (__stdcall *)(void *))GC_win32_start,
2547                         args, initflag, thrdaddr);
2548         if (thread_h == 0) GC_free(args);
2549         return thread_h;
2550       }
2551     }
2552
2553     GC_API void GC_CALL GC_endthreadex(unsigned retval)
2554     {
2555       GC_unregister_my_thread();
2556       _endthreadex(retval);
2557     }
2558 # endif /* !CYGWIN32 && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT */
2559
2560 #ifdef GC_WINMAIN_REDIRECT
2561   /* This might be useful on WinCE.  Shouldn't be used with GC_DLL.     */
2562
2563 # if defined(MSWINCE) && defined(UNDER_CE)
2564 #   define WINMAIN_LPTSTR LPWSTR
2565 # else
2566 #   define WINMAIN_LPTSTR LPSTR
2567 # endif
2568
2569   /* This is defined in gc.h.   */
2570 # undef WinMain
2571
2572   /* Defined outside GC by an application.      */
2573   int WINAPI GC_WinMain(HINSTANCE, HINSTANCE, WINMAIN_LPTSTR, int);
2574
2575   typedef struct {
2576     HINSTANCE hInstance;
2577     HINSTANCE hPrevInstance;
2578     WINMAIN_LPTSTR lpCmdLine;
2579     int nShowCmd;
2580   } main_thread_args;
2581
2582   static DWORD WINAPI main_thread_start(LPVOID arg)
2583   {
2584     main_thread_args * args = (main_thread_args *) arg;
2585     return (DWORD)GC_WinMain(args->hInstance, args->hPrevInstance,
2586                              args->lpCmdLine, args->nShowCmd);
2587   }
2588
2589   STATIC void * GC_waitForSingleObjectInfinite(void * handle)
2590   {
2591     return (void *)(word)WaitForSingleObject((HANDLE)handle, INFINITE);
2592   }
2593
2594 # ifndef WINMAIN_THREAD_STACK_SIZE
2595 #   define WINMAIN_THREAD_STACK_SIZE 0  /* default value */
2596 # endif
2597
2598   int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
2599                      WINMAIN_LPTSTR lpCmdLine, int nShowCmd)
2600   {
2601     DWORD exit_code = 1;
2602
2603     main_thread_args args = {
2604                 hInstance, hPrevInstance, lpCmdLine, nShowCmd
2605     };
2606     HANDLE thread_h;
2607     DWORD thread_id;
2608
2609     /* initialize everything */
2610     GC_INIT();
2611
2612     /* start the main thread */
2613     thread_h = GC_CreateThread(NULL /* lpsa */,
2614                         WINMAIN_THREAD_STACK_SIZE /* ignored on WinCE */,
2615                         main_thread_start, &args, 0 /* fdwCreate */,
2616                         &thread_id);
2617
2618     if (thread_h != NULL) {
2619       if ((DWORD)(word)GC_do_blocking(GC_waitForSingleObjectInfinite,
2620                                       (void *)thread_h) == WAIT_FAILED)
2621         ABORT("WaitForSingleObject(main_thread) failed");
2622       GetExitCodeThread (thread_h, &exit_code);
2623       CloseHandle (thread_h);
2624     } else {
2625       ABORT("GC_CreateThread(main_thread) failed");
2626     }
2627
2628 #   ifdef MSWINCE
2629       GC_deinit();
2630 #   endif
2631     return (int) exit_code;
2632   }
2633
2634 #endif /* GC_WINMAIN_REDIRECT */
2635
2636 GC_INNER void GC_thr_init(void)
2637 {
2638   struct GC_stack_base sb;
2639
2640   GC_ASSERT(I_HOLD_LOCK());
2641   if (GC_thr_initialized) return;
2642
2643   GC_ASSERT((word)&GC_threads % sizeof(word) == 0);
2644 # ifdef GC_NO_THREADS_DISCOVERY
2645 #   define GC_main_thread GetCurrentThreadId()
2646 # else
2647     GC_main_thread = GetCurrentThreadId();
2648 # endif
2649   GC_thr_initialized = TRUE;
2650
2651 # ifdef CAN_HANDLE_FORK
2652     /* Prepare for forks if requested.  */
2653     if (GC_handle_fork) {
2654 #     ifdef CAN_CALL_ATFORK
2655         if (pthread_atfork(fork_prepare_proc, fork_parent_proc,
2656                            fork_child_proc) == 0) {
2657           /* Handlers successfully registered.  */
2658           GC_handle_fork = 1;
2659         } else
2660 #     endif
2661       /* else */ if (GC_handle_fork != -1)
2662         ABORT("pthread_atfork failed");
2663     }
2664 # endif
2665
2666 # ifdef WOW64_THREAD_CONTEXT_WORKAROUND
2667     /* Set isWow64 flag. */
2668     {
2669       HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
2670       if (hK32) {
2671         FARPROC pfn = GetProcAddress(hK32, "IsWow64Process");
2672         if (pfn
2673             && !(*(BOOL (WINAPI*)(HANDLE, BOOL*))pfn)(GetCurrentProcess(),
2674                                                       &isWow64))
2675           isWow64 = FALSE; /* IsWow64Process failed */
2676       }
2677     }
2678 # endif
2679
2680   /* Add the initial thread, so we can stop it. */
2681   sb.mem_base = GC_stackbottom;
2682   GC_ASSERT(sb.mem_base != NULL);
2683 # ifdef IA64
2684     sb.reg_base = GC_register_stackbottom;
2685 # endif
2686
2687 # if defined(PARALLEL_MARK)
2688     {
2689       char * markers_string = GETENV("GC_MARKERS");
2690       int markers;
2691
2692       if (markers_string != NULL) {
2693         markers = atoi(markers_string);
2694         if (markers <= 0 || markers > MAX_MARKERS) {
2695           WARN("Too big or invalid number of mark threads: %" WARN_PRIdPTR
2696                "; using maximum threads\n", (signed_word)markers);
2697           markers = MAX_MARKERS;
2698         }
2699       } else {
2700 #       ifdef MSWINCE
2701           /* There is no GetProcessAffinityMask() in WinCE.     */
2702           /* GC_sysinfo is already initialized.                 */
2703           markers = (int)GC_sysinfo.dwNumberOfProcessors;
2704 #       else
2705 #         ifdef _WIN64
2706             DWORD_PTR procMask = 0;
2707             DWORD_PTR sysMask;
2708 #         else
2709             DWORD procMask = 0;
2710             DWORD sysMask;
2711 #         endif
2712           int ncpu = 0;
2713           if (
2714 #           ifdef __cplusplus
2715               GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask)
2716 #           else
2717               /* Cast args to void* for compatibility with some old SDKs. */
2718               GetProcessAffinityMask(GetCurrentProcess(),
2719                                      (void *)&procMask, (void *)&sysMask)
2720 #           endif
2721               && procMask) {
2722             do {
2723               ncpu++;
2724             } while ((procMask &= procMask - 1) != 0);
2725           }
2726           markers = ncpu;
2727 #       endif
2728 #       if defined(GC_MIN_MARKERS) && !defined(CPPCHECK)
2729           /* This is primarily for testing on systems without getenv(). */
2730           if (markers < GC_MIN_MARKERS)
2731             markers = GC_MIN_MARKERS;
2732 #       endif
2733         if (markers > MAX_MARKERS)
2734           markers = MAX_MARKERS; /* silently limit the value */
2735       }
2736       available_markers_m1 = markers - 1;
2737     }
2738
2739     /* Check whether parallel mode could be enabled.    */
2740       if (GC_win32_dll_threads || available_markers_m1 <= 0) {
2741         /* Disable parallel marking. */
2742         GC_parallel = FALSE;
2743         GC_COND_LOG_PRINTF(
2744                 "Single marker thread, turning off parallel marking\n");
2745       } else {
2746 #       ifndef GC_PTHREADS_PARAMARK
2747           /* Initialize Win32 event objects for parallel marking.       */
2748           mark_mutex_event = CreateEvent(NULL /* attrs */,
2749                                 FALSE /* isManualReset */,
2750                                 FALSE /* initialState */, NULL /* name */);
2751           builder_cv = CreateEvent(NULL /* attrs */,
2752                                 TRUE /* isManualReset */,
2753                                 FALSE /* initialState */, NULL /* name */);
2754           mark_cv = CreateEvent(NULL /* attrs */, TRUE /* isManualReset */,
2755                                 FALSE /* initialState */, NULL /* name */);
2756           if (mark_mutex_event == (HANDLE)0 || builder_cv == (HANDLE)0
2757               || mark_cv == (HANDLE)0)
2758             ABORT("CreateEvent failed");
2759 #       endif
2760       }
2761 # endif /* PARALLEL_MARK */
2762
2763   GC_ASSERT(0 == GC_lookup_thread_inner(GC_main_thread));
2764   GC_register_my_thread_inner(&sb, GC_main_thread);
2765 # undef GC_main_thread
2766 }
2767
2768 #ifdef GC_PTHREADS
2769
2770   struct start_info {
2771     void *(*start_routine)(void *);
2772     void *arg;
2773     GC_bool detached;
2774   };
2775
2776   GC_API int GC_pthread_join(pthread_t pthread_id, void **retval)
2777   {
2778     int result;
2779 #   ifndef GC_WIN32_PTHREADS
2780       GC_thread t;
2781 #   endif
2782     DCL_LOCK_STATE;
2783
2784     GC_ASSERT(!GC_win32_dll_threads);
2785 #   ifdef DEBUG_THREADS
2786       GC_log_printf("thread %p(0x%lx) is joining thread %p\n",
2787                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2788                     (long)GetCurrentThreadId(),
2789                     (void *)GC_PTHREAD_PTRVAL(pthread_id));
2790 #   endif
2791
2792     /* Thread being joined might not have registered itself yet. */
2793     /* After the join, thread id may have been recycled.         */
2794     /* FIXME: It would be better if this worked more like        */
2795     /* pthread_support.c.                                        */
2796 #   ifndef GC_WIN32_PTHREADS
2797       while ((t = GC_lookup_pthread(pthread_id)) == 0)
2798         Sleep(10);
2799 #   endif
2800     result = pthread_join(pthread_id, retval);
2801     if (0 == result) {
2802 #     ifdef GC_WIN32_PTHREADS
2803         /* pthreads-win32 and winpthreads id are unique (not recycled). */
2804         GC_thread t = GC_lookup_pthread(pthread_id);
2805         if (NULL == t) ABORT("Thread not registered");
2806 #     endif
2807
2808       LOCK();
2809       if ((t -> flags & FINISHED) != 0) {
2810         GC_delete_gc_thread_no_free(t);
2811         GC_INTERNAL_FREE(t);
2812       }
2813       UNLOCK();
2814     }
2815
2816 #   ifdef DEBUG_THREADS
2817       GC_log_printf("thread %p(0x%lx) join with thread %p %s\n",
2818                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2819                     (long)GetCurrentThreadId(),
2820                     (void *)GC_PTHREAD_PTRVAL(pthread_id),
2821                     result != 0 ? "failed" : "succeeded");
2822 #   endif
2823     return result;
2824   }
2825
2826   /* Cygwin-pthreads calls CreateThread internally, but it's not easily */
2827   /* interceptable by us..., so intercept pthread_create instead.       */
2828   GC_API int GC_pthread_create(pthread_t *new_thread,
2829                                GC_PTHREAD_CREATE_CONST pthread_attr_t *attr,
2830                                void *(*start_routine)(void *), void *arg)
2831   {
2832     int result;
2833     struct start_info * si;
2834
2835     if (!EXPECT(parallel_initialized, TRUE))
2836       GC_init_parallel();
2837              /* make sure GC is initialized (i.e. main thread is attached) */
2838     GC_ASSERT(!GC_win32_dll_threads);
2839
2840       /* This is otherwise saved only in an area mmapped by the thread  */
2841       /* library, which isn't visible to the collector.                 */
2842       si = (struct start_info *)GC_malloc_uncollectable(
2843                                                 sizeof(struct start_info));
2844       if (NULL == si)
2845         return EAGAIN;
2846
2847       si -> start_routine = start_routine;
2848       si -> arg = arg;
2849       GC_dirty(si);
2850       REACHABLE_AFTER_DIRTY(arg);
2851       if (attr != 0 &&
2852           pthread_attr_getdetachstate(attr, &si->detached)
2853           == PTHREAD_CREATE_DETACHED) {
2854         si->detached = TRUE;
2855       }
2856
2857 #     ifdef DEBUG_THREADS
2858         GC_log_printf("About to create a thread from %p(0x%lx)\n",
2859                       (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2860                       (long)GetCurrentThreadId());
2861 #     endif
2862       set_need_to_lock();
2863       result = pthread_create(new_thread, attr, GC_pthread_start, si);
2864
2865       if (result) { /* failure */
2866           GC_free(si);
2867       }
2868       return(result);
2869   }
2870
2871   STATIC void * GC_CALLBACK GC_pthread_start_inner(struct GC_stack_base *sb,
2872                                                    void * arg)
2873   {
2874     struct start_info * si = (struct start_info *)arg;
2875     void * result;
2876     void *(*start)(void *);
2877     void *start_arg;
2878     DWORD thread_id = GetCurrentThreadId();
2879     pthread_t pthread_id = pthread_self();
2880     GC_thread me;
2881     DCL_LOCK_STATE;
2882
2883 #   ifdef DEBUG_THREADS
2884       GC_log_printf("thread %p(0x%x) starting...\n",
2885                     (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id);
2886 #   endif
2887
2888     GC_ASSERT(!GC_win32_dll_threads);
2889     /* If a GC occurs before the thread is registered, that GC will     */
2890     /* ignore this thread.  That's fine, since it will block trying to  */
2891     /* acquire the allocation lock, and won't yet hold interesting      */
2892     /* pointers.                                                        */
2893     LOCK();
2894     /* We register the thread here instead of in the parent, so that    */
2895     /* we don't need to hold the allocation lock during pthread_create. */
2896     me = GC_register_my_thread_inner(sb, thread_id);
2897     SET_PTHREAD_MAP_CACHE(pthread_id, thread_id);
2898     GC_ASSERT(me != &first_thread);
2899     me -> pthread_id = pthread_id;
2900     if (si->detached) me -> flags |= DETACHED;
2901     UNLOCK();
2902
2903     start = si -> start_routine;
2904     start_arg = si -> arg;
2905
2906     GC_free(si); /* was allocated uncollectible */
2907
2908     pthread_cleanup_push(GC_thread_exit_proc, (void *)me);
2909     result = (*start)(start_arg);
2910     me -> status = result;
2911     GC_dirty(me);
2912     pthread_cleanup_pop(1);
2913
2914 #   ifdef DEBUG_THREADS
2915       GC_log_printf("thread %p(0x%x) returned from start routine\n",
2916                     (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id);
2917 #   endif
2918     return(result);
2919   }
2920
2921   STATIC void * GC_pthread_start(void * arg)
2922   {
2923     return GC_call_with_stack_base(GC_pthread_start_inner, arg);
2924   }
2925
2926   STATIC void GC_thread_exit_proc(void *arg)
2927   {
2928     GC_thread me = (GC_thread)arg;
2929     DCL_LOCK_STATE;
2930
2931     GC_ASSERT(!GC_win32_dll_threads);
2932 #   ifdef DEBUG_THREADS
2933       GC_log_printf("thread %p(0x%lx) called pthread_exit()\n",
2934                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2935                     (long)GetCurrentThreadId());
2936 #   endif
2937
2938     LOCK();
2939     GC_wait_for_gc_completion(FALSE);
2940 #   if defined(THREAD_LOCAL_ALLOC)
2941       GC_ASSERT(GC_getspecific(GC_thread_key) == &me->tlfs);
2942       GC_destroy_thread_local(&(me->tlfs));
2943 #   endif
2944     if (me -> flags & DETACHED) {
2945       GC_delete_thread(GetCurrentThreadId());
2946     } else {
2947       /* deallocate it as part of join */
2948       me -> flags |= FINISHED;
2949     }
2950 #   if defined(THREAD_LOCAL_ALLOC)
2951       /* It is required to call remove_specific defined in specific.c. */
2952       GC_remove_specific(GC_thread_key);
2953 #   endif
2954     UNLOCK();
2955   }
2956
2957 # ifndef GC_NO_PTHREAD_SIGMASK
2958     /* Win32 pthread does not support sigmask.  */
2959     /* So, nothing required here...             */
2960     GC_API int GC_pthread_sigmask(int how, const sigset_t *set,
2961                                   sigset_t *oset)
2962     {
2963       return pthread_sigmask(how, set, oset);
2964     }
2965 # endif /* !GC_NO_PTHREAD_SIGMASK */
2966
2967   GC_API int GC_pthread_detach(pthread_t thread)
2968   {
2969     int result;
2970     GC_thread t;
2971     DCL_LOCK_STATE;
2972
2973     GC_ASSERT(!GC_win32_dll_threads);
2974     /* The thread might not have registered itself yet. */
2975     /* TODO: Wait for registration of the created thread in pthread_create. */
2976     while ((t = GC_lookup_pthread(thread)) == NULL)
2977       Sleep(10);
2978     result = pthread_detach(thread);
2979     if (result == 0) {
2980       LOCK();
2981       t -> flags |= DETACHED;
2982       /* Here the pthread thread id may have been recycled. */
2983       if ((t -> flags & FINISHED) != 0) {
2984         GC_delete_gc_thread_no_free(t);
2985         GC_INTERNAL_FREE(t);
2986       }
2987       UNLOCK();
2988     }
2989     return result;
2990   }
2991
2992 #elif !defined(GC_NO_THREADS_DISCOVERY)
2993     /* We avoid acquiring locks here, since this doesn't seem to be     */
2994     /* preemptible.  This may run with an uninitialized collector, in   */
2995     /* which case we don't do much.  This implies that no threads other */
2996     /* than the main one should be created with an uninitialized        */
2997     /* collector.  (The alternative of initializing the collector here  */
2998     /* seems dangerous, since DllMain is limited in what it can do.)    */
2999
3000 # ifdef GC_INSIDE_DLL
3001     /* Export only if needed by client. */
3002     GC_API
3003 # else
3004 #   define GC_DllMain DllMain
3005 # endif
3006   BOOL WINAPI GC_DllMain(HINSTANCE inst GC_ATTR_UNUSED, ULONG reason,
3007                          LPVOID reserved GC_ATTR_UNUSED)
3008   {
3009       DWORD thread_id;
3010
3011       /* Note that GC_use_threads_discovery should be called by the     */
3012       /* client application at start-up to activate automatic thread    */
3013       /* registration (it is the default GC behavior);                  */
3014       /* to always have automatic thread registration turned on, the GC */
3015       /* should be compiled with -D GC_DISCOVER_TASK_THREADS.           */
3016       if (!GC_win32_dll_threads && parallel_initialized) return TRUE;
3017
3018       switch (reason) {
3019        case DLL_THREAD_ATTACH:
3020 #       ifdef PARALLEL_MARK
3021           /* Don't register marker threads. */
3022           if (GC_parallel) {
3023             /* We could reach here only if parallel_initialized == FALSE. */
3024             break;
3025           }
3026 #       endif
3027         /* FALLTHRU */
3028        case DLL_PROCESS_ATTACH:
3029         /* This may run with the collector uninitialized. */
3030         thread_id = GetCurrentThreadId();
3031         if (parallel_initialized && GC_main_thread != thread_id) {
3032 #         ifdef PARALLEL_MARK
3033             ABORT("Cannot initialize parallel marker from DllMain");
3034 #         else
3035             struct GC_stack_base sb;
3036             /* Don't lock here. */
3037 #           ifdef GC_ASSERTIONS
3038               int sb_result =
3039 #           endif
3040                         GC_get_stack_base(&sb);
3041             GC_ASSERT(sb_result == GC_SUCCESS);
3042             GC_register_my_thread_inner(&sb, thread_id);
3043 #         endif
3044         } /* o.w. we already did it during GC_thr_init, called by GC_init */
3045         break;
3046
3047        case DLL_THREAD_DETACH:
3048         /* We are hopefully running in the context of the exiting thread. */
3049         GC_ASSERT(parallel_initialized);
3050         if (GC_win32_dll_threads) {
3051           GC_delete_thread(GetCurrentThreadId());
3052         }
3053         break;
3054
3055        case DLL_PROCESS_DETACH:
3056         if (GC_win32_dll_threads) {
3057           int i;
3058           int my_max = (int)GC_get_max_thread_index();
3059
3060           for (i = 0; i <= my_max; ++i) {
3061            if (AO_load(&(dll_thread_table[i].tm.in_use)))
3062              GC_delete_gc_thread_no_free(&dll_thread_table[i]);
3063           }
3064           GC_deinit();
3065         }
3066         break;
3067       }
3068       return TRUE;
3069   }
3070 #endif /* !GC_NO_THREADS_DISCOVERY && !GC_PTHREADS */
3071
3072 /* Perform all initializations, including those that    */
3073 /* may require allocation.                              */
3074 /* Called without allocation lock.                      */
3075 /* Must be called before a second thread is created.    */
3076 GC_INNER void GC_init_parallel(void)
3077 {
3078 # if defined(THREAD_LOCAL_ALLOC)
3079     GC_thread me;
3080     DCL_LOCK_STATE;
3081 # endif
3082
3083   if (parallel_initialized) return;
3084   parallel_initialized = TRUE;
3085   /* GC_init() calls us back, so set flag first.      */
3086
3087   if (!GC_is_initialized) GC_init();
3088 # if defined(CPPCHECK) && !defined(GC_NO_THREADS_DISCOVERY)
3089     GC_noop1((word)&GC_DllMain);
3090 # endif
3091   if (GC_win32_dll_threads) {
3092     set_need_to_lock();
3093         /* Cannot intercept thread creation.  Hence we don't know if    */
3094         /* other threads exist.  However, client is not allowed to      */
3095         /* create other threads before collector initialization.        */
3096         /* Thus it's OK not to lock before this.                        */
3097   }
3098   /* Initialize thread local free lists if used.        */
3099 # if defined(THREAD_LOCAL_ALLOC)
3100     LOCK();
3101     me = GC_lookup_thread_inner(GetCurrentThreadId());
3102     CHECK_LOOKUP_MY_THREAD(me);
3103     GC_init_thread_local(&me->tlfs);
3104     UNLOCK();
3105 # endif
3106 }
3107
3108 #if defined(USE_PTHREAD_LOCKS)
3109   /* Support for pthread locking code.          */
3110   /* pthread_mutex_trylock may not win here,    */
3111   /* due to builtin support for spinning first? */
3112
3113   GC_INNER void GC_lock(void)
3114   {
3115     pthread_mutex_lock(&GC_allocate_ml);
3116   }
3117 #endif /* USE_PTHREAD_LOCKS */
3118
3119 #if defined(THREAD_LOCAL_ALLOC)
3120
3121   /* Add thread-local allocation support.  VC++ uses __declspec(thread).  */
3122
3123   /* We must explicitly mark ptrfree and gcj free lists, since the free   */
3124   /* list links wouldn't otherwise be found.  We also set them in the     */
3125   /* normal free lists, since that involves touching less memory than if  */
3126   /* we scanned them normally.                                            */
3127   GC_INNER void GC_mark_thread_local_free_lists(void)
3128   {
3129     int i;
3130     GC_thread p;
3131
3132     for (i = 0; i < THREAD_TABLE_SZ; ++i) {
3133       for (p = GC_threads[i]; 0 != p; p = p -> tm.next) {
3134         if (!KNOWN_FINISHED(p)) {
3135 #         ifdef DEBUG_THREADS
3136             GC_log_printf("Marking thread locals for 0x%x\n", (int)p -> id);
3137 #         endif
3138           GC_mark_thread_local_fls_for(&(p->tlfs));
3139         }
3140       }
3141     }
3142   }
3143
3144 # if defined(GC_ASSERTIONS)
3145     /* Check that all thread-local free-lists are completely marked.    */
3146     /* also check that thread-specific-data structures are marked.      */
3147     void GC_check_tls(void)
3148     {
3149         int i;
3150         GC_thread p;
3151
3152         for (i = 0; i < THREAD_TABLE_SZ; ++i) {
3153           for (p = GC_threads[i]; 0 != p; p = p -> tm.next) {
3154             if (!KNOWN_FINISHED(p))
3155               GC_check_tls_for(&(p->tlfs));
3156           }
3157         }
3158 #       if defined(USE_CUSTOM_SPECIFIC)
3159           if (GC_thread_key != 0)
3160             GC_check_tsd_marks(GC_thread_key);
3161 #       endif
3162     }
3163 # endif /* GC_ASSERTIONS */
3164
3165 #endif /* THREAD_LOCAL_ALLOC ... */
3166
3167 # ifndef GC_NO_THREAD_REDIRECTS
3168     /* Restore thread calls redirection.        */
3169 #   define CreateThread GC_CreateThread
3170 #   define ExitThread GC_ExitThread
3171 #   undef _beginthreadex
3172 #   define _beginthreadex GC_beginthreadex
3173 #   undef _endthreadex
3174 #   define _endthreadex GC_endthreadex
3175 # endif /* !GC_NO_THREAD_REDIRECTS */
3176
3177 #endif /* GC_WIN32_THREADS */