Workaround 'redundant initialization for r' cppcheck false positive
[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) && (defined(MSWIN32) || defined(MSWINCE))
1336   GC_INNER GC_bool GC_write_disabled = FALSE;
1337                 /* TRUE only if GC_stop_world() acquired GC_write_cs.   */
1338 #endif
1339
1340 GC_INNER void GC_stop_world(void)
1341 {
1342   DWORD thread_id = GetCurrentThreadId();
1343
1344   if (!GC_thr_initialized)
1345     ABORT("GC_stop_world() called before GC_thr_init()");
1346   GC_ASSERT(I_HOLD_LOCK());
1347
1348   /* This code is the same as in pthread_stop_world.c */
1349 # ifdef PARALLEL_MARK
1350     if (GC_parallel) {
1351       GC_acquire_mark_lock();
1352       GC_ASSERT(GC_fl_builder_count == 0);
1353       /* We should have previously waited for it to become zero. */
1354     }
1355 # endif /* PARALLEL_MARK */
1356
1357 # if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)
1358     GC_please_stop = TRUE;
1359 # endif
1360 # ifndef CYGWIN32
1361 #   ifndef MSWIN_XBOX1
1362       GC_ASSERT(!GC_write_disabled);
1363 #   endif
1364     EnterCriticalSection(&GC_write_cs);
1365 # endif
1366 # if defined(GC_ASSERTIONS) && (defined(MSWIN32) || defined(MSWINCE))
1367     /* It's not allowed to call GC_printf() (and friends) here down to  */
1368     /* LeaveCriticalSection (same applies recursively to GC_suspend,    */
1369     /* GC_delete_gc_thread_no_free, GC_get_max_thread_index, GC_size    */
1370     /* and GC_remove_protection).                                       */
1371     GC_write_disabled = TRUE;
1372 # endif
1373 # ifndef GC_NO_THREADS_DISCOVERY
1374     if (GC_win32_dll_threads) {
1375       int i;
1376       int my_max;
1377       /* Any threads being created during this loop will end up setting */
1378       /* GC_attached_thread when they start.  This will force marking   */
1379       /* to restart.  This is not ideal, but hopefully correct.         */
1380       AO_store(&GC_attached_thread, FALSE);
1381       my_max = (int)GC_get_max_thread_index();
1382       for (i = 0; i <= my_max; i++) {
1383         GC_vthread t = dll_thread_table + i;
1384         if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
1385             && t -> id != thread_id) {
1386           GC_suspend((GC_thread)t);
1387         }
1388       }
1389     } else
1390 # endif
1391   /* else */ {
1392     GC_thread t;
1393     int i;
1394
1395     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1396       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1397         if (t -> stack_base != 0 && t -> thread_blocked_sp == NULL
1398             && !KNOWN_FINISHED(t) && t -> id != thread_id) {
1399           GC_suspend(t);
1400         }
1401       }
1402     }
1403   }
1404 # if defined(GC_ASSERTIONS) && (defined(MSWIN32) || defined(MSWINCE))
1405     GC_write_disabled = FALSE;
1406 # endif
1407 # ifndef CYGWIN32
1408     LeaveCriticalSection(&GC_write_cs);
1409 # endif
1410 # ifdef PARALLEL_MARK
1411     if (GC_parallel)
1412       GC_release_mark_lock();
1413 # endif
1414 }
1415
1416 GC_INNER void GC_start_world(void)
1417 {
1418 # ifdef GC_ASSERTIONS
1419     DWORD thread_id = GetCurrentThreadId();
1420 # endif
1421
1422   GC_ASSERT(I_HOLD_LOCK());
1423   if (GC_win32_dll_threads) {
1424     LONG my_max = GC_get_max_thread_index();
1425     int i;
1426
1427     for (i = 0; i <= my_max; i++) {
1428       GC_thread t = (GC_thread)(dll_thread_table + i);
1429       if (t -> suspended) {
1430         GC_ASSERT(t -> stack_base != 0 && t -> id != thread_id);
1431         if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1)
1432           ABORT("ResumeThread failed");
1433         t -> suspended = FALSE;
1434         if (GC_on_thread_event)
1435           GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t));
1436       }
1437     }
1438   } else {
1439     GC_thread t;
1440     int i;
1441
1442     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1443       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1444         if (t -> suspended) {
1445           GC_ASSERT(t -> stack_base != 0 && t -> id != thread_id);
1446           if (ResumeThread(THREAD_HANDLE(t)) == (DWORD)-1)
1447             ABORT("ResumeThread failed");
1448           UNPROTECT_THREAD(t);
1449           t -> suspended = FALSE;
1450           if (GC_on_thread_event)
1451             GC_on_thread_event(GC_EVENT_THREAD_UNSUSPENDED, THREAD_HANDLE(t));
1452         }
1453       }
1454     }
1455   }
1456 # if !defined(GC_NO_THREADS_DISCOVERY) || defined(GC_ASSERTIONS)
1457     GC_please_stop = FALSE;
1458 # endif
1459 }
1460
1461 #ifdef MSWINCE
1462   /* The VirtualQuery calls below won't work properly on some old WinCE */
1463   /* versions, but since each stack is restricted to an aligned 64 KiB  */
1464   /* region of virtual memory we can just take the next lowest multiple */
1465   /* of 64 KiB.  The result of this macro must not be used as its       */
1466   /* argument later and must not be used as the lower bound for sp      */
1467   /* check (since the stack may be bigger than 64 KiB).                 */
1468 # define GC_wince_evaluate_stack_min(s) \
1469                         (ptr_t)(((word)(s) - 1) & ~(word)0xFFFF)
1470 #elif defined(GC_ASSERTIONS)
1471 # define GC_dont_query_stack_min FALSE
1472 #endif
1473
1474 /* A cache holding the results of the recent VirtualQuery call. */
1475 /* Protected by the allocation lock.                            */
1476 static ptr_t last_address = 0;
1477 static MEMORY_BASIC_INFORMATION last_info;
1478
1479 /* Probe stack memory region (starting at "s") to find out its  */
1480 /* lowest address (i.e. stack top).                             */
1481 /* S must be a mapped address inside the region, NOT the first  */
1482 /* unmapped address.                                            */
1483 STATIC ptr_t GC_get_stack_min(ptr_t s)
1484 {
1485   ptr_t bottom;
1486
1487   GC_ASSERT(I_HOLD_LOCK());
1488   if (s != last_address) {
1489     VirtualQuery(s, &last_info, sizeof(last_info));
1490     last_address = s;
1491   }
1492   do {
1493     bottom = (ptr_t)last_info.BaseAddress;
1494     VirtualQuery(bottom - 1, &last_info, sizeof(last_info));
1495     last_address = bottom - 1;
1496   } while ((last_info.Protect & PAGE_READWRITE)
1497            && !(last_info.Protect & PAGE_GUARD));
1498   return(bottom);
1499 }
1500
1501 /* Return true if the page at s has protections appropriate     */
1502 /* for a stack page.                                            */
1503 static GC_bool may_be_in_stack(ptr_t s)
1504 {
1505   GC_ASSERT(I_HOLD_LOCK());
1506   if (s != last_address) {
1507     VirtualQuery(s, &last_info, sizeof(last_info));
1508     last_address = s;
1509   }
1510   return (last_info.Protect & PAGE_READWRITE)
1511           && !(last_info.Protect & PAGE_GUARD);
1512 }
1513
1514 /* Copy all registers that might point into the heap.  Frame    */
1515 /* pointer registers are included in case client code was       */
1516 /* compiled with the 'omit frame pointer' optimization.         */
1517 /* The context register values are stored to regs argument      */
1518 /* which is expected to be of PUSHED_REGS_COUNT length exactly. */
1519 /* The functions returns the context stack pointer value.       */
1520 static ptr_t copy_ptr_regs(word *regs, const CONTEXT *pcontext) {
1521     ptr_t sp;
1522     int cnt = 0;
1523 #   define context (*pcontext)
1524 #   define PUSH1(reg) (regs[cnt++] = (word)pcontext->reg)
1525 #   define PUSH2(r1,r2) (PUSH1(r1), PUSH1(r2))
1526 #   define PUSH4(r1,r2,r3,r4) (PUSH2(r1,r2), PUSH2(r3,r4))
1527 #   if defined(I386)
1528 #     ifdef WOW64_THREAD_CONTEXT_WORKAROUND
1529         PUSH2(ContextFlags, SegFs); /* cannot contain pointers */
1530 #     endif
1531       PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp);
1532       sp = (ptr_t)context.Esp;
1533 #   elif defined(X86_64)
1534       PUSH4(Rax,Rcx,Rdx,Rbx); PUSH2(Rbp, Rsi); PUSH1(Rdi);
1535       PUSH4(R8, R9, R10, R11); PUSH4(R12, R13, R14, R15);
1536       sp = (ptr_t)context.Rsp;
1537 #   elif defined(ARM32)
1538       PUSH4(R0,R1,R2,R3),PUSH4(R4,R5,R6,R7),PUSH4(R8,R9,R10,R11);
1539       PUSH1(R12);
1540       sp = (ptr_t)context.Sp;
1541 #   elif defined(AARCH64)
1542       PUSH4(X0,X1,X2,X3),PUSH4(X4,X5,X6,X7),PUSH4(X8,X9,X10,X11);
1543       PUSH4(X12,X13,X14,X15),PUSH4(X16,X17,X18,X19),PUSH4(X20,X21,X22,X23);
1544       PUSH4(X24,X25,X26,X27),PUSH1(X28);
1545       PUSH1(Lr);
1546       sp = (ptr_t)context.Sp;
1547 #   elif defined(SHx)
1548       PUSH4(R0,R1,R2,R3), PUSH4(R4,R5,R6,R7), PUSH4(R8,R9,R10,R11);
1549       PUSH2(R12,R13), PUSH1(R14);
1550       sp = (ptr_t)context.R15;
1551 #   elif defined(MIPS)
1552       PUSH4(IntAt,IntV0,IntV1,IntA0), PUSH4(IntA1,IntA2,IntA3,IntT0);
1553       PUSH4(IntT1,IntT2,IntT3,IntT4), PUSH4(IntT5,IntT6,IntT7,IntS0);
1554       PUSH4(IntS1,IntS2,IntS3,IntS4), PUSH4(IntS5,IntS6,IntS7,IntT8);
1555       PUSH4(IntT9,IntK0,IntK1,IntS8);
1556       sp = (ptr_t)context.IntSp;
1557 #   elif defined(PPC)
1558       PUSH4(Gpr0, Gpr3, Gpr4, Gpr5),  PUSH4(Gpr6, Gpr7, Gpr8, Gpr9);
1559       PUSH4(Gpr10,Gpr11,Gpr12,Gpr14), PUSH4(Gpr15,Gpr16,Gpr17,Gpr18);
1560       PUSH4(Gpr19,Gpr20,Gpr21,Gpr22), PUSH4(Gpr23,Gpr24,Gpr25,Gpr26);
1561       PUSH4(Gpr27,Gpr28,Gpr29,Gpr30), PUSH1(Gpr31);
1562       sp = (ptr_t)context.Gpr1;
1563 #   elif defined(ALPHA)
1564       PUSH4(IntV0,IntT0,IntT1,IntT2), PUSH4(IntT3,IntT4,IntT5,IntT6);
1565       PUSH4(IntT7,IntS0,IntS1,IntS2), PUSH4(IntS3,IntS4,IntS5,IntFp);
1566       PUSH4(IntA0,IntA1,IntA2,IntA3), PUSH4(IntA4,IntA5,IntT8,IntT9);
1567       PUSH4(IntT10,IntT11,IntT12,IntAt);
1568       sp = (ptr_t)context.IntSp;
1569 #   elif defined(CPPCHECK)
1570       sp = (ptr_t)(word)cnt; /* to workaround "cnt not used" false positive */
1571 #   else
1572 #     error Architecture is not supported
1573 #   endif
1574 #   undef context
1575     GC_ASSERT(cnt == PUSHED_REGS_COUNT);
1576     return sp;
1577 }
1578
1579 STATIC word GC_push_stack_for(GC_thread thread, DWORD me)
1580 {
1581   ptr_t sp, stack_min;
1582
1583   struct GC_traced_stack_sect_s *traced_stack_sect =
1584                                       thread -> traced_stack_sect;
1585   if (thread -> id == me) {
1586     GC_ASSERT(thread -> thread_blocked_sp == NULL);
1587     sp = GC_approx_sp();
1588   } else if ((sp = thread -> thread_blocked_sp) == NULL) {
1589               /* Use saved sp value for blocked threads. */
1590 #   ifdef RETRY_GET_THREAD_CONTEXT
1591       /* We cache context when suspending the thread since it may       */
1592       /* require looping.                                               */
1593       word *regs = thread->context_regs;
1594
1595       sp = thread->context_sp;
1596 #   else
1597       /* For unblocked threads call GetThreadContext(). */
1598       word regs[PUSHED_REGS_COUNT];
1599       {
1600         CONTEXT context;
1601
1602         context.ContextFlags = GET_THREAD_CONTEXT_FLAGS;
1603         if (!GetThreadContext(THREAD_HANDLE(thread), &context))
1604           ABORT("GetThreadContext failed");
1605         sp = copy_ptr_regs(regs, &context);
1606       }
1607 #   endif
1608
1609 #   ifndef WOW64_THREAD_CONTEXT_WORKAROUND
1610       GC_push_many_regs(regs, PUSHED_REGS_COUNT);
1611 #   else
1612       GC_push_many_regs(regs + 2, PUSHED_REGS_COUNT - 2);
1613                                         /* skip ContextFlags and SegFs */
1614
1615       /* WoW64 workaround. */
1616       if (isWow64) {
1617         DWORD ContextFlags = (DWORD)regs[0];
1618         WORD SegFs = (WORD)regs[1];
1619
1620         if ((ContextFlags & CONTEXT_EXCEPTION_REPORTING) != 0
1621             && (ContextFlags & (CONTEXT_EXCEPTION_ACTIVE
1622                                 /* | CONTEXT_SERVICE_ACTIVE */)) != 0) {
1623           LDT_ENTRY selector;
1624           PNT_TIB tib;
1625
1626           if (!GetThreadSelectorEntry(THREAD_HANDLE(thread), SegFs, &selector))
1627             ABORT("GetThreadSelectorEntry failed");
1628           tib = (PNT_TIB)(selector.BaseLow
1629                           | (selector.HighWord.Bits.BaseMid << 16)
1630                           | (selector.HighWord.Bits.BaseHi << 24));
1631 #         ifdef DEBUG_THREADS
1632             GC_log_printf("TIB stack limit/base: %p .. %p\n",
1633                           (void *)tib->StackLimit, (void *)tib->StackBase);
1634 #         endif
1635           GC_ASSERT(!((word)thread->stack_base
1636                       COOLER_THAN (word)tib->StackBase));
1637           if (thread->stack_base != thread->initial_stack_base
1638               /* We are in a coroutine. */
1639               && ((word)thread->stack_base <= (word)tib->StackLimit
1640                   || (word)tib->StackBase < (word)thread->stack_base)) {
1641             /* The coroutine stack is not within TIB stack.   */
1642             WARN("GetThreadContext might return stale register values"
1643                  " including ESP=%p\n", sp);
1644             /* TODO: Because of WoW64 bug, there is no guarantee that   */
1645             /* sp really points to the stack top but, for now, we do    */
1646             /* our best as the TIB stack limit/base cannot be used      */
1647             /* while we are inside a coroutine.                         */
1648           } else {
1649             /* GetThreadContext() might return stale register values,   */
1650             /* so we scan the entire stack region (down to the stack    */
1651             /* limit).  There is no 100% guarantee that all the         */
1652             /* registers are pushed but we do our best (the proper      */
1653             /* solution would be to fix it inside Windows OS).          */
1654             sp = (ptr_t)tib->StackLimit;
1655           }
1656         } /* else */
1657 #       ifdef DEBUG_THREADS
1658           else {
1659             static GC_bool logged;
1660             if (!logged
1661                 && (ContextFlags & CONTEXT_EXCEPTION_REPORTING) == 0) {
1662               GC_log_printf("CONTEXT_EXCEPTION_REQUEST not supported\n");
1663               logged = TRUE;
1664             }
1665           }
1666 #       endif
1667       }
1668 #   endif /* WOW64_THREAD_CONTEXT_WORKAROUND */
1669   } /* ! current thread */
1670
1671   /* Set stack_min to the lowest address in the thread stack,   */
1672   /* or to an address in the thread stack no larger than sp,    */
1673   /* taking advantage of the old value to avoid slow traversals */
1674   /* of large stacks.                                           */
1675   if (thread -> last_stack_min == ADDR_LIMIT) {
1676 #   ifdef MSWINCE
1677       if (GC_dont_query_stack_min) {
1678         stack_min = GC_wince_evaluate_stack_min(traced_stack_sect != NULL ?
1679                       (ptr_t)traced_stack_sect : thread -> stack_base);
1680         /* Keep last_stack_min value unmodified. */
1681       } else
1682 #   endif
1683     /* else */ {
1684       stack_min = GC_get_stack_min(traced_stack_sect != NULL ?
1685                       (ptr_t)traced_stack_sect : thread -> stack_base);
1686       UNPROTECT_THREAD(thread);
1687       thread -> last_stack_min = stack_min;
1688     }
1689   } else {
1690     /* First, adjust the latest known minimum stack address if we       */
1691     /* are inside GC_call_with_gc_active().                             */
1692     if (traced_stack_sect != NULL &&
1693         (word)thread->last_stack_min > (word)traced_stack_sect) {
1694       UNPROTECT_THREAD(thread);
1695       thread -> last_stack_min = (ptr_t)traced_stack_sect;
1696     }
1697
1698     if ((word)sp < (word)thread->stack_base
1699         && (word)sp >= (word)thread->last_stack_min) {
1700       stack_min = sp;
1701     } else {
1702       /* In the current thread it is always safe to use sp value.       */
1703       if (may_be_in_stack(thread -> id == me &&
1704                           (word)sp < (word)thread->last_stack_min ?
1705                           sp : thread -> last_stack_min)) {
1706         stack_min = (ptr_t)last_info.BaseAddress;
1707         /* Do not probe rest of the stack if sp is correct. */
1708         if ((word)sp < (word)stack_min
1709             || (word)sp >= (word)thread->stack_base)
1710           stack_min = GC_get_stack_min(thread -> last_stack_min);
1711       } else {
1712         /* Stack shrunk?  Is this possible? */
1713         stack_min = GC_get_stack_min(thread -> stack_base);
1714       }
1715       UNPROTECT_THREAD(thread);
1716       thread -> last_stack_min = stack_min;
1717     }
1718   }
1719
1720   GC_ASSERT(GC_dont_query_stack_min
1721             || stack_min == GC_get_stack_min(thread -> stack_base)
1722             || ((word)sp >= (word)stack_min
1723                 && (word)stack_min < (word)thread->stack_base
1724                 && (word)stack_min
1725                         > (word)GC_get_stack_min(thread -> stack_base)));
1726
1727   if ((word)sp >= (word)stack_min && (word)sp < (word)thread->stack_base) {
1728 #   ifdef DEBUG_THREADS
1729       GC_log_printf("Pushing stack for 0x%x from sp %p to %p from 0x%x\n",
1730                     (int)thread->id, (void *)sp, (void *)thread->stack_base,
1731                     (int)me);
1732 #   endif
1733     GC_push_all_stack_sections(sp, thread->stack_base, traced_stack_sect);
1734   } else {
1735     /* If not current thread then it is possible for sp to point to     */
1736     /* the guarded (untouched yet) page just below the current          */
1737     /* stack_min of the thread.                                         */
1738     if (thread -> id == me || (word)sp >= (word)thread->stack_base
1739         || (word)(sp + GC_page_size) < (word)stack_min)
1740       WARN("Thread stack pointer %p out of range, pushing everything\n",
1741            sp);
1742 #   ifdef DEBUG_THREADS
1743       GC_log_printf("Pushing stack for 0x%x from (min) %p to %p from 0x%x\n",
1744                     (int)thread->id, (void *)stack_min,
1745                     (void *)thread->stack_base, (int)me);
1746 #   endif
1747     /* Push everything - ignore "traced stack section" data.            */
1748     GC_push_all_stack(stack_min, thread->stack_base);
1749   }
1750   return thread->stack_base - sp; /* stack grows down */
1751 }
1752
1753 GC_INNER void GC_push_all_stacks(void)
1754 {
1755   DWORD thread_id = GetCurrentThreadId();
1756   GC_bool found_me = FALSE;
1757 # ifndef SMALL_CONFIG
1758     unsigned nthreads = 0;
1759 # endif
1760   word total_size = 0;
1761 # ifndef GC_NO_THREADS_DISCOVERY
1762     if (GC_win32_dll_threads) {
1763       int i;
1764       LONG my_max = GC_get_max_thread_index();
1765
1766       for (i = 0; i <= my_max; i++) {
1767         GC_thread t = (GC_thread)(dll_thread_table + i);
1768         if (t -> tm.in_use && t -> stack_base) {
1769 #         ifndef SMALL_CONFIG
1770             ++nthreads;
1771 #         endif
1772           total_size += GC_push_stack_for(t, thread_id);
1773           if (t -> id == thread_id) found_me = TRUE;
1774         }
1775       }
1776     } else
1777 # endif
1778   /* else */ {
1779     int i;
1780     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1781       GC_thread t;
1782       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1783         if (!KNOWN_FINISHED(t) && t -> stack_base) {
1784 #         ifndef SMALL_CONFIG
1785             ++nthreads;
1786 #         endif
1787           total_size += GC_push_stack_for(t, thread_id);
1788           if (t -> id == thread_id) found_me = TRUE;
1789         }
1790       }
1791     }
1792   }
1793 # ifndef SMALL_CONFIG
1794     GC_VERBOSE_LOG_PRINTF("Pushed %d thread stacks%s\n", nthreads,
1795                           GC_win32_dll_threads ?
1796                                 " based on DllMain thread tracking" : "");
1797 # endif
1798   if (!found_me && !GC_in_thread_creation)
1799     ABORT("Collecting from unknown thread");
1800   GC_total_stacksize = total_size;
1801 }
1802
1803 #ifdef PARALLEL_MARK
1804
1805 # ifndef MAX_MARKERS
1806 #   define MAX_MARKERS 16
1807 # endif
1808
1809   static ptr_t marker_sp[MAX_MARKERS - 1]; /* The cold end of the stack */
1810                                            /* for markers.              */
1811 # ifdef IA64
1812     static ptr_t marker_bsp[MAX_MARKERS - 1];
1813 # endif
1814
1815   static ptr_t marker_last_stack_min[MAX_MARKERS - 1];
1816                                 /* Last known minimum (hottest) address */
1817                                 /* in stack (or ADDR_LIMIT if unset)    */
1818                                 /* for markers.                         */
1819
1820 #endif /* PARALLEL_MARK */
1821
1822 /* Find stack with the lowest address which overlaps the        */
1823 /* interval [start, limit).                                     */
1824 /* Return stack bounds in *lo and *hi.  If no such stack        */
1825 /* is found, both *hi and *lo will be set to an address         */
1826 /* higher than limit.                                           */
1827 GC_INNER void GC_get_next_stack(char *start, char *limit,
1828                                 char **lo, char **hi)
1829 {
1830   int i;
1831   char * current_min = ADDR_LIMIT;  /* Least in-range stack base      */
1832   ptr_t *plast_stack_min = NULL;    /* Address of last_stack_min      */
1833                                     /* field for thread corresponding */
1834                                     /* to current_min.                */
1835   GC_thread thread = NULL;          /* Either NULL or points to the   */
1836                                     /* thread's hash table entry      */
1837                                     /* containing *plast_stack_min.   */
1838
1839   /* First set current_min, ignoring limit. */
1840   if (GC_win32_dll_threads) {
1841     LONG my_max = GC_get_max_thread_index();
1842
1843     for (i = 0; i <= my_max; i++) {
1844       ptr_t s = (ptr_t)(dll_thread_table[i].stack_base);
1845
1846       if ((word)s > (word)start && (word)s < (word)current_min) {
1847         /* Update address of last_stack_min. */
1848         plast_stack_min = (ptr_t * /* no volatile */)
1849                             &dll_thread_table[i].last_stack_min;
1850         current_min = s;
1851 #       if defined(CPPCHECK)
1852           /* To avoid a warning that thread is always null.     */
1853           thread = (GC_thread)&dll_thread_table[i];
1854 #       endif
1855       }
1856     }
1857   } else {
1858     for (i = 0; i < THREAD_TABLE_SZ; i++) {
1859       GC_thread t;
1860
1861       for (t = GC_threads[i]; t != 0; t = t -> tm.next) {
1862         ptr_t s = t -> stack_base;
1863
1864         if ((word)s > (word)start && (word)s < (word)current_min) {
1865           /* Update address of last_stack_min. */
1866           plast_stack_min = &t -> last_stack_min;
1867           thread = t; /* Remember current thread to unprotect. */
1868           current_min = s;
1869         }
1870       }
1871     }
1872 #   ifdef PARALLEL_MARK
1873       for (i = 0; i < GC_markers_m1; ++i) {
1874         ptr_t s = marker_sp[i];
1875 #       ifdef IA64
1876           /* FIXME: not implemented */
1877 #       endif
1878         if ((word)s > (word)start && (word)s < (word)current_min) {
1879           GC_ASSERT(marker_last_stack_min[i] != NULL);
1880           plast_stack_min = &marker_last_stack_min[i];
1881           current_min = s;
1882           thread = NULL; /* Not a thread's hash table entry. */
1883         }
1884       }
1885 #   endif
1886   }
1887
1888   *hi = current_min;
1889   if (current_min == ADDR_LIMIT) {
1890       *lo = ADDR_LIMIT;
1891       return;
1892   }
1893
1894   GC_ASSERT((word)current_min > (word)start && plast_stack_min != NULL);
1895 # ifdef MSWINCE
1896     if (GC_dont_query_stack_min) {
1897       *lo = GC_wince_evaluate_stack_min(current_min);
1898       /* Keep last_stack_min value unmodified. */
1899       return;
1900     }
1901 # endif
1902
1903   if ((word)current_min > (word)limit && !may_be_in_stack(limit)) {
1904     /* Skip the rest since the memory region at limit address is        */
1905     /* not a stack (so the lowest address of the found stack would      */
1906     /* be above the limit value anyway).                                */
1907     *lo = ADDR_LIMIT;
1908     return;
1909   }
1910
1911   /* Get the minimum address of the found stack by probing its memory   */
1912   /* region starting from the recent known minimum (if set).            */
1913   if (*plast_stack_min == ADDR_LIMIT
1914       || !may_be_in_stack(*plast_stack_min)) {
1915     /* Unsafe to start from last_stack_min value. */
1916     *lo = GC_get_stack_min(current_min);
1917   } else {
1918     /* Use the recent value to optimize search for min address. */
1919     *lo = GC_get_stack_min(*plast_stack_min);
1920   }
1921
1922   /* Remember current stack_min value. */
1923   if (thread != NULL) {
1924     UNPROTECT_THREAD(thread);
1925   }
1926   *plast_stack_min = *lo;
1927 }
1928
1929 #ifdef PARALLEL_MARK
1930
1931 # if defined(GC_PTHREADS) && !defined(GC_PTHREADS_PARAMARK)
1932     /* Use pthread-based parallel mark implementation.    */
1933
1934     /* Workaround a deadlock in winpthreads-3.0b internals (observed    */
1935     /* with MinGW 32/64).                                               */
1936 #   if !defined(__MINGW32__)
1937 #     define GC_PTHREADS_PARAMARK
1938 #   endif
1939 # endif
1940
1941 # if !defined(GC_PTHREADS_PARAMARK)
1942     STATIC HANDLE GC_marker_cv[MAX_MARKERS - 1] = {0};
1943                         /* Events with manual reset (one for each       */
1944                         /* mark helper).                                */
1945
1946     STATIC DWORD GC_marker_Id[MAX_MARKERS - 1] = {0};
1947                         /* This table is used for mapping helper        */
1948                         /* threads ID to mark helper index (linear      */
1949                         /* search is used since the mapping contains    */
1950                         /* only a few entries).                         */
1951 # endif
1952
1953   /* GC_mark_thread() is the same as in pthread_support.c */
1954 # ifdef GC_PTHREADS_PARAMARK
1955     STATIC void * GC_mark_thread(void * id)
1956 # elif defined(MSWINCE)
1957     STATIC DWORD WINAPI GC_mark_thread(LPVOID id)
1958 # else
1959     STATIC unsigned __stdcall GC_mark_thread(void * id)
1960 # endif
1961   {
1962     word my_mark_no = 0;
1963
1964     if ((word)id == GC_WORD_MAX) return 0; /* to prevent a compiler warning */
1965     marker_sp[(word)id] = GC_approx_sp();
1966 #   ifdef IA64
1967       marker_bsp[(word)id] = GC_save_regs_in_stack();
1968 #   endif
1969 #   if !defined(GC_PTHREADS_PARAMARK)
1970       GC_marker_Id[(word)id] = GetCurrentThreadId();
1971 #   endif
1972
1973     /* Inform GC_start_mark_threads about completion of marker data init. */
1974     GC_acquire_mark_lock();
1975     if (0 == --GC_fl_builder_count) /* count may have a negative value */
1976       GC_notify_all_builder();
1977
1978     for (;; ++my_mark_no) {
1979       if (my_mark_no - GC_mark_no > (word)2) {
1980         /* resynchronize if we get far off, e.g. because GC_mark_no     */
1981         /* wrapped.                                                     */
1982         my_mark_no = GC_mark_no;
1983       }
1984 #     ifdef DEBUG_THREADS
1985         GC_log_printf("Starting mark helper for mark number %lu\n",
1986                       (unsigned long)my_mark_no);
1987 #     endif
1988       GC_help_marker(my_mark_no);
1989     }
1990   }
1991
1992 # ifndef GC_ASSERTIONS
1993 #   define SET_MARK_LOCK_HOLDER (void)0
1994 #   define UNSET_MARK_LOCK_HOLDER (void)0
1995 # endif
1996
1997   /* GC_mark_threads[] is unused here unlike that in pthread_support.c  */
1998
1999 # ifdef CAN_HANDLE_FORK
2000     static int available_markers_m1 = 0;
2001 # else
2002 #   define available_markers_m1 GC_markers_m1
2003 # endif
2004
2005 # ifdef GC_PTHREADS_PARAMARK
2006 #   include <pthread.h>
2007
2008 #   if defined(GC_ASSERTIONS) && !defined(NUMERIC_THREAD_ID)
2009 #     define NUMERIC_THREAD_ID(id) (unsigned long)(word)GC_PTHREAD_PTRVAL(id)
2010       /* Id not guaranteed to be unique. */
2011 #   endif
2012
2013 #   ifdef CAN_HANDLE_FORK
2014       static pthread_cond_t mark_cv;
2015                         /* initialized by GC_start_mark_threads_inner   */
2016 #   else
2017       static pthread_cond_t mark_cv = PTHREAD_COND_INITIALIZER;
2018 #   endif
2019
2020     /* GC_start_mark_threads is the same as in pthread_support.c except */
2021     /* for thread stack that is assumed to be large enough.             */
2022
2023     GC_INNER void GC_start_mark_threads_inner(void)
2024     {
2025       int i;
2026       pthread_attr_t attr;
2027       pthread_t new_thread;
2028 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2029         sigset_t set, oldset;
2030 #     endif
2031
2032       GC_ASSERT(I_DONT_HOLD_LOCK());
2033       if (available_markers_m1 <= 0) return;
2034                 /* Skip if parallel markers disabled or already started. */
2035 #     ifdef CAN_HANDLE_FORK
2036         if (GC_parallel) return;
2037
2038         /* Reset mark_cv state after forking (as in pthread_support.c). */
2039         {
2040           pthread_cond_t mark_cv_local = PTHREAD_COND_INITIALIZER;
2041           BCOPY(&mark_cv_local, &mark_cv, sizeof(mark_cv));
2042         }
2043 #     endif
2044
2045       GC_ASSERT(GC_fl_builder_count == 0);
2046       if (0 != pthread_attr_init(&attr)) ABORT("pthread_attr_init failed");
2047       if (0 != pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))
2048         ABORT("pthread_attr_setdetachstate failed");
2049
2050 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2051         /* Apply special signal mask to GC marker threads, and don't drop */
2052         /* user defined signals by GC marker threads.                     */
2053         if (sigfillset(&set) != 0)
2054           ABORT("sigfillset failed");
2055         if (pthread_sigmask(SIG_BLOCK, &set, &oldset) < 0) {
2056           WARN("pthread_sigmask set failed, no markers started,"
2057                " errno = %" WARN_PRIdPTR "\n", errno);
2058           GC_markers_m1 = 0;
2059           (void)pthread_attr_destroy(&attr);
2060           return;
2061         }
2062 #     endif /* !NO_MARKER_SPECIAL_SIGMASK */
2063
2064 #     ifdef CAN_HANDLE_FORK
2065         /* To have proper GC_parallel value in GC_help_marker.  */
2066         GC_markers_m1 = available_markers_m1;
2067 #     endif
2068       for (i = 0; i < available_markers_m1; ++i) {
2069         marker_last_stack_min[i] = ADDR_LIMIT;
2070         if (0 != pthread_create(&new_thread, &attr,
2071                                 GC_mark_thread, (void *)(word)i)) {
2072           WARN("Marker thread creation failed\n", 0);
2073           /* Don't try to create other marker threads.    */
2074           GC_markers_m1 = i;
2075           break;
2076         }
2077       }
2078
2079 #     ifndef NO_MARKER_SPECIAL_SIGMASK
2080         /* Restore previous signal mask.        */
2081         if (pthread_sigmask(SIG_SETMASK, &oldset, NULL) < 0) {
2082           WARN("pthread_sigmask restore failed, errno = %" WARN_PRIdPTR "\n",
2083                errno);
2084         }
2085 #     endif
2086
2087       (void)pthread_attr_destroy(&attr);
2088       GC_wait_for_markers_init();
2089       GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1);
2090     }
2091
2092 #   ifdef GC_ASSERTIONS
2093       STATIC unsigned long GC_mark_lock_holder = NO_THREAD;
2094 #     define SET_MARK_LOCK_HOLDER \
2095                 (void)(GC_mark_lock_holder = NUMERIC_THREAD_ID(pthread_self()))
2096 #     define UNSET_MARK_LOCK_HOLDER \
2097                 do { \
2098                   GC_ASSERT(GC_mark_lock_holder \
2099                                 == NUMERIC_THREAD_ID(pthread_self())); \
2100                   GC_mark_lock_holder = NO_THREAD; \
2101                 } while (0)
2102 #   endif /* GC_ASSERTIONS */
2103
2104     static pthread_mutex_t mark_mutex = PTHREAD_MUTEX_INITIALIZER;
2105
2106     static pthread_cond_t builder_cv = PTHREAD_COND_INITIALIZER;
2107
2108     /* GC_acquire/release_mark_lock(), GC_wait_builder/marker(),          */
2109     /* GC_wait_for_reclaim(), GC_notify_all_builder/marker() are the same */
2110     /* as in pthread_support.c except that GC_generic_lock() is not used. */
2111
2112 #   ifdef LOCK_STATS
2113       volatile AO_t GC_block_count = 0;
2114 #   endif
2115
2116     GC_INNER void GC_acquire_mark_lock(void)
2117     {
2118 #     if defined(NUMERIC_THREAD_ID_UNIQUE) && !defined(THREAD_SANITIZER)
2119         GC_ASSERT(GC_mark_lock_holder != NUMERIC_THREAD_ID(pthread_self()));
2120 #     endif
2121       if (pthread_mutex_lock(&mark_mutex) != 0) {
2122         ABORT("pthread_mutex_lock failed");
2123       }
2124 #     ifdef LOCK_STATS
2125         (void)AO_fetch_and_add1(&GC_block_count);
2126 #     endif
2127       /* GC_generic_lock(&mark_mutex); */
2128       SET_MARK_LOCK_HOLDER;
2129     }
2130
2131     GC_INNER void GC_release_mark_lock(void)
2132     {
2133       UNSET_MARK_LOCK_HOLDER;
2134       if (pthread_mutex_unlock(&mark_mutex) != 0) {
2135         ABORT("pthread_mutex_unlock failed");
2136       }
2137     }
2138
2139     /* Collector must wait for a freelist builders for 2 reasons:       */
2140     /* 1) Mark bits may still be getting examined without lock.         */
2141     /* 2) Partial free lists referenced only by locals may not be       */
2142     /* scanned correctly, e.g. if they contain "pointer-free" objects,  */
2143     /* since the free-list link may be ignored.                         */
2144     STATIC void GC_wait_builder(void)
2145     {
2146       UNSET_MARK_LOCK_HOLDER;
2147       if (pthread_cond_wait(&builder_cv, &mark_mutex) != 0) {
2148         ABORT("pthread_cond_wait failed");
2149       }
2150       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2151       SET_MARK_LOCK_HOLDER;
2152     }
2153
2154     GC_INNER void GC_wait_for_reclaim(void)
2155     {
2156       GC_acquire_mark_lock();
2157       while (GC_fl_builder_count > 0) {
2158         GC_wait_builder();
2159       }
2160       GC_release_mark_lock();
2161     }
2162
2163     GC_INNER void GC_notify_all_builder(void)
2164     {
2165       GC_ASSERT(GC_mark_lock_holder == NUMERIC_THREAD_ID(pthread_self()));
2166       if (pthread_cond_broadcast(&builder_cv) != 0) {
2167         ABORT("pthread_cond_broadcast failed");
2168       }
2169     }
2170
2171     GC_INNER void GC_wait_marker(void)
2172     {
2173       GC_ASSERT(GC_parallel);
2174       UNSET_MARK_LOCK_HOLDER;
2175       if (pthread_cond_wait(&mark_cv, &mark_mutex) != 0) {
2176         ABORT("pthread_cond_wait failed");
2177       }
2178       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2179       SET_MARK_LOCK_HOLDER;
2180     }
2181
2182     GC_INNER void GC_notify_all_marker(void)
2183     {
2184       GC_ASSERT(GC_parallel);
2185       if (pthread_cond_broadcast(&mark_cv) != 0) {
2186         ABORT("pthread_cond_broadcast failed");
2187       }
2188     }
2189
2190 # else /* ! GC_PTHREADS_PARAMARK */
2191
2192 #   ifndef MARK_THREAD_STACK_SIZE
2193 #     define MARK_THREAD_STACK_SIZE 0   /* default value */
2194 #   endif
2195
2196     /* mark_mutex_event, builder_cv, mark_cv are initialized in GC_thr_init */
2197     static HANDLE mark_mutex_event = (HANDLE)0; /* Event with auto-reset.   */
2198     static HANDLE builder_cv = (HANDLE)0; /* Event with manual reset.       */
2199     static HANDLE mark_cv = (HANDLE)0; /* Event with manual reset.          */
2200
2201     GC_INNER void GC_start_mark_threads_inner(void)
2202     {
2203       int i;
2204
2205       GC_ASSERT(I_DONT_HOLD_LOCK());
2206       if (available_markers_m1 <= 0) return;
2207
2208       GC_ASSERT(GC_fl_builder_count == 0);
2209       /* Initialize GC_marker_cv[] fully before starting the    */
2210       /* first helper thread.                                   */
2211       for (i = 0; i < GC_markers_m1; ++i) {
2212         if ((GC_marker_cv[i] = CreateEvent(NULL /* attrs */,
2213                                         TRUE /* isManualReset */,
2214                                         FALSE /* initialState */,
2215                                         NULL /* name (A/W) */)) == (HANDLE)0)
2216           ABORT("CreateEvent failed");
2217       }
2218
2219       for (i = 0; i < GC_markers_m1; ++i) {
2220 #       if defined(MSWINCE) || defined(MSWIN_XBOX1)
2221           HANDLE handle;
2222           DWORD thread_id;
2223
2224           marker_last_stack_min[i] = ADDR_LIMIT;
2225           /* There is no _beginthreadex() in WinCE. */
2226           handle = CreateThread(NULL /* lpsa */,
2227                                 MARK_THREAD_STACK_SIZE /* ignored */,
2228                                 GC_mark_thread, (LPVOID)(word)i,
2229                                 0 /* fdwCreate */, &thread_id);
2230           if (handle == NULL) {
2231             WARN("Marker thread creation failed\n", 0);
2232             /* The most probable failure reason is "not enough memory". */
2233             /* Don't try to create other marker threads.                */
2234             break;
2235           } else {
2236             /* It's safe to detach the thread.  */
2237             CloseHandle(handle);
2238           }
2239 #       else
2240           GC_uintptr_t handle;
2241           unsigned thread_id;
2242
2243           marker_last_stack_min[i] = ADDR_LIMIT;
2244           handle = _beginthreadex(NULL /* security_attr */,
2245                                 MARK_THREAD_STACK_SIZE, GC_mark_thread,
2246                                 (void *)(word)i, 0 /* flags */, &thread_id);
2247           if (!handle || handle == (GC_uintptr_t)-1L) {
2248             WARN("Marker thread creation failed\n", 0);
2249             /* Don't try to create other marker threads.                */
2250             break;
2251           } else {/* We may detach the thread (if handle is of HANDLE type) */
2252             /* CloseHandle((HANDLE)handle); */
2253           }
2254 #       endif
2255       }
2256
2257       /* Adjust GC_markers_m1 (and free unused resources) if failed.    */
2258       while (GC_markers_m1 > i) {
2259         GC_markers_m1--;
2260         CloseHandle(GC_marker_cv[GC_markers_m1]);
2261       }
2262       GC_wait_for_markers_init();
2263       GC_COND_LOG_PRINTF("Started %d mark helper threads\n", GC_markers_m1);
2264       if (i == 0) {
2265         CloseHandle(mark_cv);
2266         CloseHandle(builder_cv);
2267         CloseHandle(mark_mutex_event);
2268       }
2269     }
2270
2271 #   ifdef GC_ASSERTIONS
2272       STATIC DWORD GC_mark_lock_holder = NO_THREAD;
2273 #     define SET_MARK_LOCK_HOLDER \
2274                 (void)(GC_mark_lock_holder = GetCurrentThreadId())
2275 #     define UNSET_MARK_LOCK_HOLDER \
2276                 do { \
2277                   GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId()); \
2278                   GC_mark_lock_holder = NO_THREAD; \
2279                 } while (0)
2280 #   endif /* GC_ASSERTIONS */
2281
2282     STATIC /* volatile */ LONG GC_mark_mutex_state = 0;
2283                                 /* Mutex state: 0 - unlocked,           */
2284                                 /* 1 - locked and no other waiters,     */
2285                                 /* -1 - locked and waiters may exist.   */
2286                                 /* Accessed by InterlockedExchange().   */
2287
2288     /* #define LOCK_STATS */
2289 #   ifdef LOCK_STATS
2290       volatile AO_t GC_block_count = 0;
2291       volatile AO_t GC_unlocked_count = 0;
2292 #   endif
2293
2294     GC_INNER void GC_acquire_mark_lock(void)
2295     {
2296 #     ifndef THREAD_SANITIZER
2297         GC_ASSERT(GC_mark_lock_holder != GetCurrentThreadId());
2298 #     endif
2299       if (InterlockedExchange(&GC_mark_mutex_state, 1 /* locked */) != 0) {
2300 #       ifdef LOCK_STATS
2301           (void)AO_fetch_and_add1(&GC_block_count);
2302 #       endif
2303         /* Repeatedly reset the state and wait until acquire the lock.  */
2304         while (InterlockedExchange(&GC_mark_mutex_state,
2305                                    -1 /* locked_and_has_waiters */) != 0) {
2306           if (WaitForSingleObject(mark_mutex_event, INFINITE) == WAIT_FAILED)
2307             ABORT("WaitForSingleObject failed");
2308         }
2309       }
2310 #     ifdef LOCK_STATS
2311         else {
2312           (void)AO_fetch_and_add1(&GC_unlocked_count);
2313         }
2314 #     endif
2315
2316       GC_ASSERT(GC_mark_lock_holder == NO_THREAD);
2317       SET_MARK_LOCK_HOLDER;
2318     }
2319
2320     GC_INNER void GC_release_mark_lock(void)
2321     {
2322       UNSET_MARK_LOCK_HOLDER;
2323       if (InterlockedExchange(&GC_mark_mutex_state, 0 /* unlocked */) < 0) {
2324         /* wake a waiter */
2325         if (SetEvent(mark_mutex_event) == FALSE)
2326           ABORT("SetEvent failed");
2327       }
2328     }
2329
2330     /* In GC_wait_for_reclaim/GC_notify_all_builder() we emulate POSIX    */
2331     /* cond_wait/cond_broadcast() primitives with WinAPI Event object     */
2332     /* (working in "manual reset" mode).  This works here because         */
2333     /* GC_notify_all_builder() is always called holding lock on           */
2334     /* mark_mutex and the checked condition (GC_fl_builder_count == 0)    */
2335     /* is the only one for which broadcasting on builder_cv is performed. */
2336
2337     GC_INNER void GC_wait_for_reclaim(void)
2338     {
2339       GC_ASSERT(builder_cv != 0);
2340       for (;;) {
2341         GC_acquire_mark_lock();
2342         if (GC_fl_builder_count == 0)
2343           break;
2344         if (ResetEvent(builder_cv) == FALSE)
2345           ABORT("ResetEvent failed");
2346         GC_release_mark_lock();
2347         if (WaitForSingleObject(builder_cv, INFINITE) == WAIT_FAILED)
2348           ABORT("WaitForSingleObject failed");
2349       }
2350       GC_release_mark_lock();
2351     }
2352
2353     GC_INNER void GC_notify_all_builder(void)
2354     {
2355       GC_ASSERT(GC_mark_lock_holder == GetCurrentThreadId());
2356       GC_ASSERT(builder_cv != 0);
2357       GC_ASSERT(GC_fl_builder_count == 0);
2358       if (SetEvent(builder_cv) == FALSE)
2359         ABORT("SetEvent failed");
2360     }
2361
2362     /* mark_cv is used (for waiting) by a non-helper thread.    */
2363
2364     GC_INNER void GC_wait_marker(void)
2365     {
2366       HANDLE event = mark_cv;
2367       DWORD thread_id = GetCurrentThreadId();
2368       int i = GC_markers_m1;
2369
2370       while (i-- > 0) {
2371         if (GC_marker_Id[i] == thread_id) {
2372           event = GC_marker_cv[i];
2373           break;
2374         }
2375       }
2376
2377       if (ResetEvent(event) == FALSE)
2378         ABORT("ResetEvent failed");
2379       GC_release_mark_lock();
2380       if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED)
2381         ABORT("WaitForSingleObject failed");
2382       GC_acquire_mark_lock();
2383     }
2384
2385     GC_INNER void GC_notify_all_marker(void)
2386     {
2387       DWORD thread_id = GetCurrentThreadId();
2388       int i = GC_markers_m1;
2389
2390       while (i-- > 0) {
2391         /* Notify every marker ignoring self (for efficiency).  */
2392         if (SetEvent(GC_marker_Id[i] != thread_id ? GC_marker_cv[i] :
2393                      mark_cv) == FALSE)
2394           ABORT("SetEvent failed");
2395       }
2396     }
2397
2398 # endif /* ! GC_PTHREADS_PARAMARK */
2399
2400 #endif /* PARALLEL_MARK */
2401
2402   /* We have no DllMain to take care of new threads.  Thus we   */
2403   /* must properly intercept thread creation.                   */
2404
2405   typedef struct {
2406     LPTHREAD_START_ROUTINE start;
2407     LPVOID param;
2408   } thread_args;
2409
2410   STATIC void * GC_CALLBACK GC_win32_start_inner(struct GC_stack_base *sb,
2411                                                  void *arg)
2412   {
2413     void * ret;
2414     LPTHREAD_START_ROUTINE start = ((thread_args *)arg)->start;
2415     LPVOID param = ((thread_args *)arg)->param;
2416
2417     GC_register_my_thread(sb); /* This waits for an in-progress GC.     */
2418
2419 #   ifdef DEBUG_THREADS
2420       GC_log_printf("thread 0x%lx starting...\n", (long)GetCurrentThreadId());
2421 #   endif
2422
2423     GC_free(arg);
2424
2425     /* Clear the thread entry even if we exit with an exception.        */
2426     /* This is probably pointless, since an uncaught exception is       */
2427     /* supposed to result in the process being killed.                  */
2428 #   if !defined(__GNUC__) && !defined(NO_CRT)
2429       ret = NULL; /* to suppress "might be uninitialized" compiler warning */
2430       __try
2431 #   endif
2432     {
2433       ret = (void *)(word)(*start)(param);
2434     }
2435 #   if !defined(__GNUC__) && !defined(NO_CRT)
2436       __finally
2437 #   endif
2438     {
2439       GC_unregister_my_thread();
2440     }
2441
2442 #   ifdef DEBUG_THREADS
2443       GC_log_printf("thread 0x%lx returned from start routine\n",
2444                     (long)GetCurrentThreadId());
2445 #   endif
2446     return ret;
2447   }
2448
2449   STATIC DWORD WINAPI GC_win32_start(LPVOID arg)
2450   {
2451     return (DWORD)(word)GC_call_with_stack_base(GC_win32_start_inner, arg);
2452   }
2453
2454   GC_API HANDLE WINAPI GC_CreateThread(
2455                         LPSECURITY_ATTRIBUTES lpThreadAttributes,
2456                         GC_WIN32_SIZE_T dwStackSize,
2457                         LPTHREAD_START_ROUTINE lpStartAddress,
2458                         LPVOID lpParameter, DWORD dwCreationFlags,
2459                         LPDWORD lpThreadId)
2460   {
2461     if (!EXPECT(parallel_initialized, TRUE))
2462       GC_init_parallel();
2463                 /* make sure GC is initialized (i.e. main thread is     */
2464                 /* attached, tls initialized).                          */
2465
2466 #   ifdef DEBUG_THREADS
2467       GC_log_printf("About to create a thread from 0x%lx\n",
2468                     (long)GetCurrentThreadId());
2469 #   endif
2470     if (GC_win32_dll_threads) {
2471       return CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress,
2472                           lpParameter, dwCreationFlags, lpThreadId);
2473     } else {
2474       thread_args *args =
2475                 (thread_args *)GC_malloc_uncollectable(sizeof(thread_args));
2476                 /* Handed off to and deallocated by child thread.       */
2477       HANDLE thread_h;
2478
2479       if (NULL == args) {
2480         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2481         return NULL;
2482       }
2483
2484       /* set up thread arguments */
2485       args -> start = lpStartAddress;
2486       args -> param = lpParameter;
2487       GC_dirty(args);
2488       REACHABLE_AFTER_DIRTY(lpParameter);
2489
2490       set_need_to_lock();
2491       thread_h = CreateThread(lpThreadAttributes, dwStackSize, GC_win32_start,
2492                               args, dwCreationFlags, lpThreadId);
2493       if (thread_h == 0) GC_free(args);
2494       return thread_h;
2495     }
2496   }
2497
2498   GC_API DECLSPEC_NORETURN void WINAPI GC_ExitThread(DWORD dwExitCode)
2499   {
2500     GC_unregister_my_thread();
2501     ExitThread(dwExitCode);
2502   }
2503
2504 # if !defined(CYGWIN32) && !defined(MSWINCE) && !defined(MSWIN_XBOX1) \
2505      && !defined(NO_CRT)
2506     GC_API GC_uintptr_t GC_CALL GC_beginthreadex(
2507                                   void *security, unsigned stack_size,
2508                                   unsigned (__stdcall *start_address)(void *),
2509                                   void *arglist, unsigned initflag,
2510                                   unsigned *thrdaddr)
2511     {
2512       if (!EXPECT(parallel_initialized, TRUE))
2513         GC_init_parallel();
2514                 /* make sure GC is initialized (i.e. main thread is     */
2515                 /* attached, tls initialized).                          */
2516 #     ifdef DEBUG_THREADS
2517         GC_log_printf("About to create a thread from 0x%lx\n",
2518                       (long)GetCurrentThreadId());
2519 #     endif
2520
2521       if (GC_win32_dll_threads) {
2522         return _beginthreadex(security, stack_size, start_address,
2523                               arglist, initflag, thrdaddr);
2524       } else {
2525         GC_uintptr_t thread_h;
2526         thread_args *args =
2527                 (thread_args *)GC_malloc_uncollectable(sizeof(thread_args));
2528                 /* Handed off to and deallocated by child thread.       */
2529
2530         if (NULL == args) {
2531           /* MSDN docs say _beginthreadex() returns 0 on error and sets */
2532           /* errno to either EAGAIN (too many threads) or EINVAL (the   */
2533           /* argument is invalid or the stack size is incorrect), so we */
2534           /* set errno to EAGAIN on "not enough memory".                */
2535           errno = EAGAIN;
2536           return 0;
2537         }
2538
2539         /* set up thread arguments */
2540         args -> start = (LPTHREAD_START_ROUTINE)start_address;
2541         args -> param = arglist;
2542         GC_dirty(args);
2543         REACHABLE_AFTER_DIRTY(arglist);
2544
2545         set_need_to_lock();
2546         thread_h = _beginthreadex(security, stack_size,
2547                         (unsigned (__stdcall *)(void *))GC_win32_start,
2548                         args, initflag, thrdaddr);
2549         if (thread_h == 0) GC_free(args);
2550         return thread_h;
2551       }
2552     }
2553
2554     GC_API void GC_CALL GC_endthreadex(unsigned retval)
2555     {
2556       GC_unregister_my_thread();
2557       _endthreadex(retval);
2558     }
2559 # endif /* !CYGWIN32 && !MSWINCE && !MSWIN_XBOX1 && !NO_CRT */
2560
2561 #ifdef GC_WINMAIN_REDIRECT
2562   /* This might be useful on WinCE.  Shouldn't be used with GC_DLL.     */
2563
2564 # if defined(MSWINCE) && defined(UNDER_CE)
2565 #   define WINMAIN_LPTSTR LPWSTR
2566 # else
2567 #   define WINMAIN_LPTSTR LPSTR
2568 # endif
2569
2570   /* This is defined in gc.h.   */
2571 # undef WinMain
2572
2573   /* Defined outside GC by an application.      */
2574   int WINAPI GC_WinMain(HINSTANCE, HINSTANCE, WINMAIN_LPTSTR, int);
2575
2576   typedef struct {
2577     HINSTANCE hInstance;
2578     HINSTANCE hPrevInstance;
2579     WINMAIN_LPTSTR lpCmdLine;
2580     int nShowCmd;
2581   } main_thread_args;
2582
2583   static DWORD WINAPI main_thread_start(LPVOID arg)
2584   {
2585     main_thread_args * args = (main_thread_args *) arg;
2586     return (DWORD)GC_WinMain(args->hInstance, args->hPrevInstance,
2587                              args->lpCmdLine, args->nShowCmd);
2588   }
2589
2590   STATIC void * GC_waitForSingleObjectInfinite(void * handle)
2591   {
2592     return (void *)(word)WaitForSingleObject((HANDLE)handle, INFINITE);
2593   }
2594
2595 # ifndef WINMAIN_THREAD_STACK_SIZE
2596 #   define WINMAIN_THREAD_STACK_SIZE 0  /* default value */
2597 # endif
2598
2599   int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
2600                      WINMAIN_LPTSTR lpCmdLine, int nShowCmd)
2601   {
2602     DWORD exit_code = 1;
2603
2604     main_thread_args args = {
2605                 hInstance, hPrevInstance, lpCmdLine, nShowCmd
2606     };
2607     HANDLE thread_h;
2608     DWORD thread_id;
2609
2610     /* initialize everything */
2611     GC_INIT();
2612
2613     /* start the main thread */
2614     thread_h = GC_CreateThread(NULL /* lpsa */,
2615                         WINMAIN_THREAD_STACK_SIZE /* ignored on WinCE */,
2616                         main_thread_start, &args, 0 /* fdwCreate */,
2617                         &thread_id);
2618
2619     if (thread_h != NULL) {
2620       if ((DWORD)(word)GC_do_blocking(GC_waitForSingleObjectInfinite,
2621                                       (void *)thread_h) == WAIT_FAILED)
2622         ABORT("WaitForSingleObject(main_thread) failed");
2623       GetExitCodeThread (thread_h, &exit_code);
2624       CloseHandle (thread_h);
2625     } else {
2626       ABORT("GC_CreateThread(main_thread) failed");
2627     }
2628
2629 #   ifdef MSWINCE
2630       GC_deinit();
2631 #   endif
2632     return (int) exit_code;
2633   }
2634
2635 #endif /* GC_WINMAIN_REDIRECT */
2636
2637 GC_INNER void GC_thr_init(void)
2638 {
2639   struct GC_stack_base sb;
2640
2641   GC_ASSERT(I_HOLD_LOCK());
2642   if (GC_thr_initialized) return;
2643
2644   GC_ASSERT((word)&GC_threads % sizeof(word) == 0);
2645 # ifdef GC_NO_THREADS_DISCOVERY
2646 #   define GC_main_thread GetCurrentThreadId()
2647 # else
2648     GC_main_thread = GetCurrentThreadId();
2649 # endif
2650   GC_thr_initialized = TRUE;
2651
2652 # ifdef CAN_HANDLE_FORK
2653     /* Prepare for forks if requested.  */
2654     if (GC_handle_fork) {
2655 #     ifdef CAN_CALL_ATFORK
2656         if (pthread_atfork(fork_prepare_proc, fork_parent_proc,
2657                            fork_child_proc) == 0) {
2658           /* Handlers successfully registered.  */
2659           GC_handle_fork = 1;
2660         } else
2661 #     endif
2662       /* else */ if (GC_handle_fork != -1)
2663         ABORT("pthread_atfork failed");
2664     }
2665 # endif
2666
2667 # ifdef WOW64_THREAD_CONTEXT_WORKAROUND
2668     /* Set isWow64 flag. */
2669     {
2670       HMODULE hK32 = GetModuleHandle(TEXT("kernel32.dll"));
2671       if (hK32) {
2672         FARPROC pfn = GetProcAddress(hK32, "IsWow64Process");
2673         if (pfn
2674             && !(*(BOOL (WINAPI*)(HANDLE, BOOL*))pfn)(GetCurrentProcess(),
2675                                                       &isWow64))
2676           isWow64 = FALSE; /* IsWow64Process failed */
2677       }
2678     }
2679 # endif
2680
2681   /* Add the initial thread, so we can stop it. */
2682   sb.mem_base = GC_stackbottom;
2683   GC_ASSERT(sb.mem_base != NULL);
2684 # ifdef IA64
2685     sb.reg_base = GC_register_stackbottom;
2686 # endif
2687
2688 # if defined(PARALLEL_MARK)
2689     {
2690       char * markers_string = GETENV("GC_MARKERS");
2691       int markers;
2692
2693       if (markers_string != NULL) {
2694         markers = atoi(markers_string);
2695         if (markers <= 0 || markers > MAX_MARKERS) {
2696           WARN("Too big or invalid number of mark threads: %" WARN_PRIdPTR
2697                "; using maximum threads\n", (signed_word)markers);
2698           markers = MAX_MARKERS;
2699         }
2700       } else {
2701 #       ifdef MSWINCE
2702           /* There is no GetProcessAffinityMask() in WinCE.     */
2703           /* GC_sysinfo is already initialized.                 */
2704           markers = (int)GC_sysinfo.dwNumberOfProcessors;
2705 #       else
2706 #         ifdef _WIN64
2707             DWORD_PTR procMask = 0;
2708             DWORD_PTR sysMask;
2709 #         else
2710             DWORD procMask = 0;
2711             DWORD sysMask;
2712 #         endif
2713           int ncpu = 0;
2714           if (
2715 #           ifdef __cplusplus
2716               GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask)
2717 #           else
2718               /* Cast args to void* for compatibility with some old SDKs. */
2719               GetProcessAffinityMask(GetCurrentProcess(),
2720                                      (void *)&procMask, (void *)&sysMask)
2721 #           endif
2722               && procMask) {
2723             do {
2724               ncpu++;
2725             } while ((procMask &= procMask - 1) != 0);
2726           }
2727           markers = ncpu;
2728 #       endif
2729 #       if defined(GC_MIN_MARKERS) && !defined(CPPCHECK)
2730           /* This is primarily for testing on systems without getenv(). */
2731           if (markers < GC_MIN_MARKERS)
2732             markers = GC_MIN_MARKERS;
2733 #       endif
2734         if (markers > MAX_MARKERS)
2735           markers = MAX_MARKERS; /* silently limit the value */
2736       }
2737       available_markers_m1 = markers - 1;
2738     }
2739
2740     /* Check whether parallel mode could be enabled.    */
2741       if (GC_win32_dll_threads || available_markers_m1 <= 0) {
2742         /* Disable parallel marking. */
2743         GC_parallel = FALSE;
2744         GC_COND_LOG_PRINTF(
2745                 "Single marker thread, turning off parallel marking\n");
2746       } else {
2747 #       ifndef GC_PTHREADS_PARAMARK
2748           /* Initialize Win32 event objects for parallel marking.       */
2749           mark_mutex_event = CreateEvent(NULL /* attrs */,
2750                                 FALSE /* isManualReset */,
2751                                 FALSE /* initialState */, NULL /* name */);
2752           builder_cv = CreateEvent(NULL /* attrs */,
2753                                 TRUE /* isManualReset */,
2754                                 FALSE /* initialState */, NULL /* name */);
2755           mark_cv = CreateEvent(NULL /* attrs */, TRUE /* isManualReset */,
2756                                 FALSE /* initialState */, NULL /* name */);
2757           if (mark_mutex_event == (HANDLE)0 || builder_cv == (HANDLE)0
2758               || mark_cv == (HANDLE)0)
2759             ABORT("CreateEvent failed");
2760 #       endif
2761       }
2762 # endif /* PARALLEL_MARK */
2763
2764   GC_ASSERT(0 == GC_lookup_thread_inner(GC_main_thread));
2765   GC_register_my_thread_inner(&sb, GC_main_thread);
2766 # undef GC_main_thread
2767 }
2768
2769 #ifdef GC_PTHREADS
2770
2771   struct start_info {
2772     void *(*start_routine)(void *);
2773     void *arg;
2774     GC_bool detached;
2775   };
2776
2777   GC_API int GC_pthread_join(pthread_t pthread_id, void **retval)
2778   {
2779     int result;
2780 #   ifndef GC_WIN32_PTHREADS
2781       GC_thread t;
2782 #   endif
2783     DCL_LOCK_STATE;
2784
2785     GC_ASSERT(!GC_win32_dll_threads);
2786 #   ifdef DEBUG_THREADS
2787       GC_log_printf("thread %p(0x%lx) is joining thread %p\n",
2788                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2789                     (long)GetCurrentThreadId(),
2790                     (void *)GC_PTHREAD_PTRVAL(pthread_id));
2791 #   endif
2792
2793     /* Thread being joined might not have registered itself yet. */
2794     /* After the join, thread id may have been recycled.         */
2795     /* FIXME: It would be better if this worked more like        */
2796     /* pthread_support.c.                                        */
2797 #   ifndef GC_WIN32_PTHREADS
2798       while ((t = GC_lookup_pthread(pthread_id)) == 0)
2799         Sleep(10);
2800 #   endif
2801     result = pthread_join(pthread_id, retval);
2802     if (0 == result) {
2803 #     ifdef GC_WIN32_PTHREADS
2804         /* pthreads-win32 and winpthreads id are unique (not recycled). */
2805         GC_thread t = GC_lookup_pthread(pthread_id);
2806         if (NULL == t) ABORT("Thread not registered");
2807 #     endif
2808
2809       LOCK();
2810       if ((t -> flags & FINISHED) != 0) {
2811         GC_delete_gc_thread_no_free(t);
2812         GC_INTERNAL_FREE(t);
2813       }
2814       UNLOCK();
2815     }
2816
2817 #   ifdef DEBUG_THREADS
2818       GC_log_printf("thread %p(0x%lx) join with thread %p %s\n",
2819                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2820                     (long)GetCurrentThreadId(),
2821                     (void *)GC_PTHREAD_PTRVAL(pthread_id),
2822                     result != 0 ? "failed" : "succeeded");
2823 #   endif
2824     return result;
2825   }
2826
2827   /* Cygwin-pthreads calls CreateThread internally, but it's not easily */
2828   /* interceptable by us..., so intercept pthread_create instead.       */
2829   GC_API int GC_pthread_create(pthread_t *new_thread,
2830                                GC_PTHREAD_CREATE_CONST pthread_attr_t *attr,
2831                                void *(*start_routine)(void *), void *arg)
2832   {
2833     int result;
2834     struct start_info * si;
2835
2836     if (!EXPECT(parallel_initialized, TRUE))
2837       GC_init_parallel();
2838              /* make sure GC is initialized (i.e. main thread is attached) */
2839     GC_ASSERT(!GC_win32_dll_threads);
2840
2841       /* This is otherwise saved only in an area mmapped by the thread  */
2842       /* library, which isn't visible to the collector.                 */
2843       si = (struct start_info *)GC_malloc_uncollectable(
2844                                                 sizeof(struct start_info));
2845       if (NULL == si)
2846         return EAGAIN;
2847
2848       si -> start_routine = start_routine;
2849       si -> arg = arg;
2850       GC_dirty(si);
2851       REACHABLE_AFTER_DIRTY(arg);
2852       if (attr != 0 &&
2853           pthread_attr_getdetachstate(attr, &si->detached)
2854           == PTHREAD_CREATE_DETACHED) {
2855         si->detached = TRUE;
2856       }
2857
2858 #     ifdef DEBUG_THREADS
2859         GC_log_printf("About to create a thread from %p(0x%lx)\n",
2860                       (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2861                       (long)GetCurrentThreadId());
2862 #     endif
2863       set_need_to_lock();
2864       result = pthread_create(new_thread, attr, GC_pthread_start, si);
2865
2866       if (result) { /* failure */
2867           GC_free(si);
2868       }
2869       return(result);
2870   }
2871
2872   STATIC void * GC_CALLBACK GC_pthread_start_inner(struct GC_stack_base *sb,
2873                                                    void * arg)
2874   {
2875     struct start_info * si = (struct start_info *)arg;
2876     void * result;
2877     void *(*start)(void *);
2878     void *start_arg;
2879     DWORD thread_id = GetCurrentThreadId();
2880     pthread_t pthread_id = pthread_self();
2881     GC_thread me;
2882     DCL_LOCK_STATE;
2883
2884 #   ifdef DEBUG_THREADS
2885       GC_log_printf("thread %p(0x%x) starting...\n",
2886                     (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id);
2887 #   endif
2888
2889     GC_ASSERT(!GC_win32_dll_threads);
2890     /* If a GC occurs before the thread is registered, that GC will     */
2891     /* ignore this thread.  That's fine, since it will block trying to  */
2892     /* acquire the allocation lock, and won't yet hold interesting      */
2893     /* pointers.                                                        */
2894     LOCK();
2895     /* We register the thread here instead of in the parent, so that    */
2896     /* we don't need to hold the allocation lock during pthread_create. */
2897     me = GC_register_my_thread_inner(sb, thread_id);
2898     SET_PTHREAD_MAP_CACHE(pthread_id, thread_id);
2899     GC_ASSERT(me != &first_thread);
2900     me -> pthread_id = pthread_id;
2901     if (si->detached) me -> flags |= DETACHED;
2902     UNLOCK();
2903
2904     start = si -> start_routine;
2905     start_arg = si -> arg;
2906
2907     GC_free(si); /* was allocated uncollectible */
2908
2909     pthread_cleanup_push(GC_thread_exit_proc, (void *)me);
2910     result = (*start)(start_arg);
2911     me -> status = result;
2912     GC_dirty(me);
2913     pthread_cleanup_pop(1);
2914
2915 #   ifdef DEBUG_THREADS
2916       GC_log_printf("thread %p(0x%x) returned from start routine\n",
2917                     (void *)GC_PTHREAD_PTRVAL(pthread_id), (int)thread_id);
2918 #   endif
2919     return(result);
2920   }
2921
2922   STATIC void * GC_pthread_start(void * arg)
2923   {
2924     return GC_call_with_stack_base(GC_pthread_start_inner, arg);
2925   }
2926
2927   STATIC void GC_thread_exit_proc(void *arg)
2928   {
2929     GC_thread me = (GC_thread)arg;
2930     DCL_LOCK_STATE;
2931
2932     GC_ASSERT(!GC_win32_dll_threads);
2933 #   ifdef DEBUG_THREADS
2934       GC_log_printf("thread %p(0x%lx) called pthread_exit()\n",
2935                     (void *)GC_PTHREAD_PTRVAL(pthread_self()),
2936                     (long)GetCurrentThreadId());
2937 #   endif
2938
2939     LOCK();
2940     GC_wait_for_gc_completion(FALSE);
2941 #   if defined(THREAD_LOCAL_ALLOC)
2942       GC_ASSERT(GC_getspecific(GC_thread_key) == &me->tlfs);
2943       GC_destroy_thread_local(&(me->tlfs));
2944 #   endif
2945     if (me -> flags & DETACHED) {
2946       GC_delete_thread(GetCurrentThreadId());
2947     } else {
2948       /* deallocate it as part of join */
2949       me -> flags |= FINISHED;
2950     }
2951 #   if defined(THREAD_LOCAL_ALLOC)
2952       /* It is required to call remove_specific defined in specific.c. */
2953       GC_remove_specific(GC_thread_key);
2954 #   endif
2955     UNLOCK();
2956   }
2957
2958 # ifndef GC_NO_PTHREAD_SIGMASK
2959     /* Win32 pthread does not support sigmask.  */
2960     /* So, nothing required here...             */
2961     GC_API int GC_pthread_sigmask(int how, const sigset_t *set,
2962                                   sigset_t *oset)
2963     {
2964       return pthread_sigmask(how, set, oset);
2965     }
2966 # endif /* !GC_NO_PTHREAD_SIGMASK */
2967
2968   GC_API int GC_pthread_detach(pthread_t thread)
2969   {
2970     int result;
2971     GC_thread t;
2972     DCL_LOCK_STATE;
2973
2974     GC_ASSERT(!GC_win32_dll_threads);
2975     /* The thread might not have registered itself yet. */
2976     /* TODO: Wait for registration of the created thread in pthread_create. */
2977     while ((t = GC_lookup_pthread(thread)) == NULL)
2978       Sleep(10);
2979     result = pthread_detach(thread);
2980     if (result == 0) {
2981       LOCK();
2982       t -> flags |= DETACHED;
2983       /* Here the pthread thread id may have been recycled. */
2984       if ((t -> flags & FINISHED) != 0) {
2985         GC_delete_gc_thread_no_free(t);
2986         GC_INTERNAL_FREE(t);
2987       }
2988       UNLOCK();
2989     }
2990     return result;
2991   }
2992
2993 #elif !defined(GC_NO_THREADS_DISCOVERY)
2994     /* We avoid acquiring locks here, since this doesn't seem to be     */
2995     /* preemptible.  This may run with an uninitialized collector, in   */
2996     /* which case we don't do much.  This implies that no threads other */
2997     /* than the main one should be created with an uninitialized        */
2998     /* collector.  (The alternative of initializing the collector here  */
2999     /* seems dangerous, since DllMain is limited in what it can do.)    */
3000
3001 # ifdef GC_INSIDE_DLL
3002     /* Export only if needed by client. */
3003     GC_API
3004 # else
3005 #   define GC_DllMain DllMain
3006 # endif
3007   BOOL WINAPI GC_DllMain(HINSTANCE inst GC_ATTR_UNUSED, ULONG reason,
3008                          LPVOID reserved GC_ATTR_UNUSED)
3009   {
3010       DWORD thread_id;
3011
3012       /* Note that GC_use_threads_discovery should be called by the     */
3013       /* client application at start-up to activate automatic thread    */
3014       /* registration (it is the default GC behavior);                  */
3015       /* to always have automatic thread registration turned on, the GC */
3016       /* should be compiled with -D GC_DISCOVER_TASK_THREADS.           */
3017       if (!GC_win32_dll_threads && parallel_initialized) return TRUE;
3018
3019       switch (reason) {
3020        case DLL_THREAD_ATTACH:
3021 #       ifdef PARALLEL_MARK
3022           /* Don't register marker threads. */
3023           if (GC_parallel) {
3024             /* We could reach here only if parallel_initialized == FALSE. */
3025             break;
3026           }
3027 #       endif
3028         /* FALLTHRU */
3029        case DLL_PROCESS_ATTACH:
3030         /* This may run with the collector uninitialized. */
3031         thread_id = GetCurrentThreadId();
3032         if (parallel_initialized && GC_main_thread != thread_id) {
3033 #         ifdef PARALLEL_MARK
3034             ABORT("Cannot initialize parallel marker from DllMain");
3035 #         else
3036             struct GC_stack_base sb;
3037             /* Don't lock here. */
3038 #           ifdef GC_ASSERTIONS
3039               int sb_result =
3040 #           endif
3041                         GC_get_stack_base(&sb);
3042             GC_ASSERT(sb_result == GC_SUCCESS);
3043             GC_register_my_thread_inner(&sb, thread_id);
3044 #         endif
3045         } /* o.w. we already did it during GC_thr_init, called by GC_init */
3046         break;
3047
3048        case DLL_THREAD_DETACH:
3049         /* We are hopefully running in the context of the exiting thread. */
3050         GC_ASSERT(parallel_initialized);
3051         if (GC_win32_dll_threads) {
3052           GC_delete_thread(GetCurrentThreadId());
3053         }
3054         break;
3055
3056        case DLL_PROCESS_DETACH:
3057         if (GC_win32_dll_threads) {
3058           int i;
3059           int my_max = (int)GC_get_max_thread_index();
3060
3061           for (i = 0; i <= my_max; ++i) {
3062            if (AO_load(&(dll_thread_table[i].tm.in_use)))
3063              GC_delete_gc_thread_no_free(&dll_thread_table[i]);
3064           }
3065           GC_deinit();
3066         }
3067         break;
3068       }
3069       return TRUE;
3070   }
3071 #endif /* !GC_NO_THREADS_DISCOVERY && !GC_PTHREADS */
3072
3073 /* Perform all initializations, including those that    */
3074 /* may require allocation.                              */
3075 /* Called without allocation lock.                      */
3076 /* Must be called before a second thread is created.    */
3077 GC_INNER void GC_init_parallel(void)
3078 {
3079 # if defined(THREAD_LOCAL_ALLOC)
3080     GC_thread me;
3081     DCL_LOCK_STATE;
3082 # endif
3083
3084   if (parallel_initialized) return;
3085   parallel_initialized = TRUE;
3086   /* GC_init() calls us back, so set flag first.      */
3087
3088   if (!GC_is_initialized) GC_init();
3089 # if defined(CPPCHECK) && !defined(GC_NO_THREADS_DISCOVERY)
3090     GC_noop1((word)&GC_DllMain);
3091 # endif
3092   if (GC_win32_dll_threads) {
3093     set_need_to_lock();
3094         /* Cannot intercept thread creation.  Hence we don't know if    */
3095         /* other threads exist.  However, client is not allowed to      */
3096         /* create other threads before collector initialization.        */
3097         /* Thus it's OK not to lock before this.                        */
3098   }
3099   /* Initialize thread local free lists if used.        */
3100 # if defined(THREAD_LOCAL_ALLOC)
3101     LOCK();
3102     me = GC_lookup_thread_inner(GetCurrentThreadId());
3103     CHECK_LOOKUP_MY_THREAD(me);
3104     GC_init_thread_local(&me->tlfs);
3105     UNLOCK();
3106 # endif
3107 }
3108
3109 #if defined(USE_PTHREAD_LOCKS)
3110   /* Support for pthread locking code.          */
3111   /* pthread_mutex_trylock may not win here,    */
3112   /* due to builtin support for spinning first? */
3113
3114   GC_INNER void GC_lock(void)
3115   {
3116     pthread_mutex_lock(&GC_allocate_ml);
3117   }
3118 #endif /* USE_PTHREAD_LOCKS */
3119
3120 #if defined(THREAD_LOCAL_ALLOC)
3121
3122   /* Add thread-local allocation support.  VC++ uses __declspec(thread).  */
3123
3124   /* We must explicitly mark ptrfree and gcj free lists, since the free   */
3125   /* list links wouldn't otherwise be found.  We also set them in the     */
3126   /* normal free lists, since that involves touching less memory than if  */
3127   /* we scanned them normally.                                            */
3128   GC_INNER void GC_mark_thread_local_free_lists(void)
3129   {
3130     int i;
3131     GC_thread p;
3132
3133     for (i = 0; i < THREAD_TABLE_SZ; ++i) {
3134       for (p = GC_threads[i]; 0 != p; p = p -> tm.next) {
3135         if (!KNOWN_FINISHED(p)) {
3136 #         ifdef DEBUG_THREADS
3137             GC_log_printf("Marking thread locals for 0x%x\n", (int)p -> id);
3138 #         endif
3139           GC_mark_thread_local_fls_for(&(p->tlfs));
3140         }
3141       }
3142     }
3143   }
3144
3145 # if defined(GC_ASSERTIONS)
3146     /* Check that all thread-local free-lists are completely marked.    */
3147     /* also check that thread-specific-data structures are marked.      */
3148     void GC_check_tls(void)
3149     {
3150         int i;
3151         GC_thread p;
3152
3153         for (i = 0; i < THREAD_TABLE_SZ; ++i) {
3154           for (p = GC_threads[i]; 0 != p; p = p -> tm.next) {
3155             if (!KNOWN_FINISHED(p))
3156               GC_check_tls_for(&(p->tlfs));
3157           }
3158         }
3159 #       if defined(USE_CUSTOM_SPECIFIC)
3160           if (GC_thread_key != 0)
3161             GC_check_tsd_marks(GC_thread_key);
3162 #       endif
3163     }
3164 # endif /* GC_ASSERTIONS */
3165
3166 #endif /* THREAD_LOCAL_ALLOC ... */
3167
3168 # ifndef GC_NO_THREAD_REDIRECTS
3169     /* Restore thread calls redirection.        */
3170 #   define CreateThread GC_CreateThread
3171 #   define ExitThread GC_ExitThread
3172 #   undef _beginthreadex
3173 #   define _beginthreadex GC_beginthreadex
3174 #   undef _endthreadex
3175 #   define _endthreadex GC_endthreadex
3176 # endif /* !GC_NO_THREAD_REDIRECTS */
3177
3178 #endif /* GC_WIN32_THREADS */